支付回调验签失败
tashuo opened this issue · comments
ta_shuo commented
运行环境
- OS: CentOS 7.9.2009
- PHP: 7.4.5
- Laravel: 8.12
- wechatpay-php: 1.4.8
描述你的问题现象
- 依照文档示例中"回调通知"章节写了一个支付回调的接口
$inBody = file_get_contents('php://input')
body使用的这个方式获取- 现在验签
$verifiedStatus
一直通过不了,试着将相关的资源配置及请求数据打印出来,未看到明显的异常,请问该如何调试?
ta_shuo commented
但是后面的aes可以正常解密,是不是微信支付证书不匹配的问题
James ZHANG commented
Lines 372 to 412 in fbe8d7c
```php | |
use WeChatPay\Crypto\Rsa; | |
use WeChatPay\Crypto\AesGcm; | |
use WeChatPay\Formatter; | |
$inWechatpaySignature = '';// 请根据实际情况获取 | |
$inWechatpayTimestamp = '';// 请根据实际情况获取 | |
$inWechatpaySerial = '';// 请根据实际情况获取 | |
$inWechatpayNonce = '';// 请根据实际情况获取 | |
$inBody = '';// 请根据实际情况获取,例如: file_get_contents('php://input'); | |
$apiv3Key = '';// 在商户平台上设置的APIv3密钥 | |
// 根据通知的平台证书序列号,查询本地平台证书文件, | |
// 假定为 `/path/to/wechatpay/inWechatpaySerial.pem` | |
$platformPublicKeyInstance = Rsa::from('file:///path/to/wechatpay/inWechatpaySerial.pem', Rsa::KEY_TYPE_PUBLIC); | |
// 检查通知时间偏移量,允许5分钟之内的偏移 | |
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp); | |
$verifiedStatus = Rsa::verify( | |
// 构造验签名串 | |
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody), | |
$inWechatpaySignature, | |
$platformPublicKeyInstance | |
); | |
if ($timeOffsetStatus && $verifiedStatus) { | |
// 转换通知的JSON文本消息为PHP Array数组 | |
$inBodyArray = (array)json_decode($inBody, true); | |
// 使用PHP7的数据解构语法,从Array中解构并赋值变量 | |
['resource' => [ | |
'ciphertext' => $ciphertext, | |
'nonce' => $nonce, | |
'associated_data' => $aad | |
]] = $inBodyArray; | |
// 加密文本消息解密 | |
$inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad); | |
// 把解密后的文本转换为PHP Array数组 | |
$inBodyResourceArray = (array)json_decode($inBodyResource, true); | |
// print_r($inBodyResourceArray);// 打印解密后的结果 | |
} | |
``` |
验签需要从头上取Wechatpay-Serial
,其就是平台证书序列号,需要加载先行下载的平台证书并加载验签名。请试着理解这段样本代码先。
ta_shuo commented
Lines 372 to 412 in fbe8d7c
```php use WeChatPay\Crypto\Rsa; use WeChatPay\Crypto\AesGcm; use WeChatPay\Formatter; $inWechatpaySignature = '';// 请根据实际情况获取 $inWechatpayTimestamp = '';// 请根据实际情况获取 $inWechatpaySerial = '';// 请根据实际情况获取 $inWechatpayNonce = '';// 请根据实际情况获取 $inBody = '';// 请根据实际情况获取,例如: file_get_contents('php://input'); $apiv3Key = '';// 在商户平台上设置的APIv3密钥 // 根据通知的平台证书序列号,查询本地平台证书文件, // 假定为 `/path/to/wechatpay/inWechatpaySerial.pem` $platformPublicKeyInstance = Rsa::from('file:///path/to/wechatpay/inWechatpaySerial.pem', Rsa::KEY_TYPE_PUBLIC); // 检查通知时间偏移量,允许5分钟之内的偏移 $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp); $verifiedStatus = Rsa::verify( // 构造验签名串 Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody), $inWechatpaySignature, $platformPublicKeyInstance ); if ($timeOffsetStatus && $verifiedStatus) { // 转换通知的JSON文本消息为PHP Array数组 $inBodyArray = (array)json_decode($inBody, true); // 使用PHP7的数据解构语法,从Array中解构并赋值变量 ['resource' => [ 'ciphertext' => $ciphertext, 'nonce' => $nonce, 'associated_data' => $aad ]] = $inBodyArray; // 加密文本消息解密 $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad); // 把解密后的文本转换为PHP Array数组 $inBodyResourceArray = (array)json_decode($inBodyResource, true); // print_r($inBodyResourceArray);// 打印解密后的结果 } ``` 验签需要从头上取
Wechatpay-Serial
,其就是平台证书序列号,需要加载先行下载的平台证书并加载验签名。请试着理解这段样本代码先。
这个逻辑有处理的,目前的平台证书用的固定一个(同下单逻辑),回调请求中的Wechatpay-Serial
跟固定使用的那个平台证书序号也一致
ta_shuo commented
暂时去掉了验签逻辑,因为回调数据解密后还会请求查询订单接口验证状态,所以暂时影响也不大
James ZHANG commented
暂时去掉了验签逻辑,因为回调数据解密后还会请求查询订单接口验证状态,所以暂时影响也不大
程序代码都已经为你甄别出来了问题,有问题就去解决掉;回避问题抑或延后处理都不是严谨的处事方式,尤其在支付领域。
James ZHANG commented
Good luck dude.