WeChatDeveloper/src/Support/Signature.php
Anyon 9c3fd5b59d feat(wechat): 完善微信协议层通用能力
- 新增 InteractsProtocol,复用 access_token 注入、JSON 请求、raw/download/upload 与消息加解密伪路径处理。

- 微信公众平台、小程序、服务平台统一按官方 path + params/options 调用,服务平台保留授权链路能力。

- 微信支付 APIv3 支持 raw/download 原始响应,并确保签名 query 与实际请求一致。

- 增强 XML 重复节点/嵌套节点编解码和消息安全模式密文校验。
2026-05-08 00:29:10 +08:00

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;
}
}