微信支付 V3 版本

v2 与 v3 区别

相较于微信支付API-v2,主要区别是:

  • 遵循统一的Restful的设计风格
  • 使用JSON作为数据交互的格式,不再使用XML
  • 使用基于非对称密钥的SHA256-RSA的数字签名算法,不再使用MD5或HMAC-SHA256
  • 不再要求HTTPS客户端证书
  • 使用AES-256-GCM,对回调中的关键信息进行加密保护

更多证书和签名的详细内容请参官方文档 WeChatPay-API-v3微信支付 V3 版本 - 图1

API密钥设置

API密钥的详细内容请参见:API证书及密钥微信支付 V3 版本 - 图2

下载API证书

请在商户平台下载证书。具体操作请参见:如何获取API证书微信支付 V3 版本 - 图3

获取证书序列号

需要安装 x509 依赖

  1. yarn add x509
  1. const cert = x509.parseCert(config.certPath)
  2. console.log(`证书序列号:${cert.serial}`)

如何验证序列号

构建 Authorization

  1. PayKit.buildAuthorization(method: RequestMethod, urlSuffix: string, mchId: string, serialNo: string, key: Buffer, body: string)

参数说明

  • method 请求方法 RequestMethod
  • urlSuffix 可通过 WxApiType 来获取,URL挂载参数需要自行拼接
  • mchId 商户Id
  • serialNo 商户 API 证书序列号
  • key key.pem fs.readFileSync(config.keyPath)
  • body 接口请求参数

验证签名

  1. let verifySignature: boolean = PayKit.verifySignature(signature, data, nonce, timestamp, publicKey)
  2. // 或者
  3. let verifySignature: boolean = PayKit.verifySign(headers, data, publicKey)
  4. console.log(`verifySignature:${verifySignature}`)

调用 v3 接口

获取平台证书列表为例

  1. try {
  2. let result = await PayKit.exeGet(
  3. WX_DOMAIN.CHINA, //
  4. WX_API_TYPE.GET_CERTIFICATES,
  5. config.mchId,
  6. serialNo,
  7. fs.readFileSync(config.keyPath).toString()
  8. )
  9. console.log(`result.data:${result.data}`)
  10. // 应答报文主体
  11. let data = JSON.stringify(result.data)
  12. // 应答状态码
  13. console.log(`status:${result.status}`)
  14. console.log(`data:${data}`)
  15. // http 请求头
  16. let headers = result.headers
  17. // 证书序列号
  18. let serial = headers['wechatpay-serial']
  19. // 应答时间戳
  20. let timestamp = headers['wechatpay-timestamp']
  21. // 应答随机串
  22. let nonce = headers['wechatpay-nonce']
  23. // 应答签名
  24. let signature = headers['wechatpay-signature']
  25. console.log(`serial:\n${serial}`)
  26. console.log(`timestamp:\n${timestamp}`)
  27. console.log(`nonce:\n${nonce}`)
  28. console.log(`signature:\n${signature}`)
  29. // 根据序列号查证书 验证签名
  30. // let verifySignature: boolean = PayKit.verifySignature(signature, data, nonce, timestamp, wxPublicKey)
  31. let verifySignature: boolean = PayKit.verifySign(headers, data, wxPublicKey)
  32. console.log(`verifySignature:${verifySignature}`)
  33. ctx.body = data
  34. } catch (error) {
  35. console.log(error)
  36. }

证书和回调报文解密

证书报文解密为例

  1. // 证书和回调报文解密
  2. let certPath = '/Users/Javen/cert/platform_cert.pem'
  3. try {
  4. // 解密
  5. let decrypt = PayKit.aes256gcmDecrypt(
  6. config.apiKey3,
  7. ctx.app.config.AEAD_AES_256_GCM.nonce,
  8. ctx.app.config.AEAD_AES_256_GCM.associated_data,
  9. ctx.app.config.AEAD_AES_256_GCM.ciphertext
  10. )
  11. // 保存证书
  12. fs.writeFileSync(certPath, decrypt)
  13. ctx.body = decrypt
  14. } catch (error) {
  15. console.log(error)
  16. }

更多示例

微信支付-Egg 示例微信支付 V3 版本 - 图5