微信小程序虚拟支付(道具直购)踩坑全记录:从-15005到支付成功
一、前言
在实现微信小程序虚拟支付-道具直购功能过程中,遭遇了大量官方文档未明确、错误提示模糊的隐藏坑点。本文把今天真实遇到的问题、错误原因、正确代码完整汇总,可直接作为开发手册使用。
二、核心环境说明
- 接口:
wx.requestVirtualPayment(小程序前端唤起支付) - 模式:
short_series_goods(道具直购固定模式) - 环境:
env:1沙箱 /env:0正式 - 错误码:
1001参数错误 /-15005签名无效
三、今日问题汇总(已脱敏+修复所有错误)
问题1:前端调用报 1001 错误
错误信息
arduino
parameter.signature should be String instead of Undefined
原因 以为只需要传 paySig,但道具支付必须传两个签名:
paySig:订单参数签名signature:用户身份签名
前端必须传的完整参数
js
wx.requestVirtualPayment({
env: 1,
mode: "short_series_goods",
offerId: "微信平台分配的道具ID", // 这里不能填productId!
paySig: "后端计算",
signData: "后端返回JSON字符串",
signature: "后端计算",
success:()=>{},
fail:(err)=>{}
})
问题2:持续报 -15005 SIGNATURE_INVALID 签名错误
今天最核心、最耗时的问题,一共踩中 3 个坑:
坑1:signData 里多了 platform":"miniprogram"
错误写法
json
{"offerId":"xxx",...,"platform":"miniprogram",...}
结论 道具支付不允许加 platform 字段,一加必签错。
坑2:signature 错误对 sessionKey 做了 base64 解码
错误代码
python
key_bytes = base64.b64decode(session_key) // 这一行会直接导致-15005
真实规则(虚拟支付专属)
- sessionKey 不需要解码
- 直接用字符串
encode("utf-8")参与 HMAC
最终正确代码
python
def calc_signature(self, session_key: str, sign_data: str) -> str:
return hmac.new(
key=session_key.encode("utf-8"),
msg=sign_data.encode("utf-8"),
digestmod=hashlib.sha256,
).hexdigest()
坑3:paySig 拼接规则与 URI 理解错误
正确规则
ini
paySig = HMAC-SHA256(appKey, "requestVirtualPayment" + "&" + signData)
正确代码
python
def calc_pay_sig(self, uri: str, post_body: str, env: int) -> str:
app_key = self._get_app_key(env)
msg = uri + "&" + post_body
return hmac.new(
key=app_key.encode("utf-8"),
msg=msg.encode("utf-8"),
digestmod=hashlib.sha256,
).hexdigest()
问题3:支付页面不显示道具图片/名称
原因(环境隔离规则)
env=1沙箱 → 只能读 开发版道具env=0正式 → 只能读 线上版道具- 调用的
offerId必须与后台配置完全一致 - 道具配置修改后必须重新发布/保存才能同步
解决方案
- 确认环境与道具版本对应
- 检查
offerId正确(不是 productId) - 重新编辑道具并发布
- 检查图片格式/大小符合要求
四、最终正确全套规则(脱敏版)
1. signData 结构(不能多字段)
json
{
"offerId": "微信分配的ID",
"buyQuantity": 1,
"env": 1,
"currencyType": "CNY",
"productId": "你自定义的商品ID",
"goodsPrice": 价格,
"outTradeNo": "订单号",
"attach": "test"
}
2. paySig 计算
- 密钥:虚拟支付
appKey - 原文:
requestVirtualPayment&signData - 算法:HMAC-SHA256
3. signature 计算
- 密钥:
sessionKey直接 encode,不解码 - 原文:
signData - 算法:HMAC-SHA256
4. 前端调用参数(最终正确)
js
wx.requestVirtualPayment({
env: 1,
mode: "short_series_goods",
offerId: "微信道具ID",
paySig: "",
signData: "",
signature: "",
success:()=>{},
fail:()=>{}
})