PHP自己撸的代码.
搞不懂有些延签能过,有些验签不能过,多数都能过
这种偶然性的东西我真是头大了.....
公钥肯定是没问题的
从$_SERVER中取值出问题了?
还是$body取值有问题?
还是base64_decode有什么特殊隐藏技巧?
//这个有隐藏技巧?
$body=file_get_contents('php://input');
//还是我这里写的有毛病..?
$nonce=isset($_SERVER['HTTP_WECHATPAY_NONCE'])?$_SERVER['HTTP_WECHATPAY_NONCE']:'';
$wx_cert_no=isset($_SERVER['HTTP_WECHATPAY_SERIAL'])?$_SERVER['HTTP_WECHATPAY_SERIAL']:'';
$sign_base64_str=isset($_SERVER['HTTP_WECHATPAY_SIGNATURE'])?$_SERVER['HTTP_WECHATPAY_SIGNATURE']:'';
$timestamp=isset($_SERVER['REQUEST_TIME'])?$_SERVER['REQUEST_TIME']:'';
//公钥铁定没问题,不然延签也不会过啊
$wx_key=file_get_contents('下载的微信公钥');
//这个很少用.不确定. 反正我整了一晚上 愣是没搞明白 这种偶然性
$res=openssl_verify($message,base64_decode($sign_base64_str),$wx_key,'sha256WithRSAEncryption');
if ($res=="1"){
return true;
}else{
return false;
}
援引自: https://packagist.org/packages/wechatpay/wechatpay
回调通知
回调通知受限于开发者/商户所使用的`WebServer`有很大差异,这里只给出开发指导步骤,供参考实现。
1. 从请求头部`Headers`,拿到`Wechatpay-Signature`、`Wechatpay-Nonce`、`Wechatpay-Timestamp`、`Wechatpay-Serial`及`Request-ID`,商户侧`Web`解决方案可能有差异,请求头可能大小写不敏感,请根据自身应用来定;
2. 获取请求`body`体的`JSON`纯文本;
3. 检查通知消息头标记的`Wechatpay-Timestamp`偏移量是否在5分钟之内;
4. 调用`SDK`内置方法,[构造验签名串](https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml)然后经`Rsa::verfify`验签;
5. 消息体需要解密的,调用`SDK`内置方法解密;
6. 如遇到问题,请拿`Request-ID`点击[这里](https://support.pay.weixin.qq.com/online-service?utm_source=github&utm_medium=wechatpay-php&utm_content=apiv3),联系官方在线技术支持;
样例代码如下:
<?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);// 打印解密后的结果 }