mirror of
https://gitee.com/zoujingli/WeChatDeveloper.git
synced 2026-09-04 23:12:09 +08:00
- 新增 InteractsProtocol,复用 access_token 注入、JSON 请求、raw/download/upload 与消息加解密伪路径处理。 - 微信公众平台、小程序、服务平台统一按官方 path + params/options 调用,服务平台保留授权链路能力。 - 微信支付 APIv3 支持 raw/download 原始响应,并确保签名 query 与实际请求一致。 - 增强 XML 重复节点/嵌套节点编解码和消息安全模式密文校验。
74 lines
2.0 KiB
PHP
74 lines
2.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* 签名与验签工具。
|
|
*/
|
|
|
|
namespace We\Support;
|
|
|
|
use We\Exception\SignatureException;
|
|
|
|
/**
|
|
* 签名与验签工具集合。
|
|
*
|
|
* 覆盖微信消息 SHA1 签名、微信支付 APIv3 商户 RSA-SHA256 签名和平台证书/公钥验签。
|
|
*/
|
|
final class Signature
|
|
{
|
|
/**
|
|
* 生成微信服务器消息签名:参数按字典序排序后拼接并计算 SHA1。
|
|
*
|
|
* @param array<int,string> $items
|
|
*/
|
|
public static function sha1(array $items): string
|
|
{
|
|
sort($items, SORT_STRING);
|
|
|
|
return sha1(implode('', $items));
|
|
}
|
|
|
|
/**
|
|
* 校验微信服务器消息签名。
|
|
*
|
|
* @param array<int,string> $items
|
|
*/
|
|
public static function assertSha1(string $expected, array $items): void
|
|
{
|
|
$actual = self::sha1($items);
|
|
if (!hash_equals($actual, $expected)) {
|
|
throw new SignatureException('微信回调签名验证失败', 0, null, ['expected' => $expected, 'actual' => $actual]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 使用微信支付商户私钥生成 RSA-SHA256 签名。
|
|
*/
|
|
public static function paymentV3Sign(string $privateKey, string $message): string
|
|
{
|
|
$key = openssl_pkey_get_private($privateKey);
|
|
if ($key === false) {
|
|
throw new SignatureException('微信支付商户私钥无效');
|
|
}
|
|
if (!openssl_sign($message, $signature, $key, OPENSSL_ALGO_SHA256)) {
|
|
throw new SignatureException('微信支付签名生成失败');
|
|
}
|
|
|
|
return base64_encode($signature);
|
|
}
|
|
|
|
/**
|
|
* 使用微信支付平台证书或平台公钥验证 RSA-SHA256 签名。
|
|
*/
|
|
public static function verifyPaymentV3(string $publicKey, string $message, string $signature): bool
|
|
{
|
|
$key = openssl_pkey_get_public($publicKey);
|
|
if ($key === false) {
|
|
throw new SignatureException('微信支付平台公钥或证书无效');
|
|
}
|
|
|
|
return openssl_verify($message, base64_decode($signature, true) ?: '', $key, OPENSSL_ALGO_SHA256) === 1;
|
|
}
|
|
}
|