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

如何添加Stripe订单确认功能并保留活动注册表单数据?

Stripe活动报名支付流程修复方案

问题根源

  1. 表单监听ID不匹配:表单ID是registrationForm,但JS代码里监听的是mainForm,导致表单提交时JS逻辑根本没触发,直接走了表单默认的POST跳转,checkout.php里的POST处理逻辑没执行,表单数据没存进session。
  2. 前后端响应不匹配:checkout.php的POST请求只返回{"success":true},但前端代码期望拿到带id的session对象,所以前端不会跳转到Stripe支付页面,反而直接提交到checkout.php的GET请求,此时session里没有表单数据,后续支付成功后自然拿不到数据。
  3. Session传递数据不可靠:依赖用户浏览器session传递表单数据,支付完成后跳转回站点时,可能因为会话过期、跨域(Stripe跳转时上下文丢失)导致session数据丢失,更可靠的方式是把表单数据绑定到Stripe的Checkout Session中。

修复步骤

1. 前端代码修正

  • 修正表单监听的ID,移除表单默认的action和method属性,避免默认跳转
  • 统一Stripe实例,不要重复初始化

修改后的表单代码片段:

<form id="registrationForm"> <!-- 移除action和method -->
    <!-- 原表单字段保持不变 -->

    <script>
        // 统一初始化Stripe实例
        const stripe = Stripe("pk_test_51OWirXLdOaRkelq7e41bzMCHiHQQ8DM58BMQ1OOsep64ge470Kf45kjHaav6DSDH3blukq8vozEQK1Dfk4H80bqC000HPnvHxo");

        // 监听正确的表单ID
        document.getElementById('registrationForm').addEventListener('submit', function (event) {
            event.preventDefault();

            // 显示加载提示
            document.getElementById('loadingMessage').style.display = 'block';

            fetch('checkout.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    nome: document.getElementById('nome').value,
                    cognome: document.getElementById('cognome').value,
                    email: document.getElementById('email').value,
                    telefono: document.getElementById('telefono').value,
                    discoteca: document.getElementById('SerataNome').value,
                    faiTavolo: document.getElementById('faiTavolo').value,
                    saltaCoda: document.getElementById('saltaCoda').value,
                    quantitaPersone: document.getElementById('quantitaPersone').value,
                    ricordaWhatsapp: document.getElementById('ricordaWhatsapp').checked,
                    archiviazioneDati: document.getElementById('archiviazioneDati').value,
                    invioPromozioni: document.getElementById('invioPromozioni').value,
                }),
            })
            .then(response => response.json())
            .then(result => {
                if (result.sessionId) {
                    stripe.redirectToCheckout({ sessionId: result.sessionId });
                } else {
                    alert('Errore durante la creazione della sessione di checkout.');
                    document.getElementById('loadingMessage').style.display = 'none';
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('Si è verificato un errore durante il pagamento.');
                document.getElementById('loadingMessage').style.display = 'none';
            });
        });
    </script>

    <button type="submit" id="submitBtn">PAGA</button>
</form>

2. 后端checkout.php修正

  • 仅在POST请求时创建Checkout Session,把表单数据存入Session的metadata(同时保留session备份)
  • 返回Checkout Session的ID给前端,让前端跳转

修改后的checkout.php代码:

<?php
require_once 'init.php';
require_once 'config.php';

$stripe_secret_key = "sk_test_*****5";
\Stripe\Stripe::setApiKey($stripe_secret_key);

session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 获取表单数据
    $formData = json_decode(file_get_contents("php://input"), true);
    
    // 存到session备份
    $_SESSION['form_data'] = $formData;

    // 创建Checkout Session,把表单数据存入metadata
    $checkout_session = \Stripe\Checkout\Session::create([
        'mode' => 'payment',
        'success_url' => 'https://www.chesifastasera.com/vendor/stripe-php-master/processaQrcode.php?session_id={CHECKOUT_SESSION_ID}',
        'cancel_url' => 'https://www.chesifastasera.com/你的取消页面URL',
        'customer_email' => $formData['email'], // 预填用户邮箱
        'line_items' => [
            [
                'quantity' => (int)$formData['quantitaPersone'],
                'price_data' => [
                    'currency' => 'EUR',
                    'unit_amount' => 20000, // 注意这里是分,20000=200EUR
                    'product_data' => [
                        'name' => 'SerataTest - ' . $formData['discoteca']
                    ]
                ]
            ]
        ],
        'metadata' => $formData, // 把所有表单数据存入metadata
    ]);

    // 返回session ID给前端
    echo json_encode(['sessionId' => $checkout_session->id]);
    exit();
}

// GET请求直接返回错误(因为表单提交应该走POST)
http_response_code(405);
echo json_encode(['error' => 'Metodo non consentito']);
?>

3. processaQrcode.php处理逻辑

  • 从Checkout Session中获取表单数据(优先),或者从session中获取
  • 处理数据(比如生成二维码、存储到数据库等)

示例代码:

<?php
require_once 'init.php';
require_once 'config.php';

$stripe_secret_key = "sk_test_*****5";
\Stripe\Stripe::setApiKey($stripe_secret_key);

session_start();

// 获取Checkout Session ID
$sessionId = $_GET['session_id'] ?? '';
$formData = [];

if ($sessionId) {
    // 从Stripe获取Session数据,拿到metadata里的表单信息
    try {
        $session = \Stripe\Checkout\Session::retrieve($sessionId);
        // 验证支付是否成功
        if ($session->payment_status === 'paid') {
            $formData = $session->metadata;
        } else {
            // 支付未完成,跳转回错误页面
            header("Location: https://www.chesifastasera.com/支付失败页面");
            exit();
        }
    } catch (\Exception $e) {
        // 从session备份获取数据
        $formData = $_SESSION['form_data'] ?? [];
    }
} else {
    $formData = $_SESSION['form_data'] ?? [];
}

// 检查是否有表单数据
if (empty($formData)) {
    header("Location: https://www.chesifastasera.com/表单数据丢失页面");
    exit();
}

// 处理表单数据,比如生成二维码、存储到数据库等
// 调用你的业务逻辑,比如:
// include '你的二维码生成逻辑.php';
// generateQrcode($formData);

// 清空session数据,避免重复处理
unset($_SESSION['form_data']);

// 跳转成功页面
header("Location: https://www.chesifastasera.com/支付成功页面");
?>

4. 更可靠的方案:使用Stripe Webhook

依赖前端跳转可能存在用户中途关闭页面的情况,导致processaQrcode.php没执行。建议配置Stripe Webhook,当支付成功时自动触发你的后端逻辑:

  1. 在Stripe Dashboard中创建Webhook,监听checkout.session.completed事件
  2. 设置Webhook URL为你的后端处理地址(比如https://www.chesifastasera.com/webhook.php)
  3. 在webhook.php中验证Stripe签名,然后获取Session的metadata,调用processaQrcode.php的逻辑

示例webhook.php:

<?php
require_once 'init.php';
require_once 'config.php';

$stripe_secret_key = "sk_test_*****5";
$webhook_secret = "whsec_你的webhook密钥";

\Stripe\Stripe::setApiKey($stripe_secret_key);

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
    $event = \Stripe\Webhook::constructEvent(
        $payload, $sig_header, $webhook_secret
    );
} catch(\UnexpectedValueException $e) {
    // 无效payload
    http_response_code(400);
    exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
    // 无效签名
    http_response_code(400);
    exit();
}

// 处理checkout.session.completed事件
if ($event->type === 'checkout.session.completed') {
    $session = $event->data->object;
    
    // 验证支付状态
    if ($session->payment_status === 'paid') {
        $formData = $session->metadata;
        
        // 调用processaQrcode的逻辑
        include 'processaQrcode.php';
        // 假设processaQrcode.php里有处理函数
        processQrcodeData($formData);
    }
}

http_response_code(200);
?>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:02:31