回调优化
This commit is contained in:
@@ -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,
|
||||
* MD5(utf-8)后转大写与报文 sign 比对,一致即视为核心平台合法通知。
|
||||
*
|
||||
* 配置优先级:后台「系统设置 → 旺铺支付」(site_config wangpu.*) > config/services.php(env)
|
||||
*/
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user