微信支付
在 web-nextjs 中集成微信 Native 扫码支付和 H5 手机网站支付,含内网穿透调试、API v3 安全配置和常见问题。
微信支付
技术架构图
支付时序图
准备工作
步骤 1:注册微信商户
前往 微信支付商户平台 注册。注意:微信支付要求企业或个体工商户资质,个人暂不支持。
步骤 2:开通 Native 支付
商户平台 → 产品中心 → 我的产品 → Native 支付 → 开通。
步骤 3:配置 API v3 密钥
商户平台 → 账户中心 → API 安全 → 设置 APIv3 密钥。
生成 32 位随机字符串:
openssl rand -hex 16将此密钥牢记保存,后续不可查看。此密钥用于回调数据解密。
步骤 4:下载商户 API 证书
商户平台 → 账户中心 → API 安全 → 申请 API 证书:
- 按步骤使用证书工具(certutil)生成
- 下载
apiclient_cert.pem(证书)和apiclient_key.pem(私钥) - 记录「证书序列号」(大写十六进制字符串)
步骤 5:获取微信支付平台证书公钥
可通过以下方式获取:
- 调用 API:
GET /v3/certificates - 在商户平台下载
此证书用于验证微信支付的回调签名。
步骤 6:准备环境变量
将 apiclient_key.pem 的内容(完整 PEM 格式,含 header/footer)准备为环境变量。
环境变量配置
WECHAT_PAY_APP_ID=wx1234567890abcdef # 公众号/小程序/移动应用 AppID
WECHAT_PAY_MCH_ID=1234567890 # 商户号
WECHAT_PAY_API_V3_KEY=your32charkey... # APIv3 密钥(32 位)
WECHAT_PAY_PRIVATE_KEY="-- 你的商户私钥(PKCS8 格式,含 PEM header/footer) --"
WECHAT_PAY_SERIAL_NO=证书序列号(大写十六进制字符串)
WECHAT_PAY_PLATFORM_PUBLIC_KEY="-- 微信支付平台公钥(含 PEM header/footer) --"
WECHAT_PAY_BASE_URL=https://api.mch.weixin.qq.com
WECHAT_PAY_NOTIFY_URL=https://你的域名/api/payments/wechat/notify开发环境调试
重要提醒
⚠️ 微信支付没有官方沙箱环境(不同于支付宝),必须使用真实商户账号进行调试。建议先用小额(0.01 元)测试。
内网穿透配置
微信需要向本地发送回调,必须使用内网穿透工具:
Native 支付调试流程
- 启动 natapp +
pnpm dev - 进入
/pricing→ 选择微信支付 - 页面显示二维码
- 使用真实微信扫码 → 完成支付
- 观察 notify 回调日志
- 检查数据库
H5 支付无法本地测试
微信要求 H5 支付域名必须在商户平台白名单中,本地 localhost 无法通过验证。开发阶段只调试 Native 支付。
官方调试工具
商户平台 → 开发调试 → API 接口调试
生产环境配置
- 在商户平台配置「支付授权目录」(H5 支付):产品中心 → H5 支付 → 申请域名白名单
- 回调通知 URL 无需单独配置白名单,但必须是公网可访问的 HTTPS URL
- 商户 API 证书有效期约 5 年,到期前商户平台会发送提醒邮件,届时需重新申请并更新环境变量
官方上线指引:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml
安全注意事项
- ⚠️ 私钥绝不能泄露到客户端:
WECHAT_PAY_PRIVATE_KEY仅在服务端使用,永远不要以NEXT_PUBLIC_开头 - ⚠️ 回调验签必须执行:在
notify/route.ts中,必须先用await req.text()读取原始请求体(不能解析为 JSON,否则破坏签名),再验证请求头中的Wechatpay-Signature、Wechatpay-Timestamp、Wechatpay-Nonce、Wechatpay-Serial;验签不通过直接返回 HTTP 400 - ⚠️ 回调数据必须解密:微信支付通知中的
resource字段使用 AEAD_AES_256_GCM 加密,必须调用解密函数后才能获取真实支付状态,不可直接信任明文字段 - ⚠️ 幂等性处理:根据
out_trade_no检查 DB,已paid则直接返回{ code: 'SUCCESS' } - ⚠️ API v3 密钥强度:32 位随机字符串,定期轮换,不与其他系统共享同一密钥
- ⚠️ 时间戳有效期:微信支付的时间戳验证窗口为 5 分钟,服务器时间必须准确(建议启用 NTP 同步)
微信签名规范:https://pay.weixin.qq.com/doc/global/v3/zh/4012354988.md
常见问题(FAQs)
Q: 收不到微信回调?
→ 检查 WECHAT_PAY_NOTIFY_URL 是否公网可访问,是否 HTTPS;用 natapp/cpolar 内网穿透。
Q: 验签失败?
→ 确认用的是「微信支付平台公钥」(不是商户证书中的公钥),检查 Wechatpay-Serial 是否与平台证书序列号一致。
Q: Native 支付返回 SIGNERROR?
→ 检查私钥格式:微信 API v3 要求 PKCS8 格式(-----BEGIN PRIVATE KEY-----),而非 PKCS1(-----BEGIN RSA PRIVATE KEY-----)。
Q: 二维码扫了没有反应?
→ 检查 code_url 是否是 weixin://wxpay/bizpayurl?pr=... 格式,确认微信 App 已更新到最新版。
Q: 轮询一直是 pending?
→ 检查 /api/payments/wechat/query 是否调用了正确的微信查单 API(需要传入 out_trade_no)。