收藏
回答

微信小程序虚拟支付 PAY_SIG_INVALID 问题,麻烦看下是怎么回事?

问题类型 API/组件名称 终端类型 微信版本 基础库版本
Bug wx.requestVirtualPayment 工具 1 1

# 微信小程序虚拟支付 PAY_SIG_INVALID 问题


## 问题描述


在使用 `wx.requestVirtualPayment` 调用虚拟支付时,始终返回 `PAY_SIG_INVALID` 错误,已尝试多种签名计算方式均无法解决。


## 错误信息


- **错误码**`PAY_SIG_INVALID`

- **错误信息**`requestVirtualPayment:fail PAY_SIG_INVALID`

- **环境**:正式环境(`env: 1`


## 基本信息


- **小程序 AppID**`wx279137ac641a2674`

- **OfferID**`1450482034`

- **ProductID**`aa_aa`

- **环境**:正式环境(`env: 1`

- **AppKey 前缀**`mBkm`(正式环境,完整长度为 32 位)


## 签名计算方式


根据微信文档,我们使用以下方式计算 `paySig`


```php

// 方式1:使用 requestVirtualPayment 作为 URI

$uri = 'requestVirtualPayment';

$paySigData = $uri . '&' . $signData;

$paySig = hash_hmac('sha256', $paySigData, $appKey);


// 方式2:使用 /cgi-bin/midas/pay 作为 URI

$uri = '/cgi-bin/midas/pay';

$paySigData = $uri . '&' . $signData;

$paySig = hash_hmac('sha256', $paySigData, $appKey);


// 方式3:直接对 signData 签名

$paySig = hash_hmac('sha256', $signData, $appKey);

```


同时尝试了:

- 十六进制编码(默认)

- Base64 编码


## 实际请求数据


### signData 内容


```json

{

  "offerId": "1450482034",

  "buyQuantity": 1,

  "env": 1,

  "currencyType": "CNY",

  "productId": "aa_aa",

  "goodsPrice": 100,

  "outTradeNo": "VP17724976542266728",

  "attach": "{\"vipGrade\":2,\"pricePayType\":\"payMonthly\",\"functiontype\":4}"

}

```


### signData 字符串(用于签名)


```

{"offerId":"1450482034","buyQuantity":1,"env":1,"currencyType":"CNY","productId":"aa_aa","goodsPrice":100,"outTradeNo":"VP17724976542266728","attach":"{\"vipGrade\":2,\"pricePayType\":\"payMonthly\",\"functiontype\":4}"}

```


### paySigData(方式1:requestVirtualPayment)


```

requestVirtualPayment&{"offerId":"1450482034","buyQuantity":1,"env":1,"currencyType":"CNY","productId":"aa_aa","goodsPrice":100,"outTradeNo":"VP17724976542266728","attach":"{\"vipGrade\":2,\"pricePayType\":\"payMonthly\",\"functiontype\":4}"}

```


### paySig 计算结果(方式1,十六进制)


```

c8ab87291473270158d0e1c1...

```


### paySig 计算结果(方式1,Base64)


```

yKuHKRRzJwFY0OHB...

```


### paySig 计算结果(方式2,十六进制)


```

d167e341788a2269...

```


### paySig 计算结果(方式2,Base64)


```

0WfjQXiKImmqFeFy...

```


### paySig 计算结果(方式3,直接签名,十六进制)


```

86648b14825196b4...

```


### paySig 计算结果(方式3,直接签名,Base64)


```

hmSLFIJRlrTLyu8H...

```


## 已尝试的解决方案


1. ✅ 使用 `requestVirtualPayment` 作为 URI 前缀

2. ✅ 使用 `/cgi-bin/midas/pay` 作为 URI 前缀

3. ✅ 直接对 `signData` 签名(不使用 URI 前缀)

4. ✅ 十六进制编码

5. ✅ Base64 编码

6. ✅ 测试环境(`env: 0`)和正式环境(`env: 1`

7. ✅ 确认 `app_key` 配置正确(正式环境使用正式环境的 `app_key`

8. ✅ 确认 `signData` 的 JSON 格式正确(字段顺序、转义等)


## 调用代码


### 前端调用


```javascript

wx.requestVirtualPayment({

  signData: '{"offerId":"1450482034","buyQuantity":1,"env":1,"currencyType":"CNY","productId":"aa_aa","goodsPrice":100,"outTradeNo":"VP17724976542266728","attach":"{\"vipGrade\":2,\"pricePayType\":\"payMonthly\",\"functiontype\":4}"}',

  signature: 'b3239b3794df84d2...', // 使用 sessionKey 计算的签名

  paySig: 'yKuHKRRzJwFY0OHB...', // 使用 app_key 计算的签名(Base64 版本)

  mode: 'short_series_goods'

});

```


### 后端签名计算(PHP)


```php

// 用户态签名

$signature = hash_hmac('sha256', $signData, $sessionKey);


// 商户侧签名(paySig)

$uri = 'requestVirtualPayment';

$paySigData = $uri . '&' . $signData;

$paySig = base64_encode(hash_hmac('sha256', $paySigData, $appKey, true));

```


## 后台配置确认


-`productId` `aa_aa` 已在正式环境发布

-`goodsPrice` 配置为 100 分(1 元),与代码一致

-`offerId` `1450482034` 正确

-`app_key` 已确认是正式环境的密钥


## 问题


1. **`paySig` 的计算方式是否正确?** 是否应该使用 `requestVirtualPayment` 作为 URI,还是 `/cgi-bin/midas/pay`

2. **`paySig` 的编码格式是什么?** 应该是十六进制还是 Base64?

3. **`signData` 的 JSON 格式是否有特殊要求?** 字段顺序、空格、转义等是否有要求?

4. **是否有其他参数或配置影响签名验证?**


## 期望结果


希望微信技术支持能够:

1. 确认 `paySig` 的正确计算方式

2. 验证我们提供的 `signData``paySig` 是否正确

3. 提供正确的签名计算示例代码


## 联系方式


- **小程序 AppID**`wx279137ac641a2674`

- **问题发生时间**:2026-03-03

- **问题环境**:正式环境


---


**注意**`app_key` 的完整值已脱敏处理,如需完整值进行验证,请通过安全渠道提供。



回答关注问题邀请回答
收藏

3 个回答

  • 磊磊同学
    磊磊同学
    03-03

    前端api 下单 uri 为 requestVirtualPayment ,env传0,实测ios传1不行,paySigData 一定是后端json_encode后传入前端用的,如果前端生成的 可能会导致前后端规则不一样 会失败,我们全链路都跑通了 没问题


    static function calc_pay_sig($uri, $post_body, $appkey) {
        $need_sign_msg = $uri . '&' . $post_body;
        return hash_hmac('sha256', $need_sign_msg, $appkey, false);
    }
    
    03-03
    有用 2
    回复
  • 从君华
    从君华
    03-18

    不要自己写,把官方文档中的 Demo 丢给 AI 转成你的语言,包通的。

    03-18
    有用
    回复
  • Memory (私信不回复)
    Memory (私信不回复)
    03-03

    去抄https://developers.weixin.qq.com/community/develop/article/doc/00006845ce4860bedcb4d5eed61813

    03-03
    有用
    回复
登录 后发表内容