作者 lyh

gx数据

... ... @@ -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);
}
}
... ...