# QQ小程序支付签名计算

# 概述

本文档详细说明 qq.requestQQPayment 接口中 paySign 参数的计算逻辑。签名计算逻辑与微信支付保持一致,参考 微信支付小程序调起支付签名文档

注意:调起支付与下单计算签名使用的商户API证书需保持一致

# 1. 获取商户API证书

构造请求签名需要使用商户API证书,可以参考 QQ支付接口文档 申请商户API证书。

你需要准备以下信息:

  • 商户号:在QQ支付商户平台获取
  • 商户API证书序列号:申请证书时获得
  • 商户API证书私钥:保存为 pem 格式文件(如 apiclient_key.pem

# 2. 构造签名串

签名串一共有四行,每一行为一个参数。结尾以 \n(换行符,ASCII编码值为0x0A)结束,包括最后一行

小程序appID\n
时间戳\n
随机字符串\n
prepay_id=<预支付交易会话标识>\n
1
2
3
4

# 2.1 获取小程序 appID

小程序支付需要申请小程序,获取小程序 AppID,可在 QQ开放平台 查看。

# 2.2 获取时间戳

获取发起请求时的系统当前时间戳,即格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,作为请求时间戳。

生成时间戳(Unix命令):

date +%s
1

示例:

1554208460
1

# 2.3 生成随机字符串

生成一个请求随机串,推荐调用随机数函数生成,将得到的值转换为字符串。

生成随机字符串(Unix命令):

hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random
1

示例:

593BEC0C930BF1AFEB40B4A08C8FB242
1

# 2.4 获取 prepay_id

调用下单接口会返回 prepay_id,参考 QQ支付统一下单接口

示例:

prepay_id=your_prepay_id
1

# 2.5 构造完整签名串

按照前述规则,构造的请求签名串如下:

your_appid\n
1554208460\n
593BEC0C930BF1AFEB40B4A08C8FB242\n
prepay_id=your_prepay_id\n
1
2
3
4

# 3. 计算签名值

使用商户API证书私钥对待签名串进行 SHA256 with RSA 签名,并对签名结果进行 Base64编码 得到签名值。

# 命令行示例

假设商户API证书私钥保存为 apiclient_key.pem

echo -n -e \
 "your_appid\n1554208460\n593BEC0C930BF1AFEB40B4A08C8FB242\nprepay_id=your_prepay_id\n" \
 | openssl dgst -sha256 -sign apiclient_key.pem \
 | openssl base64 -A
1
2
3
4

# 4. 调用支付接口

将计算得到的签名值传入 qq.requestQQPayment 接口:

qq.requestQQPayment({
  timestamp: "1554208460",
  nonceStr: "593BEC0C930BF1AFEB40B4A08C8FB242",
  package: "prepay_id=wx201410272009395522657a690389285100",
  signType: "RSA",
  paySign: "mI35pfNEQV6777ke/1T+LJLQDNTm7yeoUJH+j/adPGhmCCi0PbgkvYQTRcXH0uibcLVtvFLdGLpmoYO9FV6lBBsTAjuhh5YOvQi0e2g3e0yytitiNET9FEuqM0pjnKfRW4K6LIZDdbWJv9KhZUx3DrJa5TL7OJ7VdADVivxVySIlPVKjGwuCXzuXSJes0UcILgWQUMyha5/3nYofuHtS7r+KYyMuxD+oJ9VM1Qdxk4UIG59CP5Y3wtYIFybyF3bdu1caHTRRX+DLyMXyYA/IrTmiW01c4RPjpHBX5Dk1sZyY1zVsWNsvMHr2e1NTWtBxKJ+qk5N61J7caYoepHFaxw==",
  success(res) {
    console.log('支付成功', res);
  },
  fail(res) {
    console.log('支付失败', res);
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13

# 5. 常见问题

# 5.1 签名验证失败

如果签名验证失败,请检查:

  1. 签名串的每一行是否都以 \n 结尾(包括最后一行)
  2. 时间戳是否为秒级时间戳(10位数字)
  3. prepay_id 前是否包含 prepay_id= 前缀
  4. 使用的商户API证书私钥是否正确
  5. 签名算法是否为 SHA256 with RSA
  6. 签名结果是否进行了 Base64 编码

# 5.2 时间戳过期

QQ支付会拒绝处理很久之前发起的请求,请确保:

  • 系统时间准确
  • 时间戳为当前时间
  • 调起支付的时间与生成签名的时间间隔不要太长

# 5.3 证书不匹配

确保调起支付与下单时使用的是同一个商户API证书。

# 6. 参考资料