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