You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Stripe Webhook触发后cURL重复调用RESTful API?

Stripe Webhook触发后cURL重复调用API的问题排查与解决

我在Stripe支付完成后,由Stripe Webhook触发一段cURL代码调用RESTful API,但出现了cURL两次调用API的异常情况——支付仅扣费一次,但API被执行了两次。相关PHP代码如下:

$url = "RESTFUL_API_URL";

// Init cURL session
$curl = curl_init();

// Create array of options for the cURL session
curl_setopt_array($curl, array(
    CURLOPT_HTTPHEADER => array('Accept: application/json'),
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    //CURLOPT_MAXREDIRS => 10,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_TIMEOUT => 60,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
    CURLOPT_CUSTOMREQUEST => "GET"
));

// Execute cURL session and store the response in $response
$response = curl_exec($curl);

// If the operation failed, store the error message in $error
$error = curl_error($curl);

// Close cURL session
curl_close($curl);

if ($error) {
    echo "cURL Error: " . $error;
} else {
    $response = Json::decode($response, true);
}

可能的原因

  • Stripe Webhook重试机制:Stripe要求Webhook在10秒内返回2xx状态码,若脚本处理过慢或未及时响应,Stripe会自动重复发送事件,导致cURL被执行多次。
  • 缺少幂等性校验:没有对Stripe事件ID做去重处理,同一条支付事件可能被重复接收并处理,进而触发多次cURL调用。
  • cURL重定向(可能性低):虽然默认关闭了重定向跟随,但如果API地址存在隐性重定向,也可能导致看似两次调用的情况。

解决措施

1. 优先返回响应给Stripe

在Webhook脚本最开头就返回200状态码,避免Stripe触发重试:

// 先给Stripe返回200响应,防止重试
http_response_code(200);
// 强制输出响应,避免缓冲延迟
flush();
ob_flush();

// 再执行后续的cURL逻辑
$url = "RESTFUL_API_URL";
// ... 剩余cURL代码

2. 添加事件幂等性校验

通过数据库记录已处理的Stripe事件ID,确保同一条事件只处理一次:

// 从Stripe Webhook请求中解析事件ID
$event = json_decode(file_get_contents('php://input'), true);
$eventId = $event['id'];

// 用数据库存储已处理事件
$pdo = new PDO('mysql:host=localhost;dbname=your_database', 'username', 'password');
$stmt = $pdo->prepare("SELECT COUNT(*) FROM processed_stripe_events WHERE event_id = ?");
$stmt->execute([$eventId]);
$processed = $stmt->fetchColumn();

if ($processed > 0) {
    http_response_code(200);
    exit; // 已处理过,直接退出
}

// 记录事件ID到数据库
$stmt = $pdo->prepare("INSERT INTO processed_stripe_events (event_id, created_at) VALUES (?, NOW())");
$stmt->execute([$eventId]);

// 继续执行cURL逻辑
// ... 剩余代码

3. 排查cURL重定向问题

开启cURL的详细日志,检查是否存在重定向导致的多次请求:

curl_setopt_array($curl, array(
    CURLOPT_HTTPHEADER => array('Accept: application/json'),
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_MAXREDIRS => 3, // 限制最大重定向次数
    CURLOPT_FOLLOWLOCATION => true, // 明确是否允许跟随重定向
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_TIMEOUT => 60,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_VERBOSE => true,
    CURLOPT_STDERR => fopen('curl_debug.log', 'w') // 写入调试日志
));

查看生成的curl_debug.log,确认是否有多次请求的记录。

4. 优化脚本处理效率

如果cURL调用的API处理较慢,可考虑异步执行(比如用消息队列),避免脚本超时导致Stripe重试。

内容的提问来源于stack exchange,提问作者Shaho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 02:30:40