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

如何向Stripe自定义支付流程的感谢页传递用户邮箱与Stripe客户ID参数

如何向Stripe自定义支付流程的感谢页传递用户邮箱与Stripe客户ID参数

作为搞过Stripe支付流程的开发者,我给你两个实用方案,你可以根据自己的需求选:


方案一:通过Stripe API安全获取(推荐)

这个方案不会在URL里暴露任何敏感信息,完全依赖Stripe的官方API获取真实数据,准确性和安全性都有保障。

步骤1:修改后端prepare接口,返回客户ID

你的prepare.php目前只返回了clientSecret,现在把创建好的Stripe客户ID也加进去,方便后续使用:

$productID = $request['items'][0]['id'];
$customer = \Stripe\Customer::create();
$paymentIntent = \Stripe\PaymentIntent::create([
    'customer' => $customer->id,
    'setup_future_usage' => 'off_session',
    'amount' => config('app.PRICE_TNT6WEEK') * 100,
    'currency' => 'usd',
    'automatic_payment_methods' => ['enabled' => true],
    'description' => $productID,
]);

// 新增返回customerId
$output = [
    'clientSecret' => $paymentIntent->client_secret,
    'customerId' => $customer->id
];

\Log::debug(['<pre>'.print_r($request->toArray(), true).'</pre>', $productID, $output]);
return response()->json($output);

步骤2:在感谢页通过ClientSecret拉取数据

你已经有checkStatus函数用来验证支付状态,现在扩展它,拿到支付意图后再拉取客户的邮箱信息:

// 初始化时先把customerId存到全局变量
let customerId;

async function initialize() {
    const response = await fetch("{{route('prepare.product', [$slug, $slugVersion])}}", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ items }),
    });
    const data = await response.json();
    const clientSecret = data.clientSecret;
    customerId = data.customerId; // 存储客户ID
    elements = stripe.elements({ clientSecret });
    
    // 剩下的元素初始化代码...
}

async function checkStatus() {
    const clientSecret = new URLSearchParams(window.location.search).get(
        "payment_intent_client_secret"
    );
    if (!clientSecret) return;

    // 获取支付意图
    const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);
    // 通过客户ID拉取客户详情,拿到邮箱
    const { customer } = await stripe.retrieveCustomer(paymentIntent.customer);
    const userEmail = customer.email;
    const stripeCustomerId = paymentIntent.customer;

    // 这里可以把数据传给你的后端存储,或者在页面直接使用
    console.log('用户邮箱:', userEmail);
    console.log('Stripe客户ID:', stripeCustomerId);

    // 原有的支付状态处理逻辑...
    switch (paymentIntent.status) {
        case "succeeded":
            showMessage(`支付成功!你的邮箱:${userEmail}`);
            // 可选:发送AJAX把数据存到自己的数据库
            fetch('/save-thank-you-data', {
                method: 'POST',
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ email: userEmail, stripeCustomerId })
            });
            break;
        // 其他状态处理...
    }
}

可选:提前给Stripe客户绑定邮箱

如果你想确保客户邮箱准确存在Stripe的客户对象里,可以在用户提交表单时,先调用一个后端接口更新客户邮箱:

async function handleSubmit(e) {
    e.preventDefault();
    setLoading(true);

    const userEmail = document.getElementById("email").value;
    // 先更新客户邮箱
    await fetch("/update-customer-email", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ customerId, email: userEmail })
    });

    // 原有的确认支付代码...
    const { error } = await stripe.confirmPayment({/* ... */});
    
    setLoading(false);
}

对应的后端接口代码:

public function updateCustomerEmail(Request $request) {
    \Stripe\Customer::update(
        $request->customerId,
        ['email' => $request->email]
    );
    return response()->json(['success' => true]);
}

方案二:直接在返回URL里拼接参数(快速实现)

如果只是临时快速上线,不介意参数在URL里暴露,可以直接把邮箱和客户ID拼在return_url后面:

步骤1:前端拼接参数到返回URL

let customerId;

async function initialize() {
    // 同方案一,先拿到customerId并存储
    const response = await fetch("{{route('prepare.product', [$slug, $slugVersion])}}", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ items }),
    });
    const data = await response.json();
    customerId = data.customerId;
    // 其他初始化代码...
}

async function handleSubmit(e) {
    e.preventDefault();
    setLoading(true);

    const userEmail = document.getElementById("email").value;
    // 构造带参数的返回URL
    const returnUrl = new URL("{{route('upsell.show', [$slug, $slugVersion])}}");
    returnUrl.searchParams.append('email', userEmail);
    returnUrl.searchParams.append('stripe_customer_id', customerId);

    const { error } = await stripe.confirmPayment({
        elements,
        confirmParams: {
            return_url: returnUrl.toString(), // 使用拼接好的URL
            payment_method_data: {
                billing_details: {
                    name: document.getElementById("full_name").value,
                    email: userEmail,
                    phone: document.getElementById("phone").value,
                }
            },
        },
    });

    // 错误处理代码...
    setLoading(false);
}

步骤2:感谢页控制器获取参数

在你的upsell.show对应的Laravel控制器里,直接从请求中拿参数:

public function showUpsell(Request $request) {
    $userEmail = $request->get('email');
    $stripeCustomerId = $request->get('stripe_customer_id');
    // 可以把参数传给视图,或者存储到数据库
    return view('upsell.show', compact('userEmail', 'stripeCustomerId'));
}

⚠️ 注意:这种方式参数会暴露在URL中,用户可以手动修改,所以如果需要确保数据绝对准确,还是优先用方案一。


备注:内容来源于stack exchange,提问作者Linas Lg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 07:53:07