尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

微信小程序支付与浏览器支付怎么区分?JSAPI和H5全流程对比

发布时间:2026/9/28 16:25:29

资讯中心
01
ARTICLE

微信小程序支付与浏览器支付怎么区分?JSAPI和H5全流程对比

微信小程序支付与浏览器支付怎么区分?JSAPI和H5全流程对比
做了好几年微信生态开发微信小程序支付和微信浏览器支付这两个词几乎每次做商城类项目都会被一起提出来。我自己的体会是大部分新手踩坑不是因为代码写错而是压根没搞清楚这两者到底是不是同一个东西。先说结论小程序支付和微信内置浏览器里的网页支付本质都叫 JSAPI 支付走的是同一套下单逻辑而外部手机浏览器里的支付才是真正独立的 H5 支付。三种场景的调起方式、参数要件、域名配置各不相同把它们当成一个东西来开发轻则控制台报 signature 错误重则线上订单全部卡死。这篇文章我打算把三个场景完整拆一遍从商户号、证书、APIv3 密钥这些前置配置到统一下单、前端调起、回调验签最后落到老生常谈的签名错误、回调丢单排查顺带聊聊 uniapp 多端支付和支付网关设计。无论你是刚接手支付功能的后端还是被微信公众号里付不了款折腾的前端都可以直接对照着排查。1. 微信小程序支付和微信浏览器支付先分清这三件事1.1 小程序支付和公众号网页支付其实都是 JSAPI微信支付的官方文档里有一个接口叫JSAPI 支付它的定位是在微信客户端内的支付场景。它覆盖了两大块微信小程序内通过wx.requestPayment调起收银台微信公众号服务号内的 H5 页面通过微信 JS-SDK 的chooseWXPay旧版是WeixinJSBridge.invoke(getBrandWCPayRequest)调起收银台。这两块的共同点是必须拿到用户的 openid。小程序里可以用wx.login换取 openid公众号网页里要通过 OAuth2 网页授权获取 openid。下单接口同样是/v3/pay/transactions/jsapiAPIv3或/pay/unifiedorderAPIv2返回的prepay_id是前端调起支付的唯一凭证。很多第一次接触支付的同学会困惑我小程序里都拿到 code 了为什么还要传 openid原因很简单微信支付是按用户维度结算和风控的服务端需要知道这单是哪个人付的钱所以下单请求里payer.openid是必填项。1.2 外部浏览器里的 H5 支付才是真正独立的场景当用户用Safari、Chrome、华为浏览器等手机浏览器打开你的商城网页时微信支付提供了另一种方案叫H5 支付也常被叫 MWEB 支付。它的核心特征是不需要 openid不需要用户登录微信授权下单接口是/v3/pay/transactions/h5APIv3返回一个h5_url网页跳转到h5_url后会拉起微信客户端收银台完成支付。从流程上看H5 支付更像把人带到微信里付钱再跳回来。它必须满足两个硬性条件商户号开通 H5 支付权限并且支付域名已完成 ICP 备案。很多朋友遇到外部浏览器打开网页点支付没反应十有八九是域名没有在商户平台配置成 H5 支付域名。我把三个场景的关键差异整理成表格方便你对照场景接口核心前置条件调起方式是否需要openid微信小程序支付/v3/pay/transactions/jsapi小程序 AppID 已绑定商户号wx.requestPayment必须微信内置浏览器网页支付公众号支付/v3/pay/transactions/jsapi服务号 AppID、JS接口安全域名、OAuth2授权wx.chooseWXPay/WeixinJSBridge必须外部浏览器 H5 支付/v3/pay/transactions/h5H5支付域名ICP备案跳转h5_url不需要记住这张表后面所有代码和配置都不会跑偏。2. 支付接入前先把四把钥匙配齐2.1 商户号、AppID、APIv3 和证书各管什么事微信支付APIv3的接入体系里有几个概念特别容易混淆我见过不少人在这一步就开始懵商户号mchid你在微信商户平台申请的收款账户所有资金都进这个账户所有接口请求都带着它。AppID小程序的 AppID 或者公众号服务号的 AppID。它代表谁在收款商户号和 AppID 必须完成关联绑定否则下单接口会直接报APPID_MCHID_NOT_MATCH。APIv3 密钥一串 32 字符的密钥主要用来解密回调通知里的敏感数据AES-256-GCM 解密。它不是签名密钥千万别拿它去做 RSA 签名。商户 API 证书包含apiclient_cert.pem证书和apiclient_key.pem私钥。商户发请求时的签名用的是这把私钥。微信支付平台证书用于验证微信发给你的回调通知的签名。我举个例子帮你理解商户 API 证书相当于你家的门禁卡你进门发请求时要用它证明身份微信支付平台证书相当于物业的工牌物业来敲门发回调时你要看它的工牌确认身份APIv3 密钥则相当于家里保险柜的密码物业送来的文件是加密的得用保险柜密码才能打开看。很多用户态签名 signature 错误的排查到最后发现是配置层面搞混了有人把 APIv3 密钥填到了私钥的位置有人把证书序列号填成了商户号。这些错误在签名计算时必然失败。2.2 申请流程与配置易错点规范流程大概是用营业执照申请微信支付商户号完成对公账户验证在商户平台产品中心开通对应的支付产品JSAPI 支付 / H5 支付在APPID 账号管理里关联小程序或公众号 AppID在账户中心 - API 安全里设置 APIv3 密钥、申请 API 证书、下载微信支付平台证书在开发配置里配置支付目录和 H5 支付域名。这套流程里我踩过的坑是API 证书有效期只有一年到期后没有及时续期线上接口突然全部签名失败。虽然日志里错误很明显证书过期但当时第一反应是查代码绕了很大一圈才发现是证书过期。所以建议在日历上设立证书到期提醒或者做一个每周定时任务去检查证书有效期。另外还有一个易错点APIv3 密钥一旦设置微信不会明文展示只能重置。如果项目组多人协作一定要把密钥放到统一的配置中心或环境变量里不要写在代码仓库否则离职交接时你根本拿不回密钥只能重置并同步更新所有环境。下面是我比较推荐的配置清单配置项获取位置用途易错点mchid商户号商户平台首页所有接口必传填成 AppIDAppID小程序/公众号后台标识应用主体和小程序 AppID 混淆APIv3 密钥商户平台自主设置AES-256-GCM 解密回调误用于签名商户API证书私钥API安全-证书管理RSA-SHA256 请求签名泄露或过期平台证书序列号API安全-平台证书回调验签与商户证书混淆支付目录/H5域名产品中心-开发配置限制支付发起来源漏配、配错域名3. 微信小程序支付完整落地从下单到回调3.1 后端调 JSAPI 下单接口小程序支付的前端其实非常轻真正复杂的是后端。后端核心工作只有一个调微信支付的统一下单接口拿到prepay_id。APIv3 的下单接口地址是POST https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi请求体大概是这样的以 PHP 数组转 JSON 为例{ appid: wx1234567890abcdef, mchid: 1900001234, description: 测试商品-微信小程序支付, out_trade_no: 20250601123000123, notify_url: https://api.example.com/wechat/pay/notify, amount: { total: 100, currency: CNY }, payer: { openid: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o } }这里有个很多新手忽略的重点金额单位是分而且是整数。total: 100代表 1 元不是 0.1 元。如果前端传的是元后端没有乘以 100用户付 1 元商品微信会扣 1 分钱这种线上事故非常尴尬。我在开发时一般会在下单接口做一道金额格式校验// 前端传的金额单位是元最多两位小数后端统一转分 $total (int) round((float) $amount * 100); if ($total 0 || $total 1000000000) { throw new \Exception(金额不合法); }请求而不只是 JSON 对了就行APIv3 要求每个请求都要在 Header 里带上签名。这是整个接入流程里最容易让人崩溃的部分。签名规范如下构造签名串格式是{HTTP请求方法}\n{URL}\n{请求时间戳}\n{请求随机串}\n{请求报文主体}\n以我们上面这个 JSAPI 下单请求为例它实际是这样POST /v3/pay/transactions/jsapi 1727088000 5K8264ILTKCH16CQ2502SI8ZNMTM67VS {appid:wx1234567890abcdef,mchid:1900001234,...}用商户 API 私钥对这个签名串做 SHA256withRSA 签名结果 Base64 编码组装Authorization请求头WECHATPAY2-SHA256-RSA2048 mchid1900001234,nonce_str5K8264ILTKCH16CQ2502SI8ZNMTM67VS,signatureBASE64签名串,timestamp1727088000,serial_no1000AABBCCDD这里面的serial_no是商户 API 证书的序列号不是商户号我见过不少人把mchid当serial_no传微信直接就报签名错误。我的 PHP 签名函数一般长这样private function sign(string $message, string $privateKeyPath): string { $privateKey openssl_pkey_get_private(file_get_contents($privateKeyPath)); if (!$privateKey) { throw new \RuntimeException(私钥读取失败); } openssl_sign($message, $signature, $privateKey, OPENSSL_ALGO_SHA256); return base64_encode($signature); } private function buildAuthorization(string $method, string $urlPath, string $body): string { $timestamp time(); $nonce bin2hex(random_bytes(16)); $message $method . \n . $urlPath . \n . $timestamp . \n . $nonce . \n . $body . \n; $signature $this-sign($message, config(pay.private_key_path)); return sprintf( WECHATPAY2-SHA256-RSA2048 mchid%s,nonce_str%s,signature%s,timestamp%d,serial_no%s, config(pay.mchid), $nonce, $signature, $timestamp, config(pay.serial_no) ); }下单成功之后微信返回的响应里有两个核心字段prepay_id和expires_in。prepay_id就是一个支付订单的凭证前端调起收银台全靠它有效期大概 2 小时。3.2 前端 wx.requestPayment 调起支付后端把prepay_id返回给小程序前端之后前端需要做一件事用预支付 ID 组装调起参数并再次签名。有些团队会把一步直接在后端把paySign也算好前端只负责wx.requestPayment。前端代码大致是wx.requestPayment({ timeStamp: 1727088000, nonceStr: 5K8264ILTKCH16CQ2502SI8ZNMTM67VS, package: prepay_idwx201410272009395522572a690389285100, signType: RSA, paySign: 签名值, success: function (res) { // 支付成功但最终要以服务端回调为准 }, fail: function (err) { // 用户取消或支付失败 } })这里最容易踩的坑是paySign 的签名串与统一下单的签名串不一样。后端统一下单时签名的是请求报文POST\n/v3/pay/transactions/jsapi\n...而在前端调起支付时paySign 签名的是下面这段字符串注意末尾的换行appId timeStamp nonceStr package signType每行一个参数共五行末尾各带一个\n。package的值要写成prepay_idxxx的完整形式signType填RSA。很多项目在统一下单签名成功后直接拿统一下单的签名逻辑去算 paySign怎么调都提示支付参数不正确就是忽略了这两处签名串构造的差异。小程序端调起支付后前端的 success 回调只能作为 UI 提示真正确定订单是否支付成功必须以服务端收到微信回调通知为准。否则用户可能支付成功了但因为微信回调延迟或丢失订单状态还停留在待支付状态。3.3 notify_url 回调验签与解密微信支付回调通知是整个流程的闭环环节。微信在用户付款成功后会往你下单时填的notify_url发一个 POST 请求请求体大概是这样{ id: EV-20250601123000, create_time: 2025-06-01T12:30:0008:00, resource_type: encrypt-resource, event_type: TRANSACTION.SUCCESS, resource: { original_type: transaction, algorithm: AEAD_AES_256_GCM, ciphertext: 加密后的报文数据, associated_data: transaction, nonce: C6D2F3D9E5A1B4 } }回调处理必须做两件套验签和解密。验签的目的是确认这个回调真的是微信发来的不是别人伪造的。微信会把请求签名放在 HTTP 头里比如 APIv3 下是Wechatpay-Signature、Wechatpay-Timestamp、Wechatpay-Nonce、Wechatpay-Serial。你需要用微信支付平台证书根据Wechatpay-Serial找到对应证书去验签。验签通过后再用 APIv3 密钥解密密文。AES-256-GCM 解密需要使用ciphertext、nonce、associated_data三个参数解密出来的才是真正的订单数据{ out_trade_no: 20250601123000123, transaction_id: 4200001234202506011000001234, trade_state: SUCCESS, amount: { total: 100, payer_total: 100, currency: CNY }, success_time: 2025-06-01T12:30:0108:00 }我把验签和解密的 PHP 核心代码放在一起// 读取请求头和原始body $body file_get_contents(php://input); $headers getallheaders(); $timestamp $headers[Wechatpay-Timestamp]; $nonce $headers[Wechatpay-Nonce]; $signature $headers[Wechatpay-Signature]; $serial $headers[Wechatpay-Serial]; // 1. 构造验签原文注意格式时间戳\n随机串\n请求体\n $message $timestamp . \n . $nonce . \n . $body . \n; // 2. 用微信支付平台证书公钥验签 $platformCert file_get_contents(config(pay.platform_cert_path)); $verified openssl_verify($message, base64_decode($signature), $platformCert, OPENSSL_ALGO_SHA256); if ($verified ! 1) { // 验签失败直接记录日志并返回非200状态码 http_response_code(401); exit; } // 3. 解密 resource $json json_decode($body, true); $resource $json[resource]; $apiV3Key config(pay.api_v3_key); $decrypted openssl_decrypt( base64_decode($resource[ciphertext]), aes-256-gcm, $apiV3Key, OPENSSL_RAW_DATA, $resource[nonce], $resource[associated_data] ); // $decrypted 就是真实的订单JSON $payResult json_decode($decrypted, true); // 4. 业务处理幂等校验 更新订单 给微信返回成功 if ($payResult[trade_state] SUCCESS) { // 判断 out_trade_no 是否已处理防止重复回调 // 更新订单状态、加余额、发货等 } // 5. 返回微信规定格式response code 200, body: {code:SUCCESS,message:成功} http_response_code(200); echo {code:SUCCESS,message:成功};很多人处理回调时会犯一个错误拿到订单后直接改金额。正确做法是拿回调里的amount.total与你自己订单表里的应付金额比对如果不一致说明被篡改或者业务异常必须记录下来人工处理。3.4 完整接入时的关键顺序标准的小程序支付流程用文字描述是这样的小程序前端调用wx.login拿 code后端拿 code 换 openid前端把商品信息发给后端创建订单后端校验库存和金额调用 JSAPI 下单接口拿prepay_id后端计算出paySign把timeStamp/nonceStr/package/signType/paySign返回给前端前端调wx.requestPayment用户输密码/指纹完成支付微信异步通知后端notify_url后端验签、解密、更新订单状态前端在success回调里提示支付成功并向后端查询订单状态刷新页面。这个顺序里步骤 6 和步骤 7 在时间上几乎同时发生但前端 success 不一定是支付成功的最终依据。我在项目里会额外提供一个查询订单状态的接口前端在支付回调成功后主动轮询一次避免用户在支付成功后页面还显示待付款。4. 微信浏览器支付内置浏览器和外部浏览器两套玩法4.1 微信内置浏览器里的公众号支付如果你在微信里打开一个网页比如公众号菜单里的商城这个网页要支付走的还是 JSAPI 支付。它和小程序支付最大的区别是openid 获取方式不一样。小程序里获取 openid 靠wx.login 后端code2Session公众号网页里获取 openid 必须走 OAuth2 网页授权前端跳转到微信授权 URLhttps://open.weixin.qq.com/connect/oauth2/authorize?appidAPPIDredirect_uriREDIRECT_URIresponse_typecodescopesnsapi_basestateSTATE#wechat_redirect授权后回调你的redirect_uri带上code后端用code请求https://api.weixin.qq.com/sns/oauth2/access_token?appidAPPIDsecretSECRETcodeCODEgrant_typeauthorization_code拿到 openid。拿到 openid 之后下单逻辑跟小程序完全一致仍然是/v3/pay/transactions/jsapi。区别在调起支付这一步公众号网页调起收银台需要先引入微信 JS-SDK做wx.config注入配置然后调用wx.chooseWXPay({ timestamp: 1727088000, nonceStr: 5K8264ILTKCH16CQ2502SI8ZNMTM67VS, package: prepay_idwx201410272009395522572a690389285100, signType: RSA, paySign: 签名值, success: function (res) {} });这里有两个细节要特别提醒wx.chooseWXPay参数名是timestamp小写开头而小程序wx.requestPayment是timeStamp驼峰。如果前后端共用一套参数生成逻辑很可能会因为键名不同导致调起失败或签名串不一致。另外wx.config需要用到公众号的jsapi_ticket后端要封装一个获取 ticket 并缓存的接口。签名用的nonceStr和timestamp与支付参数无关是 JS-SDK 自己的签名很多团队会在这里二次懵。4.2 外部浏览器里的 H5 支付如果你的网页被别人在浏览器里打开比如从百度、QQ、抖音等 App 的浏览器跳过来这时候就不能用 JSAPI 支付了必须走 H5 支付。H5 支付的核心接口是POST https://api.mch.weixin.qq.com/v3/pay/transactions/h5请求体与 JSAPI 下单类似但需要额外传scene_info{ appid: wx1234567890abcdef, mchid: 1900001234, description: 测试商品-浏览器支付, out_trade_no: 20250601123000130, notify_url: https://api.example.com/wechat/pay/notify, amount: { total: 100, currency: CNY }, scene_info: { payer_client_ip: 14.23.150.211, h5_info: { type: Wap, app_name: xx商城, wap_url: https://mall.example.com } } }下单成功后返回{ h5_url: https://wx.tenpay.com/cgi-bin/mmpayweb/...?token... }后端拿到h5_url后前端把这个链接塞进location.href或window.location.replace()用户会先跳到一个中间页然后自动拉起微信 App 收银台。支付完成后会重新跳回你的网页通过redirect_url参数控制需要在 H5 支付配置里设置。我特别想提醒H5 支付的h5_url不能在微信内置浏览器里直接跳转。如果你把 H5 支付的链接发给用户用户在微信里点开微信会拦截并提示请在外部浏览器打开。因为微信不希望用户在微信内部用 H5 拉起再跳转那样会绕开 JSAPI 的授权流程。所以在做 H5 支付前服务端要注意判断来源如果检测到MicroMessenger的 UA就引导用户使用公众号支付或复制链接到外部浏览器。4.3 域名备案、UA 判定与常见配置H5 支付开通后必须在商户平台产品中心 - H5支付 - 开发配置里添加H5 支付域名这个域名必须已完成 ICP 备案且是当前下单请求的 referer 域名。我在实践中的经验是平台对域名的校验非常严格如果请求里的Referer域名和配置不一致会直接报H5_REFERER_NOT_ALLOWED。开发调试时怎么判断当前页面是不是在微信内置浏览器前端可以这样检测 UAfunction isWechatBrowser() { var ua navigator.userAgent.toLowerCase(); return ua.indexOf(micromessenger) ! -1; }但要注意UA 只是浏览器自报家门可以被修改。服务端判断是否来自微信内置浏览器不能只信 UA。比如做支付时我更建议用微信提供的JS-SDK能力探测或者在后端维护一份可信 UA 特征 来源 IP 请求路径的综合判断。网上有些人讨论通过改 UA 来让网页误以为自己在微信里这种方法在支付场景下不推荐也不可靠——微信支付的风控会校验 referer、订单行为、支付环境等多维数据伪装 UA 很容易被判定为风险交易反而影响正常用户。5. 常见问题与排查技巧实录5.1 用户态签名 signature 错误这个报错是微信支付开发中出镜率最高的问题没有之一。它本质是微信验签没过常见原因有三个原因一签名串构造错误。少了换行符、多了空格、URL 写了带域名的完整地址而要求只写路径都会导致签名不一致。正确格式我再强调一遍方法\nURL路径\n时间戳\n随机串\n请求体\n每个\n都不能少。原因二使用的密钥不对。请求签名必须用商户 API 证书私钥apiclient_key.pem不是 APIv3 密钥。如果你误把 APIv3 密钥当成签名私钥生成的签名必然验签失败。原因三时间戳偏差。微信要求请求时间戳与服务器时间偏差不能超过 5 分钟如果你服务器时间不准比如云主机时区没设对也会报签名错误。排查时可以先把签名串打印出来放到微信官方提供的签名校验工具里比对一般很快能定位是哪一环错了。5.2 支付目录、域名白名单导致调不起小程序支付常见的报错是url not in domain list这表示小程序后台的 request 合法域名没有加上你的 API 域名。公众号网页支付常见的报错是config:invalid signature或chooseWXPay:fail这时候优先检查公众号的JS 接口安全域名是否配置正确。有一个配置细节JS 接口安全域名填写的是域名不需要带https://也不带路径。比如你接口是https://api.example.com/wechat那域名配置为api.example.com。我在项目里见过前端把完整 URL 填进去结果怎么调都无效。另外微信开发者工具里的不校验合法域名只在开发阶段可用真机预览时不会生效。测试小程序支付最好用真机扫码预览否则你会遇到开发者工具里一切正常手机上全部失败的尴尬。5.3 回调丢失与订单状态不同步回调丢失是支付系统里最考验工程素养的问题。微信会重试通知但重试间隔会拉长。如果业务系统没有做好幂等且回调又偶尔延迟订单状态就会不一致。我在项目里的做法是查询接口兜底。用户支付成功后前端调用查询订单状态接口如果该接口发现订单还是待支付后端主动调微信的查单接口/v3/pay/transactions/out-trade-no/{out_trade_no}去确认最终状态。这套机制能覆盖回调延迟、回调丢失、回调被防火墙拦截等大部分情况。回调处理还有一个常见坑服务器防火墙或网关把微信回调 IP 拦截了。腾讯云的服务器默认安全组一般没问题但如果你自建机房或有严格的白名单策略一定要把微信支付回调的 IP 段放行。这个问题的典型表现是订单已经支付用户也看到扣款了但系统一直显示待付款。5.4 金额、openid、iOS 兼容等细节坑金额单位微信支付所有金额都是分用整数表示。如果你用浮点数存金额1.1 * 100可能等于110.00000000000001入库前记得取整。openid 不匹配小程序 AppID 和公众号 AppID 不同用公众号网页授权拿到的 openid 去小程序下单会报payer_openid_error。iOS 虚拟商品限制小程序里卖虚拟商品会员、课程、道具等iOS 端不允许使用微信支付苹果要求走 IAP 内购。如果硬上微信支付审核会被驳回严重时小程序会被下架。这块属于平台合规问题立项阶段就要确认业务属性。iOS 网络请求失败率偏高小程序在 iOS 机型上偶发网络请求失败根据我看到的分析有一部分是wx.request使用了 HTTP/2、IPv6 等特性老版本微信客户端兼容不好可以尝试让后端支持 HTTP/1.1 并检查 TLS 配置同时设置合理的超时重试策略。下面是一张排查速查表建议收藏现象可能原因优先排查项下单报签名错误签名串错、密钥错、时间偏差签名工具比对签名串前端调起支付无反应参数键名错、paySign算错核对 timeStamp/timestamp小程序报 url not in domain域名白名单没配置小程序后台 request 合法域名公众号 config invalid signatureJS接口安全域名或jsapi_ticket错误检查域名配置与ticket缓存H5 支付被拦截域名未备案/未配置/H5场景限制商户平台H5支付域名配置回调收不到防火墙拦截、回调地址不可外网访问先模拟POST到notify_url6. 多端支付与支付网关设计的一点思路6.1 uniapp / App / 小程序 / H5 支付参数为什么不能通用很多用 uniapp 开发的朋友会问我同一套代码打包成 App、H5 和小程序支付流程和参数是否相同答案很明确不相同。uniapp 里uni.requestPayment确实做了一层抽象但它内部实现取决于编译到哪个平台编译到微信小程序时它调用的是wx.requestPayment参数就是上面说的timeStamp/nonceStr/package/paySign编译到 App 时它走的是 App 支付 SDK比如微信 App 支付或支付宝 App 支付参数是provider/orderInfo需要后端生成 App 端的订单串编译到 H5 时如果是微信浏览器走 JSAPI如果是外部浏览器走 H5 支付。所以你在后端设计接口时不能让前端把支付参数写死而是要根据端类型返回不同的支付参数结构。这也是为什么前端抱怨为什么我 H5 端和 App 端支付代码不能复用的原因——底层协议完全不同。6.2 微信支付与支付宝支付的抽象对齐很多项目不止接入微信支付还要接入支付宝支付。支付宝的接口风格和微信差别很大支付宝用的是app_id sign_type charset timestamp version method biz_content这种公共参数 业务参数的形式签名是 RSA2SHA256withRSA微信 APIv3 则是 restful 风格 Authorization 头签名。它们不是同一个套路但你可以在业务层做对齐。比如定义一个统一的创建支付订单接口$request [ channel wx_jsapi, // 渠道标识wx_jsapi / wx_h5 / alipay_wap order_no 20250601123000123, amount 100, subject xx商品, openid oUpF8uMuAJO_M2pxb1Q9zNjWeS6o // 可能为空 ];后端根据channel分发给不同的渠道适配器每个适配器输出统一的响应结构pay_params前端支付参数、pay_url跳转链接、prepay_id等。6.3 一个简单支付网关的路由设计如果你的项目以后要扩展多个支付渠道我建议从第一天就把支付逻辑抽象成网关。一个最小的支付网关至少有四个核心能力下单pay、回调notify、查单query、退款refund。我简单画一下路由的表结构设计不是让你照抄而是提供思路能力统一接口内部派发下单/api/pay/create根据 channel 调微信JSAPI / 微信H5 / 支付宝回调/api/pay/notify/{channel}验签后转发给业务处理器查单/api/pay/query分别调微信查单、支付宝查单退款/api/pay/refund分别调微信退款、支付宝退款这个抽象带来的好处是业务方永远只对着你自己的四个接口不需要关心微信和支付宝的签名差异、接口差异。每次新渠道接入只需要新增一个 adapter业务代码不动。我在实际项目里还加了一层支付渠道配置表把商户号、AppID、证书路径、密钥都存成配置方便多商户场景下动态切换。常见的小程序知识付费平台就是靠这张配置表去支持平台方小程序里一个个子商户的支付能力——虽然那会涉及分账但配置思路是通用的。我个人做了多年代码后最大的体会是支付接入难不在调通而在想清楚。你愿意花半小时把场景归类清楚、把签名原理弄明白后面调接口就快得多。上面这些坑我基本都踩过一遍把它们写下来是希望你在做微信小程序支付和微信浏览器支付的时候少走几步冤枉路。真要再遇到诡异的签名问题先别急着改代码把签名串打印出来不信你对不出来。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。