微信V3支付报错 平台证书及平台证书序列号

1.平台证书及平台证书序列号设置错误报错:

  • 错误1:

Verify the response's data with: timestamp=1735184656, nonce=a5806b8cabc923299f8db1a174f3a4d0, signature=FZ5FgD/jtt4J99GKssKWKA/0buBSOAbWcu6H52l2UqqaJKvrsNxvodB569ZFz5G3fbassOQcSh5BFq6hvEMjQ2U3gKyF1muqsX8oufN4pLQpO+SO5CM7q8y/jIiYG18Kn3Iss7jbG/qGTsssscN98tfpUAb3TCWSQB1mVXUgSDWsROthYfduUgsNMC/xe1z1f2Os9L8fYWjqv8Fr5W5sL7+jFzSTibu7XcietZ+G1MusHC606ncF8MU9cNEf5QRHqgkril3e5IEesssEud6bp35sss0I87wgU5eMDZJp2hw==, cert=[2sssssss1FCC3BBA284F5C7889BCD7B47 => ...] failed

  • 错误2:

certs(175BxxxxE4507EA22FFD9D8B7CCD0218F1E3xxxx) contains the merchant's certificate serial number(175BxxxxE4507EA22FFD9D8B7CCD0218F1E3xxxx) which is not allowed here.

  • 错误3:

Cannot found the serial(2sssssss1FCC3BBA284F5C7889BCD7B47)'s configuration, which's from the response(header:Wechatpay-Serial), your's 5B1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A

2.重点介绍平台证书 及序列号获取方法

2.1选择商户后台 "验证微信支付身份" 管理证书。

拿到 平台证书的序列号,

2.2 点击 "右上角" 下载证书

获取证书相关链接:https://pay.weixin.qq.com/doc/v3/merchant/4012068814

打开链接后按照提示下载jar包,

jdk下载地址:https://repo.huaweicloud.com/java/jdk/ windows配置环境变量JAVA_HOME:C:\Program Files\Java\jdk-13

path增加:%JAVA_HOME%\bin

java -jar CertificateDownloader.jar -k a3F7t8L2x9K5xxxxx -m 1xxxxxx -f D:\program\WXCertUtil\WXCertUtil\cert\1700367105_20241225_cert\apiclient_key.pem -s 11111122E5678EA22xxxx18F1cdEab3 -o d:

在d盘生成wechatpay开头的pem文件,就是我们要的平台证书。上传到服务器/data/wechat_cert/wechatpay_platform_create_at_202412.pem下

下属代码中的

WECHAT_PAY_PLATFORM_CERTIFICATE=/data/wechat_cert/wechatpay_platform_create_at_202412.pem

WECHAT_PAY_PLATFORM_CERTIFICATE_SERIAL=11D1111B23D5BFD1FddbBBA111F5C7889BC11111

3.支付完整代码

php 复制代码
<?php

namespace app\common\util;


use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;


//参考 微信支付文档:https://pay.weixin.qq.com/docs/merchant/apis/in-app-payment/direct-jsons/app-prepay.html
class WeChatPayUtil
{
    /**
     * 微信开发平台审核通过的应用ID
     * @var string
     */
    protected $appid = 'xxx';

    /**
     * 商户ID
     * @var string
     */
    protected $merchantId = 'xxx';

    /**
     * 商户v3版本私钥
     * @var string
     */
    protected $merchantV3PrivateKey = 'xx';


    /**
     * 「商户API私钥」文件的绝对路径
     * @var string
     */
    protected $merchantPrivatePath = '\v3_apiclient_key.pem';

    /**
     * 「商户API证书」的「证书序列号」
     * @var string
     */
    protected $merchantCertificateSerial = 'xxx';

    /**
     * 「微信支付平台证书」文件的绝对路径
     * @var string
     */
    protected $platformCertificate = '\platform_key.pem';

    /**
     * 「微信支付平台证书」的「证书序列号」
     * @var string
     */
    protected $platformCertificateSerial = 'xx';

    /**
     * APIv3 客户端实例
     * @var \WeChatPay\BuilderChainable
     */
    protected $instance;


    public function getMerchantV3PrivateKey(): string
    {
        return $this->merchantV3PrivateKey;
    }


    public function __construct()
    {
        $this->appid = getenv('WECHAT_PAY_APPID');
        $this->merchantId = getenv('WECHAT_PAY_MERCHANT_ID');
        $this->merchantV3PrivateKey = getenv('WECHAT_PAY_MERCHANT_V3_PRIVATE_KEY');
        $this->merchantPrivatePath = getenv('WECHAT_PAY_MERCHANT_PRIVATE_PATH');
        $this->merchantCertificateSerial = getenv('WECHAT_PAY_MERCHANT_CERTIFICATE_SERIAL');
        $this->platformCertificate = getenv('WECHAT_PAY_PLATFORM_CERTIFICATE');
        $this->platformCertificateSerial = getenv('WECHAT_PAY_PLATFORM_CERTIFICATE_SERIAL');
        // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
        $merchantPrivateKeyInstance = Rsa::from("file://" . $this->merchantPrivatePath, Rsa::KEY_TYPE_PRIVATE);
        // 从本地文件中加载「微信支付平台证书」或者「微信支付平台公钥」,用来验证微信支付应答的签名
        $platformPublicKeyInstance = Rsa::from("file://" . $this->platformCertificate, Rsa::KEY_TYPE_PUBLIC);
        // 构造一个 APIv3 客户端实例
        $instance = Builder::factory([
            'mchid' => $this->merchantId,
            'serial' => $this->merchantCertificateSerial,
            'privateKey' => $merchantPrivateKeyInstance,
            'certs' => [
                $this->platformCertificateSerial => $platformPublicKeyInstance,
            ],
        ]);
        $this->instance = $instance;
    }


    /**
     *  APP下单
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
     * @param $out_trade_no string 在自己系统中唯一的订单号
     * @param $body string  商品描述
     * @param $amount number 订单金额,单位为元
     * @param $notify_url string 支付回调地址,必须是https开头。例如:https://www.xxx.com/xxx/xxx
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function appPay($out_trade_no, $body, $amount, $notify_url)
    {
        return $this->instance
            ->chain('v3/pay/transactions/app')
            ->post(['json' => [
                'mchid' => $this->merchantId,
                'out_trade_no' => $out_trade_no,
                'appid' => $this->appid,
                'description' => $body,
                'notify_url' => $notify_url,
                'amount' => [
                    'total' => $amount * 100,
                    'currency' => 'CNY'
                ],
                'time_expire' => date('Y-m-d\TH:i:sP', time() + 20 * 60) // 订单未支付20分钟过期
            ]]);
    }


    /**
     * 生成支付签名
     * @param $result_data
     * @return array
     */
    public function generateSignature($result_data)
    {
        // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
        // 文件路径例如:D:\EMin\xxx\cert\wx_v3\v3_apiclient_key.pem
        $merchantPrivateKeyInstance = Rsa::from('file://' . $this->merchantPrivatePath, Rsa::KEY_TYPE_PRIVATE);
        $arouse_data = [
            'appId' => $this->appid,
            'timeStamp' => strval(Formatter::timestamp()),
            'nonceStr' => Formatter::nonce(),
            //'package' => 'prepay_id=' . $result_data['prepay_id'],  // JSAPI下单
            'prepay_id' => $result_data['prepay_id'], // APP下单
        ];
        $arouse_data += ['paySign' => Rsa::sign(
            Formatter::joinedByLineFeed(...array_values($arouse_data)),
            $merchantPrivateKeyInstance
        ), 'signType' => 'RSA'];
        return $arouse_data;
    }


    /**
     *签名验签
     * @date 2024/11/28
     * @param array $header 请求头
     * @param string $body 请求参数
     * @return bool
     */
    public function signVerify(array $header, string $body)
    {
        $inWechatPaySignature = $header['wechatpay-signature'];// 请根据实际情况获取 微信方的签名
        $inWechatPayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取 微信方的时间戳
        $inWechatPayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取 微信方的随机字符串

        // 根据通知的平台证书序列号,查询本地平台证书文件,
        $platformPublicKeyInstance = Rsa::from('file://' . $this->platformCertificate, Rsa::KEY_TYPE_PUBLIC);

        // 检查通知时间偏移量,允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatPayTimestamp);
        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($inWechatPayTimestamp, $inWechatPayNonce, $body),
            $inWechatPaySignature,
            $platformPublicKeyInstance
        );

        if ($timeOffsetStatus && $verifiedStatus) {
            return true;
        }
        return false;
    }


}

配置文件如下:

WECHAT_PAY_APPID=wxd11111111111111

WECHAT_PAY_MERCHANT_ID=1700111111

WECHAT_PAY_MERCHANT_V3_PRIVATE_KEY=aaaaaaaaa9K5p1Q4w6R3s2c7u4bbbbbb

WECHAT_PAY_MERCHANT_PRIVATE_PATH=/data/wechat_cert/wechat_apiclient_key.pem

WECHAT_PAY_MERCHANT_CERTIFICATE_SERIAL=175BC000E45tytr22eeD9d8B7BBD6666F1E3E749
WECHAT_PAY_PLATFORM_CERTIFICATE=/data/wechat_cert/wechatpay_platform_create_at_202412.pem
WECHAT_PAY_PLATFORM_CERTIFICATE_SERIAL=11D1111B23D5BFD1dddbBBA111F5r7889vb11111

相关推荐
至尊鸡4 小时前
微信流量主挑战:三天25用户!功能未完善?(新纪元4)
微信
至尊鸡4 小时前
微信流量主挑战:用户破16!新增文档转换(新纪元3)
微信
wmd131643067124 天前
将微信配置信息存到数据库并进行调用
数据库·微信
陈思杰系统思考Jason4 天前
系统思考—全局思维
百度·微信·微信公众平台·新浪微博·微信开放平台
JSON_L5 天前
小程序 - 模拟时钟
微信·微信小程序·小程序
陈思杰系统思考Jason11 天前
系统思考—持续修炼
百度·微信·微信公众平台·新浪微博·微信开放平台
JSON_L11 天前
小程序 - 头像上传
微信·小程序
陈思杰系统思考Jason11 天前
系统思考—沟通成本
百度·微信·微信公众平台·新浪微博·微信开放平台