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

测试模式下Stripe Payment模式请求payload中customer字段为null的解决方案

问题:测试模式下Stripe Payment模式如何在请求Payload中包含Customer ID

当Stripe处于测试模式时,使用payment模式(而非subscription模式)的请求payload中customer字段为null。即使在提交测试信用卡付款前提前在Stripe中创建客户,也无法改变payment模式下customer字段的状态。

请问在测试模式下使用payment模式时,有没有办法让Stripe在请求payload中包含customer ID?Stripe默认认为仅进行一次性付款而非订阅服务的客户无需创建账户,但我的应用场景并非如此。

使用Subscription模式(customer: cus_PIpLq6wFgjP2W3)

{"id": "evt_1OUDgfDcghvJaUoz0kK03Z13","object": "event","api_version": "2022-11-15","created": 1704223901,"data": {"object": {"id": "cs_test_a1PGOU8a6sLHxvrBnuFeFArDdcXN8E1rSqeAAfjB6kqVK2sBFOy6dWq4q4","object": "checkout.session","after_expiration": null,"allow_promotion_codes": null,"amount_subtotal": 999,"amount_total": 999,"automatic_tax": {"enabled": false,"status": null},"billing_address_collection": null,"cancel_url": "http://localhost:3000/cancel","client_reference_id": null,"client_secret": null,"consent": null,"consent_collection": null,"created": 1704223859,"currency": "usd","currency_conversion": null,"custom_fields": [],"custom_text": {"after_submit": null,"shipping_address": null,"submit": null,"terms_of_service_acceptance": null},"customer": "cus_PIpLq2wFgpP2W3","customer_creation": null,"customer_details": {"address": {"city": null,"country": "US","line1": null,"line2": null,"postal_code": "28036","state": null},"email": "testemail@gmail.com","name": "test1 test2","phone": null,"tax_exempt": "none","tax_ids": []},"customer_email": null,"expires_at": 1704310259,"invoice": "in_1OUDgbDcghvJaUozYJCmJyo7","invoice_creation": null,"livemode": false,"locale": null,"metadata": {},"mode": "subscription","payment_intent": null,"payment_link": null,"payment_method_collection": null,"payment_method_configuration_details": null,"payment_method_options": null,"payment_method_types": ["card"],"payment_status": "paid","phone_number_collection": {"enabled": false},"recovered_from": null,"setup_intent": null,"shipping_address_collection": null,"shipping_cost": null,"shipping_details": null,"shipping_options": [],"status": "complete","submit_type": null,"subscription": "sub_1OUDgbDcghvJaUozli1YZwLQ","success_url": "http://localhost:3000/login","total_details": {"amount_discount": 0,"amount_shipping": 0,"amount_tax": 0},"ui_mode": "hosted","url": null}},"livemode": false,"pending_webhooks": 1,"request": {"id": null,"idempotency_key": null},"type": "checkout.session.completed"}

使用Payment模式(customer: null)

{"id": "evt_1OTwhHDcghvJaUozf9VptPDi","object": "event","api_version": "2022-11-15","created": 1704158591,"data": {"object": {"id": "cs_test_a1ryh8MDmMh1q8mEgX7kExp4m2Ovx5h2WxbKUNFVK6IQhjMhIXDMLsP3BQ","object": "checkout.session","after_expiration": null,"allow_promotion_codes": null,"amount_subtotal": 2399,"amount_total": 2399,"automatic_tax": {"enabled": false,"status": null},"billing_address_collection": null,"cancel_url": "http://localhost:3000/cancel","client_reference_id": null,"client_secret": null,"consent": null,"consent_collection": null,"created": 1704158556,"currency": "usd","currency_conversion": null,"custom_fields": [],"custom_text": {"after_submit": null,"shipping_address": null,"submit": null,"terms_of_service_acceptance": null},"customer": null,"customer_details": {"address": {"city": null,"country": "US","line1": null,"line2": null,"postal_code": "28036","state": null},"email": "testemail@gmail.com","name": "Testfirst Testlast","phone": null,"tax_exempt": "none","tax_ids": []},"customer_email": null,"expires_at": 1704244956,"invoice": null,"invoice_creation": null,"livemode": false,"locale": null,"metadata": {},"mode": "payment","payment_intent": "pi_3OEmgiDcghvJaUoz1Q1TFagq","payment_link": null,"payment_method_collection": null,"payment_method_configuration_details": null,"payment_method_options": {},"payment_method_types": ["card"],"payment_status": "paid","phone_number_collection": {"enabled": false},"recovered_from": null,"setup_intent": null,"shipping_address_collection": null,"shipping_cost": null,"shipping_details": null,"shipping_options": [],"status": "complete","submit_type": null,"subscription": null,"success_url": "http://localhost:3000/login","total_details": {"amount_discount": 0,"amount_shipping": 0,"amount_tax": 0},"ui_mode": "hosted","url": null}},"livemode": false,"pending_webhooks": 1,"request": {"id": null,"idempotency_key": null},"type": "checkout.session.completed"}

loadStripe代码

async function handleClick() {
    const stripe = await loadStripe(
        'pk_test_2fsdf979sdeUozQvee95j3F88MFXPMFrPGPpjlklmm4Y4oh2Uob7uiRdJCjlkozZIyAayjth3vv3fds898sfe2g'
    )
    const { error } = await stripe.redirectToCheckout({
        lineItems: [
            {
                price: 'price_10FEPIMIDfsdfozETytrkq2',
                quantity: 1,
            }
        ],
        mode: 'subscription',
        successUrl: 'http://localhost:3000/login',
        cancelUrl: 'http://localhost:3000/cancel'
    })
}

我使用的是Stripe托管页面,因此无法灵活地将customer ID硬编码到交易中。


解决方案

方法1:后端创建Checkout Session时指定customer参数

前端直接调用redirectToCheckout无法指定customer参数,这是Stripe的安全限制。你需要通过后端API创建Checkout Session,传入提前创建好的Customer ID,同时设置customer_creation参数控制客户创建逻辑。示例Node.js后端代码:

const stripe = require('stripe')('sk_test_your_secret_key');

const createCheckoutSession = async (req, res) => {
  const customerId = 'cus_your_existing_customer_id'; // 提前在Stripe创建的客户ID

  const session = await stripe.checkout.sessions.create({
    payment_method_types: ['card'],
    line_items: [
      {
        price: 'price_10FEPIMIDfsdfozETytrkq2',
        quantity: 1,
      },
    ],
    mode: 'payment',
    customer: customerId,
    customer_creation: 'if_required', // 若客户不存在则创建,存在则复用
    success_url: 'http://localhost:3000/login',
    cancel_url: 'http://localhost:3000/cancel',
  });

  res.json({ url: session.url });
};

前端修改为调用后端接口获取Session URL后跳转:

async function handleClick() {
  const response = await fetch('/create-checkout-session', { method: 'POST' });
  const { url } = await response.json();
  window.location.href = url;
}

这种方式创建的Payment模式Session会关联指定的Customer ID,Webhook事件中customer字段会显示对应的ID。

方法2:通过customer_email自动关联现有客户

如果你不想提前创建客户,可以在后端创建Session时传入customer_email参数,Stripe会自动匹配系统中已存在的同邮箱客户并关联到Session中。示例:

const session = await stripe.checkout.sessions.create({
  // 其他参数不变
  customer_email: 'testemail@gmail.com',
  mode: 'payment',
});

若Stripe系统中已有该邮箱对应的客户,Session会自动关联,Webhook事件的customer字段会填充对应ID;如果没有,会自动创建新客户并关联。

注意事项

  • 测试模式和生产模式的逻辑一致,上述方法在两种模式下都适用。
  • 必须通过后端创建Checkout Session才能实现客户关联,前端直接调用无法满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:19:50