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

能否用Stripe Express Checkout Element实现订阅功能(Ruby环境)

使用Stripe Express Checkout Element实现Ruby订阅功能的正确方案

完全可以通过Express Checkout Element实现订阅功能,你之前的思路存在冗余——不需要先完成一次性支付再在return_url创建订阅(这会导致重复扣费),直接将Element配置为订阅模式,配合后端创建Stripe Subscription即可完成「一次性订阅首期扣费+后续自动续费」的完整流程。

步骤1:前端代码调整

将Elements的mode设为subscription,移除amount参数(订阅金额由后端的Price对象定义),同时将支付确认方法从stripe.confirmPayment改为stripe.confirmSubscription:

const elements = stripe.elements({
  mode: 'subscription', // 切换为订阅模式
  currency: 'usd',
  appearance,
})

const expressCheckoutElement = elements.create('expressCheckout');
expressCheckoutElement.mount('#express-checkout-element');

const handleError = (error) => {
  const messageContainer = document.querySelector('#error-message');
  messageContainer.textContent = error.message;
}

expressCheckoutElement.on('confirm', async (event) => {
  const {error: submitError} = await elements.submit();
  if (submitError) {
    handleError(submitError);
    return;
  }

  // 调用后端创建Subscription的接口,而非PaymentIntent
  const res = await fetch('/create-subscription', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ price_lookup_key: '你的订阅价格lookup key' })
  });
  const {client_secret: clientSecret} = await res.json();

  const {error} = await stripe.confirmSubscription({
    elements,
    clientSecret,
    confirmParams: {
      return_url: 'https://example.com/subscription/complete',
    },
  });

  if (error) {
    handleError(error);
  } else {
    // 支付成功后自动跳转至return_url
  }
});

步骤2:Ruby后端实现

使用Stripe Ruby SDK创建Subscription,通过你持有的lookup_key找到对应的Price,同时关联Customer(可复用现有用户或新建):

require 'stripe'

Stripe.api_key = '你的Stripe秘钥'

post '/create-subscription' do
  content_type :json
  data = JSON.parse(request.body.read)
  price_lookup_key = data['price_lookup_key']

  # 通过lookup_key获取目标Price对象
  price = Stripe::Price.list(lookup_keys: [price_lookup_key], limit: 1).data.first
  raise '指定的订阅价格不存在' unless price

  # 新建或关联现有Customer(替换为你的用户系统逻辑)
  customer = Stripe::Customer.create(email: current_user.email)

  # 创建Subscription,设置首期支付为待确认状态
  subscription = Stripe::Subscription.create({
    customer: customer.id,
    items: [{ price: price.id }],
    payment_behavior: 'default_incomplete',
    expand: ['latest_invoice.payment_intent'],
  })

  # 返回Subscription的client_secret给前端完成确认
  { client_secret: subscription.latest_invoice.payment_intent.client_secret }.to_json
end

关键说明

  1. 避免重复扣费:直接通过Subscription流程完成支付确认,只会扣除订阅首期费用,后续续费由Stripe自动触发,不会产生两次扣费。
  2. return_url逻辑:在跳转后的页面,可通过URL参数传递Subscription ID,调用Stripe API查询订阅状态,无需再次创建订阅。
  3. Webhook可靠性:务必配置Stripe Webhook监听customer.subscription.created和invoice.paid事件,这是确认订阅状态最可靠的方式,避免前端跳转延迟导致的状态不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:15:57