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

如何在PHP应用中从Stripe Checkout获取Charge Object数据?

在PHP中获取Stripe支付完成后的Charge ID并存储到数据库

核心结论

不能直接在纯HTML的success.html页面获取Stripe的Charge对象信息——敏感数据不能暴露在前端,且Stripe不会通过跳转直接返回Charge详情。正确做法是通过后端PHP代码,利用Stripe返回的session_id查询API获取Charge信息,再存储到数据库。

步骤1:将success.html改为success.php(后端处理)

用户支付完成后,Stripe会跳转到你设置的success_url,并附带session_id参数(比如https://你的域名/success.php?session_id=cs_test_xxx)。你需要用PHP后端处理这个请求:

示例代码(success.php)

<?php
// 引入Stripe SDK(Composer安装的话用这个,否则手动引入SDK文件)
require_once 'vendor/autoload.php';

// 初始化Stripe,替换为你的Stripe秘密密钥
\Stripe\Stripe::setApiKey('sk_test_xxxxxxxxxxxxxxxxxxxxxxxx');

// 获取URL中的session_id
$sessionId = $_GET['session_id'] ?? null;
if (!$sessionId) {
    die('缺少有效支付会话ID');
}

try {
    // 从Stripe获取支付会话详情
    $session = \Stripe\Checkout\Session::retrieve($sessionId);

    // 验证支付是否真的成功(防止用户直接访问success页面伪造状态)
    if ($session->payment_status !== 'paid') {
        die('支付未完成,请检查支付状态');
    }

    // 通过会话关联的Payment Intent获取Charge ID
    $paymentIntent = \Stripe\PaymentIntent::retrieve($session->payment_intent);
    $chargeId = $paymentIntent->charges->data[0]->id; // 取第一个Charge(通常对应本次支付)

    // --------------------------
    // 以下是存储到数据库的示例(PDO方式)
    // --------------------------
    $dbConfig = [
        'host' => 'localhost',
        'dbname' => '你的数据库名',
        'user' => '数据库用户名',
        'pass' => '数据库密码'
    ];
    $pdo = new PDO(
        "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset=utf8mb4",
        $dbConfig['user'],
        $dbConfig['pass']
    );
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 假设你有一个存储支付记录的表,比如`user_payments`
    $stmt = $pdo->prepare("INSERT INTO user_payments (user_id, charge_id, session_id, amount, created_at) 
                          VALUES (?, ?, ?, ?, NOW())");
    // 替换为实际的用户ID(比如从登录会话中获取)
    $userId = $_SESSION['user_id'] ?? 0;
    $amount = $session->amount_total / 100; // Stripe金额以分为单位,转换为元

    $stmt->execute([$userId, $chargeId, $sessionId, $amount]);

    // 给用户显示成功信息
    echo "<h1>支付成功!</h1>";
    echo "<p>你的支付凭证ID:" . htmlspecialchars($chargeId) . "</p>";

} catch (\Stripe\Exception\ApiErrorException $e) {
    die('获取支付信息失败:' . $e->getMessage());
} catch (PDOException $e) {
    die('存储支付记录失败:' . $e->getMessage());
}
?>

步骤2:更可靠的方案——Stripe Webhook

上面的跳转方案依赖用户完成跳转,但如果用户支付后直接关闭页面,你的后端就无法获取Charge信息。因此推荐搭配Stripe Webhook监听checkout.session.completed事件,确保无论用户是否跳转,都能收到支付成功的通知。

Webhook处理代码示例(stripe-webhook.php)

<?php
require_once 'vendor/autoload.php';

\Stripe\Stripe::setApiKey('sk_test_xxxxxxxxxxxxxxxxxxxxxxxx');

// 获取Webhook请求体和签名
$payload = @file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';
// 替换为你的Stripe Webhook密钥(在Stripe后台获取)
$webhookSecret = 'whsec_xxxxxxxxxxxxxxxxxxxxxxxx';

try {
    // 验证Webhook签名,确保请求来自Stripe
    $event = \Stripe\Webhook::constructEvent(
        $payload, $sigHeader, $webhookSecret
    );
} catch (\UnexpectedValueException $e) {
    http_response_code(400);
    exit('无效的请求体');
} catch (\Stripe\Exception\SignatureVerificationException $e) {
    http_response_code(400);
    exit('无效的签名');
}

// 处理支付完成事件
if ($event->type === 'checkout.session.completed') {
    $session = $event->data->object;

    // 获取Charge ID
    $paymentIntent = \Stripe\PaymentIntent::retrieve($session->payment_intent);
    $chargeId = $paymentIntent->charges->data[0]->id;

    // 从会话的metadata中获取用户ID(需要创建会话时提前存入)
    $userId = $session->metadata['user_id'] ?? 0;

    // 存储到数据库(同success.php的存储逻辑)
    $pdo = new PDO(
        "mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4",
        '数据库用户名',
        '数据库密码'
    );
    $stmt = $pdo->prepare("INSERT INTO user_payments (user_id, charge_id, session_id, amount, created_at) 
                          VALUES (?, ?, ?, ?, NOW())");
    $stmt->execute([$userId, $chargeId, $session->id, $session->amount_total / 100]);
}

// 告诉Stripe已成功接收事件
http_response_code(200);
?>

补充:创建Checkout Session时添加metadata

为了在Webhook中关联用户,创建会话时要把用户ID存入metadata:

$session = \Stripe\Checkout\Session::create([
    'payment_method_types' => ['card'],
    'line_items' => [[
        'price_data' => [
            'currency' => 'cny',
            'product_data' => ['name' => '你的商品名称'],
            'unit_amount' => 1000, // 10元(单位:分)
        ],
        'quantity' => 1,
    ]],
    'mode' => 'payment',
    'success_url' => 'https://你的域名/success.php?session_id={CHECKOUT_SESSION_ID}',
    'cancel_url' => 'https://你的域名/cancel.php',
    // 存入用户ID,方便Webhook关联
    'metadata' => ['user_id' => $_SESSION['user_id']]
]);

关键注意事项

  • 永远不要在前端使用Stripe秘密密钥:所有Stripe API调用必须在后端完成,避免密钥泄露。
  • 验证支付状态:无论用跳转还是Webhook,都要验证payment_status为paid,防止恶意请求。
  • 数据库存储:Charge ID是唯一标识支付的凭证,务必关联用户ID和订单信息,方便后续对账和查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:55