回调优化

This commit is contained in:
liu
2026-09-04 23:30:13 +08:00
parent 968054b9ff
commit 17c1281073
7 changed files with 119 additions and 43 deletions
+36 -9
View File
@@ -14,7 +14,11 @@ use Illuminate\Support\Str;
* - 业务参数 JSON 序列化后,用随机 16 位密钥做 AES-128-ECB 加密(base64)放入 data
* - AES 密钥用旺铺平台公钥 RSA 加密(base64)放入 signature
* - 整体以 JSON 信封 POST{serialNo, version, timestamp, data, signature, extras, organizNo}
* - 应答/通知反向解密:商户私钥解 signature 得 AES 密钥,再用其解 data 得业务报文。
* 应答报文反向解密:商户私钥解 signature 得 AES 密钥,再用其解 data 得业务报文。
*
* 支付/退款后台通知为明文表单报文,不涉及加解密,仅 MD5 验签:
* sign 之外所有非空数据元按名称 ASCII 升序拼成 key=value&... 串,末尾拼接 &key=加签Key
* MD5utf-8)后转大写与报文 sign 比对,一致即视为核心平台合法通知。
*
* 配置优先级:后台「系统设置 → 旺铺支付」(site_config wangpu.*) > config/services.phpenv
*/
@@ -68,20 +72,43 @@ class WangpuPayService
}
/**
* 解密支付结果后台通知(报文 RSA+AES 双重加密,解密成功即视为合法通知)
* 验证支付结果后台通知签名(明文表单报文 + MD5 验签,验签通过即视为合法通知)
*
* @param array<string, mixed> $envelope 通知信封(含 data/signature
* @return array<string, mixed> 解密后的业务报文(mer_order_id/order_status/order_amt/trade_no 等)
* @throws RepositoryException 报文解密失败
* @param array<string, mixed> $params 通知表单报文(含 sign
* @return array<string, mixed> 原样返回的通知报文(mer_order_id/order_status/order_amt/trade_no 等)
* @throws RepositoryException 缺少签名 / 加签Key未配置 / 验签失败
*/
public function decryptNotify(array $envelope): array
public function verifyNotify(array $params): array
{
Log::driver('pay')->info('旺铺支付通知接收', ['envelope' => $envelope]);
$params = $this->decryptEnvelope($envelope);
Log::driver('pay')->info('旺铺支付通知解密', ['params' => $params]);
Log::driver('pay')->info('旺铺支付通知接收', ['params' => $params]);
$sign = strtoupper(trim((string) ($params['sign'] ?? '')));
if ($sign === '' || ! hash_equals($this->sign($params), $sign)) {
Log::driver('pay')->warning('旺铺支付通知验签失败', ['params' => $params]);
throw new RepositoryException('通知报文验签失败');
}
return $params;
}
/**
* 通知报文 MD5 加签:剔除 sign 与空值 → 按参数名 ASCII 升序拼 key=value&... → 末尾拼 &key=加签Key → MD5 大写
*
* @param array<string, mixed> $params 通知报文
* @throws RepositoryException 加签Key未配置
*/
protected function sign(array $params): string
{
unset($params['sign']);
$params = array_filter($params, static fn (mixed $value): bool => $value !== null && $value !== '');
ksort($params, SORT_STRING);
$str = implode('&', array_map(static fn (string $key, mixed $value): string => $key . '=' . $value, array_keys($params), $params));
$signKey = $this->config('sign_key');
if ($signKey === '') {
throw new RepositoryException('旺铺支付未配置通知加签Key,请联系管理员');
}
return strtoupper(md5($str . '&key=' . $signKey));
}
/**
* 支付结果后台通知地址(统一下单时上送的 notifyurl)
*/