如何在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




