作者 lyh

gx数据

@@ -146,14 +146,24 @@ class PayStripeApi @@ -146,14 +146,24 @@ class PayStripeApi
146 try { 146 try {
147 // Webhook 签名密钥(从 Stripe 仪表盘获取) 147 // Webhook 签名密钥(从 Stripe 仪表盘获取)
148 $endpointSecret = 'whsec_garhW2TrCIrduyM3rve9mFS2sn69B9Yt'; 148 $endpointSecret = 'whsec_garhW2TrCIrduyM3rve9mFS2sn69B9Yt';
  149 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export($endpointSecret, true) . PHP_EOL, FILE_APPEND);
149 // 获取原始请求内容 150 // 获取原始请求内容
150 $payload = request()->getContent(); 151 $payload = request()->getContent();
  152 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export($payload, true) . PHP_EOL, FILE_APPEND);
151 // 获取 Stripe 签名头 153 // 获取 Stripe 签名头
152 $sigHeader = request()->header('Stripe-Signature'); 154 $sigHeader = request()->header('Stripe-Signature');
  155 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export($sigHeader, true) . PHP_EOL, FILE_APPEND);
153 // 验证签名 156 // 验证签名
154 if (!self::verifySignature($payload, $sigHeader, $endpointSecret)) { 157 if (!self::verifySignature($payload, $sigHeader, $endpointSecret)) {
155 - http_response_code(400);  
156 - throw new \Exception('Invalid signature'); 158 + return [
  159 + 'code' => '201',
  160 + 'message' => 'Invalid signature',
  161 + 'details' => [
  162 + 'payload' => $payload,
  163 + 'sigHeader' => $sigHeader,
  164 + 'endpointSecret' => $endpointSecret,
  165 + ],
  166 + ]; // 返回 400 Bad Request 状态码;
157 } 167 }
158 $event = json_decode($payload, true); 168 $event = json_decode($payload, true);
159 // 获取事件类型 169 // 获取事件类型
@@ -193,14 +203,23 @@ class PayStripeApi @@ -193,14 +203,23 @@ class PayStripeApi
193 */ 203 */
194 public static function verifySignature($payload, $sigHeader, $endpointSecret) 204 public static function verifySignature($payload, $sigHeader, $endpointSecret)
195 { 205 {
196 - // 获取 Stripe 签名  
197 - $signatures = [];  
198 - if (preg_match_all('/t=\d+,v1=([a-f0-9]+)/', $sigHeader, $matches)) {  
199 - $signatures = $matches[1]; 206 + // 解析 Signature Header,获取 timestamp 和签名
  207 + if (!preg_match('/t=(\d+),v1=([a-f0-9]+)/', $sigHeader, $matches)) {
  208 + return false; // 签名格式错误
200 } 209 }
201 - // 计算签名哈希值  
202 - $expectedSignature = hash_hmac('sha256', $payload, $endpointSecret);  
203 - return in_array($expectedSignature, $signatures, true); 210 + $timestamp = $matches[1]; // 提取时间戳
  211 + $receivedSignature = $matches[2]; // 提取签名
  212 + // 防止重放攻击:检查时间戳是否在 5 分钟以内
  213 + $currentTimestamp = time();
  214 + if (abs($currentTimestamp - $timestamp) > 300) {
  215 + return false; // 签名过期
  216 + }
  217 + // 计算预期签名
  218 + $signedPayload = "{$timestamp}.{$payload}";
  219 + $expectedSignature = hash_hmac('sha256', $signedPayload, $endpointSecret);
  220 + // 比较签名是否匹配
  221 + return hash_equals($expectedSignature, $receivedSignature);
204 } 222 }
205 223
  224 +
206 } 225 }