You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在PHP脚本中从Stripe的checkout.session.completed事件获取元数据(order_no)

如何在PHP中处理Stripe的checkout.session.completed事件并提取元数据

我明白你现在的困惑——不用额外框架(比如Slim)纯PHP处理Stripe Webhook,提取checkout会话里的元数据确实需要理清步骤。我帮你拆解整个流程,附上可直接用的代码示例:

第一步:先在Stripe后台配置Webhook端点

首先你得告诉Stripe把事件发送到哪里:

  • 登录Stripe Dashboard,进入「Developers」→「Webhooks」
  • 点击「Add endpoint」,填写你的PHP脚本URL(比如https://你的域名/stripe-webhook.php
  • 在「Events to send」里找到并勾选checkout.session.completed事件
  • 复制页面上的「Signing secret」(这个是验证请求合法性的关键,一定要保存好)

第二步:纯PHP Webhook处理脚本

下面是完整的stripe-webhook.php代码,注释里写清了每一步的作用:

<?php
// 引入Stripe库(如果用Composer安装,直接用这个;手动下载的话替换成对应路径)
require_once 'vendor/autoload.php';

// 配置你的Stripe密钥和Webhook签名密钥
\Stripe\Stripe::setApiKey('你的Stripe Secret Key'); // 从Dashboard的API Keys里复制
$webhook_secret = '你的Webhook Signing Secret'; // 刚才复制的签名密钥

// 获取Stripe发送的原始POST数据(不能用$_POST,因为是JSON格式)
$payload = @file_get_contents('php://input');
if (!$payload) {
    http_response_code(400);
    exit('无法读取请求数据');
}

// 获取Stripe的签名头信息
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';
$event = null;

try {
    // 验证请求确实来自Stripe,防止伪造
    $event = \Stripe\Webhook::constructEvent(
        $payload,
        $sig_header,
        $webhook_secret
    );
} catch (\UnexpectedValueException $e) {
    // 请求体格式无效
    http_response_code(400);
    exit($e->getMessage());
} catch (\Stripe\Exception\SignatureVerificationException $e) {
    // 签名验证失败,请求不是来自Stripe
    http_response_code(400);
    exit($e->getMessage());
}

// 处理checkout.session.completed事件
if ($event->type === 'checkout.session.completed') {
    // 从事件中取出checkout会话对象
    $checkout_session = $event->data->object;
    
    // 提取你之前设置的metadata里的order_id
    // 这里注意你创建会话时用的是order_id,不是order_no,要对应上
    $order_id = $checkout_session->metadata->order_id ?? '未找到订单号';
    
    // 这里可以添加你的业务逻辑,比如更新数据库订单状态
    // 示例(根据你的数据库配置修改):
    /*
    $mysqli = new mysqli('localhost', '数据库用户名', '数据库密码', '数据库名');
    if ($mysqli->connect_error) {
        die('数据库连接失败: ' . $mysqli->connect_error);
    }
    // 转义防止SQL注入
    $safe_order_id = $mysqli->real_escape_string($order_id);
    $mysqli->query("UPDATE orders SET status = '已支付' WHERE order_id = '$safe_order_id'");
    $mysqli->close();
    */
    
    // 给Stripe返回200响应,告诉它事件已处理成功
    http_response_code(200);
    echo json_encode(['状态' => '成功', '订单号' => $order_id]);
} else {
    // 如果是其他类型的事件,返回200但标记为忽略
    http_response_code(200);
    echo json_encode(['状态' => '忽略', '事件类型' => $event->type]);
}
?>

几个关键注意点

  • 必须用php://input读取数据:Stripe发送的是JSON格式的POST请求,PHP默认的$_POST只会解析表单编码的数据,所以一定要读取原始请求体。
  • 签名验证不能省:这一步是防止恶意请求的核心,千万不要跳过。
  • 元数据字段要对应:你创建会话时设置的是order_id,所以在Webhook里要提取$checkout_session->metadata->order_id,如果需要改成order_no,记得在创建会话的代码里同步修改。
  • 测试Webhook:可以用Stripe CLI发送测试事件,或者在Stripe Dashboard的Webhook页面里点击「Send test event」选择checkout.session.completed,验证你的脚本是否能正确接收和处理。

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

火山引擎 最新活动