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

news/2024/12/28 3:51:11 标签: 微信

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.重点介绍平台证书 及序列号获取方法

选择 “验证<a class=微信支付身份” 管理证书 " />
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

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


http://www.niftyadmin.cn/n/5802321.html

相关文章

D类音频应用EMI管理

1、前言 对于EMI&#xff0c;首先需要理解天线。频率和波长之间的关系&#xff0c;如下图所示。   作为有效天线所需的最短长度是λ/4。在空气中&#xff0c;介电常数是1&#xff0c;但是在FR4或玻璃环氧PCB的情况下&#xff0c;介电常数大约4.8。这种效应会导致信号在FR4材…

企业架构学习笔记-数字化转型

1. 企业数字化发展阶段 案例1.业务部门“点菜”&#xff0c;IT部门叫苦 随着企业信息化进程的不断推进&#xff0c;IT部门的角色和面临的挑战也在发生显著变化。在信息化建设的初级阶段&#xff0c;确实存在IT部门需要积极引导和说服业务部门重视信息技术价值的情况。当时&am…

【HarmonyOS】鸿蒙将资源文件夹Resource-RawFile下的文件存放到沙箱目录下

【HarmonyOS】鸿蒙将资源文件夹Resource-RawFile下的文件存放到沙箱目录下 一、问题背景 应用开发中&#xff0c;我们经常会遇到一些文件原先是放在资源文件夹 rawfile下&#xff0c;但是逻辑处理时&#xff0c;需要转移到本地沙箱才能操作。这种情况下&#xff0c;就需要将将…

【漏洞复现】灵当CRM datapdf.php 任意文件读取漏洞

免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删除。本次测试仅供学习使用,如若非法他用,与平台和本文作…

【Git】—— 使用git操作远程仓库(gitee)

目录 一、远程仓库常用命令 1、从远程仓库克隆项目 2、查看关联的远程仓库 3、添加关联的远程仓库 4、移除关联的远程仓库 5、将本地仓库推送到远程仓库 6、从远程仓库拉取项目 二、分支命令 1、查询分支 2、创建分支 3、切换分支 4、推送到远程分支 5、合并分支 …

HTTP/2与HTTP1.X的对比及升级指南

文章目录 前言HTTP协议概述HTTP/1.xHTTP/2详解1. 二进制分帧层&#xff08;Binary Framing Layer&#xff09;2. 多路复用&#xff08;Multiplexing&#xff09;3. 头部压缩&#xff08;Header Compression&#xff09;4. 服务器推送&#xff08;Server Push&#xff09;5. 流优…

解决Springboot整合Shiro自定义SessionDAO+Redis管理会话,登录后不跳转首页

解决Springboot整合Shiro自定义SessionDAORedis管理会话&#xff0c;登录后不跳转首页 问题发现问题解决 问题发现 在Shiro框架中&#xff0c;SessionDAO的默认实现是MemorySessionDAO。它内部维护了一个ConcurrentMap来保存session数据&#xff0c;即将session数据缓存在内存…

xterm遇到的问题及解决方案

xterm遇到的问题及解决方案 /r插入终端导致的之后插入的数据覆盖了改行头部的数据 问题说明 如图所示&#xff0c;当在一行输入的候&#xff0c;输入的l插入到了改行的头部。 查看ws返回数据 可见ws返回的信息存在\r字符&#xff0c;在xterm.js中\r是回车字符的意思&…