微信支付
微信订单的信息仅存在于支付阶段
微信支付API参考 (opens in a new tab)
微信支付nodejs版sdk文档 (opens in a new tab)
微信支付模式
按商户角色分: 直连模式 和 服务商模式, 其中服务商模式可调用分账功能 (opens in a new tab)
按客户端种类分: JSAPI支付 & APP支付 & H5支付 & Native支付 & 小程序支付 & 合单支付 & 付款码支付V2 & 刷脸支付
微信支付流程
支付流程
生成预付单 -> 调起支付 -> 微信返回支付结果 -> 查询判断支付结果
- 表达: 时序图, 流程图, 状态图
前端通信
- 公众号、小程序、APP支付
- 前端返回“用户取消”的情况,则订单状态保持未支付状态,并提示用户支付未完成。
- 前端返回“成功”或“报错”的情况,商户需要调用商户查单接口,确认订单状态。
后台同步微信订单
- 回调通知
- 定时轮询: 定时任务每隔30秒启动一次,找出最近10分钟内创建并且未支付的订单,调用《微信支付查单接口》核实订单状态。系统记录订单查询的次数,在10次查询之后状态还是未支付成功,则停止后续查询,并调用《关单接口》关闭订单。(轮询时间间隔和次数,商户可以根据自身业务场景灵活设置)
- T+1日对账
- 订单匹配成功,并且状态都是支付成功:正常情况,对账成功。
- 订单匹配成功,但是商户侧状态非支付成功:商户根据自身业务情况,决定是否把订单状态更新为支付成功并给用户发货,或者是给用户发起退款。
- 订单匹配失败,对账单中的单号在商户系统未找到记录:异常情况,需要商户排查系统是否出现数据异常。
- 订单匹配失败,商户系统中成功的订单在对账单中未找到记录:异常情况,需要商户排查是否订单处理逻辑有bug。
微信支付安全
实现方式
- 端点鉴别&完整性: 请求接口时进行商户私钥签名, 得到返回值时用微信平台公钥去验证微信平台的签名。
- 保密性
- 接口级别的保密: 需对平台证书下载接口的返回值以及回调接口的请求值通过
AES-256-GCM
对称加密算法用商户的APIv3密钥
进行解密 - 字段级别的保密: 需对敏感信息字段(如用户的住址、银行卡号、手机号码等)通过
RSA公钥加解密
算法使用微信平台证书的公钥进行加解密。
- 接口级别的保密: 需对平台证书下载接口的返回值以及回调接口的请求值通过
签名构造
每个支付接口的调用需提供 认证类型 (目前为WECHATPAY2-SHA256-RSA2048) & 签名信息 附加在Authorization
头中, 格式为Authorization: 认证类型 签名信息
, 其中签名信息由 mchid="<商户号>",serial_no="<商户API证书序列号>",nonce_str="<请求随机串>",timestamp="<时间戳>",signature="<签名值>"
构成, 而 签名值 又由
HTTP请求方法\n
URL\n
请求时间戳\n
请求随机串\n
请求报文主体\n
签名串 经由SHA256
散列加密后, 再经过RSA2048
算法使用 商户API私钥 进行加密, 最后进行Base64
编码得到。
验证签名
通过https://api.mch.weixin.qq.com/v3/certificates
接口下载微信 平台证书 , 从中得到 公钥 , 从HTTP头中获取Wechatpay-Timestamp
时间戳与Wechatpay-Nonce
随机串头部, 并构造签名串
应答时间戳\n
应答随机串\n
应答报文主体\n
, 在Wechatpay-Signature
头中获得签名值, 通过Base64
解码以及平台证书的公钥解密后比对与签名串是否相同即可。
加解密基本概念
- 对称加密算法: AES, DES, 3DES
- 非对称加密算法: RSA, ECC, DSA
- 散列加密算法: MD5, SHA1, SHA256, SHA512, HMAC
- 构造签名基本流程: 签名串 -> 散列加密签名串 -> 私钥加密 -> base64编码 -> 签名
- 验签基本流程: base64解码 -> 公钥解密 -> 散列加密的签名串, 签名串 -> 散列加密的签名串, 散列加密的签名串