收藏
回答

微信支付 PHP sdk 消息回调的Rsa::verfify 一直校验失败,求大佬看看~

php框架 laravel 9,支付、退款、查询接口都能正常使用,消息回调的Rsa verify 一直返回false

<?php

namespace App\Http\Controllers\MiniApp;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;

class CallbackController extends Controller
{
    public function notify(Request $request)
    {
        $inWechatpaySignature = $request->header('wechatpay-signature');
        $inWechatpayTimestamp = $request->header('wechatpay-timestamp');
        $inWechatpayNonce = $request->header('wechatpay-nonce');
        $inBody = json_encode($request->all());
//        dd($inWechatpaySignature,$inWechatpayTimestamp,$inWechatpayNonce,$inBody);
        $apiV3Key = config('wxpay.v3Secret');

        // 从本地文件中加载「微信支付平台证书」(可使用证书下载工具得到),用来验证微信支付应答的签名
        $platformCertificateFilePath = 'file://' . base_path('wxPayCert/platform_cert.pem');
        $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
        // 检查通知时间偏移量,允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);

        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        //verifiedStatus 一直为false
        Log::info('校验结果:',['时间偏移' => $timeOffsetStatus,'Rsa校验' => $verifiedStatus]);
        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);
//            dd($inBodyResourceArray);
            Log::info('解密信息', $inBodyResourceArray);
            // print_r($inBodyResourceArray);// 打印解密后的结果
            return $this->response->ok();
        }
        abort(500,'Rsa 验证失败');
    }
}


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

2 个回答

  • 北望沣渭
    北望沣渭
    21小时前
    $inBody = json_encode($request->all());
    

    这个语句不对,验签需要用原始的payload,替换成

    $inBody = $request->getContent();
    

    试试看

    另外 $inWechatpaySignature, $inWechatpayTimestamp, $inWechatpayNonce 这仨你获取到的值应该都是数组Array,需要调整取标号是0的。


    21小时前
    有用 2
    回复 1
    •  
       
      6小时前
      感谢,$inBody换成您这种可以了。另外3个参数通过代码中的方式取出来的值就是字符串是正确的。
      6小时前
      回复
  • Memory (私信不回复)
    Memory (私信不回复)
    22小时前
    $inBody = json_encode($request->all());
    

    你这样获取到的就不是原始值了,自然验证不过

    22小时前
    有用 2
    回复 1
    •  
       
      6小时前
      感谢。通过getContent可行~
      6小时前
      回复
登录 后发表内容