4-3 APIv3签名机制&生成请求头Authorization步骤
为什么需要签名
上一节发送 JSAPI 下单请求时收到了 401 错误:
HTTP 头 authorization 值格式错误,请参考微信支付商户 REST API 签名规则
text
微信支付 APIv3 使用 SHA256-RSA 签名算法,要求每个请求都在 HTTP 头中携带 Authorization 字段,用于验证请求来源的身份。这是一种非对称加密机制:商户使用私钥签名,微信使用公钥验证。
签名串构造规则
签名串的组成
签名串由 5 个部分拼接而成,使用换行符 \n 分隔:
HTTP方法\n
URL路径\n
时间戳\n
随机字符串\n
请求体\n
text
具体示例
以 JSAPI 下单为例:
POST\n
/v3/pay/transactions/jsapi\n
1684401015\n
5K8264ILTKCH16CQ2502SI8ZNMTM67VS\n
{"appid":"wx1234","mchid":"1234567890",...}\n
text
| 组成部分 | 说明 | 示例 |
|---|---|---|
| HTTP 方法 | 请求方法,大写 | POST |
| URL 路径 | 不包含域名和 query 参数 | /v3/pay/transactions/jsapi |
| 时间戳 | 当前 Unix 时间戳(秒) | 1684401015 |
| 随机字符串 | 防重放攻击 | 5K8264ILTKCH16CQ2502SI8ZNMTM67VS |
| 请求体 | JSON 字符串,GET 请求为空 | {"appid":"wx1234",...} |
注意事项
| 注意点 | 说明 |
|---|---|
最后一行也要加 \n | 签名串以换行符结尾 |
| URL 不包含域名 | 只取路径部分,如 /v3/pay/transactions/jsapi |
| GET 请求体为空 | 签名串末尾仍然有一个 \n |
| 时间戳精度 | 秒级,不是毫秒 |
SHA256-RSA 签名算法
签名流程
签名串 → SHA256 摘要 → RSA 私钥加密 → Base64 编码 → 签名值
text
Node.js 中使用 crypto 模块实现:
import * as crypto from 'crypto';
import * as fs from 'fs';
// 读取商户私钥
const privateKey = fs.readFileSync('ssl/keys/apiclient_key.pem', 'utf-8');
// 创建签名
const sign = crypto.createSign('RSA-SHA256');
sign.update(signStr); // signStr 就是上面构造的签名串
sign.end();
// 生成签名值(Base64 编码)
const signature = sign.sign(privateKey, 'base64');
typescript
私钥文件位置
私钥文件在商户平台下载 API 证书时获得,通常存放于项目根目录:
ssl/
├── keys/
│ └── apiclient_key.pem # 商户私钥(绝对不能泄露)
└── certs/
└── apiclient_cert.pem # 商户公钥证书
text
Authorization 请求头格式
格式规范
Authorization: WECHATPAY2-SHA256-RSA2048 mchid="商户号",nonce_str="随机字符串",signature="签名值",timestamp="时间戳",serial_no="证书序列号"
text
字段说明
| 字段 | 说明 | 示例 |
|---|---|---|
WECHATPAY2-SHA256-RSA2048 | 签名类型(固定值) | |
mchid | 商户号 | 1234567890 |
nonce_str | 随机字符串(与签名串中的一致) | 5K8264ILTKCH16CQ... |
signature | Base64 编码的签名值 | base64EncodedSignature== |
timestamp | 时间戳(与签名串中的一致) | 1684401015 |
serial_no | 商户 API 证书序列号 | 5A6F2E3D4C5B6A7F... |
获取证书序列号
证书序列号可以在商户平台查看:
路径:商户平台 > API安全 > API证书 > 管理证书
也可以通过 OpenSSL 命令查看:
openssl x509 -in apiclient_cert.pem -noout -serial
# 输出:serial=5A6F2E3D4C5B6A7F...
bash
.env 配置
# 已有的支付配置
WECHAT_APPID=wx1234567890
WECHAT_MCHID=1234567890
WECHAT_APIV3_KEY=your_apiv3_key_here
# 新增:证书序列号
WECHAT_SERIAL_NO=5A6F2E3D4C5B6A7F...
bash
完整签名流程总结
1. 构造签名串
POST + \n + /v3/pay/transactions/jsapi + \n + timestamp + \n + nonce + \n + body + \n
2. RSA-SHA256 签名
使用商户私钥对签名串进行签名,得到 Base64 编码的签名值
3. 组装 Authorization 头
WECHATPAY2-SHA256-RSA2048 mchid="...",nonce_str="...",signature="...",timestamp="...",serial_no="..."
4. 发送请求
将 Authorization 头添加到 HTTP 请求中
text
参考资源
- 微信支付签名指南 - APIv3 签名规则
- Node.js crypto - 加密模块文档
- OpenSSL 命令 - 证书操作工具
↑