|
...
|
...
|
@@ -146,14 +146,24 @@ class PayStripeApi |
|
|
|
try {
|
|
|
|
// Webhook 签名密钥(从 Stripe 仪表盘获取)
|
|
|
|
$endpointSecret = 'whsec_garhW2TrCIrduyM3rve9mFS2sn69B9Yt';
|
|
|
|
@file_put_contents(storage_path('logs/lyh_error.log'), var_export($endpointSecret, true) . PHP_EOL, FILE_APPEND);
|
|
|
|
// 获取原始请求内容
|
|
|
|
$payload = request()->getContent();
|
|
|
|
@file_put_contents(storage_path('logs/lyh_error.log'), var_export($payload, true) . PHP_EOL, FILE_APPEND);
|
|
|
|
// 获取 Stripe 签名头
|
|
|
|
$sigHeader = request()->header('Stripe-Signature');
|
|
|
|
@file_put_contents(storage_path('logs/lyh_error.log'), var_export($sigHeader, true) . PHP_EOL, FILE_APPEND);
|
|
|
|
// 验证签名
|
|
|
|
if (!self::verifySignature($payload, $sigHeader, $endpointSecret)) {
|
|
|
|
http_response_code(400);
|
|
|
|
throw new \Exception('Invalid signature');
|
|
|
|
return [
|
|
|
|
'code' => '201',
|
|
|
|
'message' => 'Invalid signature',
|
|
|
|
'details' => [
|
|
|
|
'payload' => $payload,
|
|
|
|
'sigHeader' => $sigHeader,
|
|
|
|
'endpointSecret' => $endpointSecret,
|
|
|
|
],
|
|
|
|
]; // 返回 400 Bad Request 状态码;
|
|
|
|
}
|
|
|
|
$event = json_decode($payload, true);
|
|
|
|
// 获取事件类型
|
|
...
|
...
|
@@ -193,14 +203,23 @@ class PayStripeApi |
|
|
|
*/
|
|
|
|
public static function verifySignature($payload, $sigHeader, $endpointSecret)
|
|
|
|
{
|
|
|
|
// 获取 Stripe 签名
|
|
|
|
$signatures = [];
|
|
|
|
if (preg_match_all('/t=\d+,v1=([a-f0-9]+)/', $sigHeader, $matches)) {
|
|
|
|
$signatures = $matches[1];
|
|
|
|
// 解析 Signature Header,获取 timestamp 和签名
|
|
|
|
if (!preg_match('/t=(\d+),v1=([a-f0-9]+)/', $sigHeader, $matches)) {
|
|
|
|
return false; // 签名格式错误
|
|
|
|
}
|
|
|
|
// 计算签名哈希值
|
|
|
|
$expectedSignature = hash_hmac('sha256', $payload, $endpointSecret);
|
|
|
|
return in_array($expectedSignature, $signatures, true);
|
|
|
|
$timestamp = $matches[1]; // 提取时间戳
|
|
|
|
$receivedSignature = $matches[2]; // 提取签名
|
|
|
|
// 防止重放攻击:检查时间戳是否在 5 分钟以内
|
|
|
|
$currentTimestamp = time();
|
|
|
|
if (abs($currentTimestamp - $timestamp) > 300) {
|
|
|
|
return false; // 签名过期
|
|
|
|
}
|
|
|
|
// 计算预期签名
|
|
|
|
$signedPayload = "{$timestamp}.{$payload}";
|
|
|
|
$expectedSignature = hash_hmac('sha256', $signedPayload, $endpointSecret);
|
|
|
|
// 比较签名是否匹配
|
|
|
|
return hash_equals($expectedSignature, $receivedSignature);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} |
...
|
...
|
|