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

Stripe订阅创建失败及查询异常技术求助

问题分析与解决方案

错误根源解析

第一个权限错误 (PermissionError)

你错误地将Stripe.api_key设置为卖家的密钥,同时在stripe_account参数中传入了密钥而非卖家的Connect账号ID(格式为acct_xxx)。Stripe要求:

  • 平台必须使用自身的API密钥发起请求,不能切换为卖家的密钥
  • stripe_account参数需要接收Connect账号ID,而非API密钥

第二个订阅查询错误 (undefined method 'subscriptions')

  1. Stripe Ruby SDK的Customer对象没有直接的subscriptions属性,不能直接调用customer.subscriptions.any?
  2. 若订阅创建在卖家的Connect账号下,用平台API密钥查询平台侧的Customer,无法获取到卖家账号下的订阅记录

代码修复方案

1. 修正订阅创建逻辑 (SubscriptionsController#create)

确保使用平台自身密钥,传入正确的卖家Connect账号ID,同时记录订阅关联的卖家账号信息:

class SubscriptionsController < ApplicationController
  before_action :authenticate_user!

  def new
    @service = Service.find(params[:service])
  end

  def create
    @service = Service.find(params[:service])
    # 平台密钥应在初始化时配置(比如Rails credentials),这里无需重复设置
    # Stripe.api_key = Rails.application.credentials.stripe[:secret_key]

    # 确保access_code存储的是卖家的Connect账号ID(acct_xxx),而非密钥
    seller_stripe_account_id = @service.user.access_code
    plan_id = params[:plan]
    token = params[:stripeToken]

    # 获取卖家账号下的Plan,必须指定stripe_account参数
    plan = Stripe::Plan.retrieve(plan_id, stripe_account: seller_stripe_account_id)

    # 平台侧创建/获取用户的Customer
    customer = if current_user.stripe_id?
                 Stripe::Customer.retrieve(current_user.stripe_id)
               else
                 Stripe::Customer.create(email: current_user.email, source: token)
               end

    # 创建订阅:使用平台密钥,指定卖家账号ID
    subscription = Stripe::Subscription.create(
      {
        customer: customer.id,
        items: [{ plan: plan.id }],
        expand: ["latest_invoice.payment_intent"],
        application_fee_percent: 10,
      },
      stripe_account: seller_stripe_account_id
    )

    # 建议新增Subscription模型,存储订阅关联信息(用户、服务、Stripe订阅ID、卖家账号ID)
    # Subscription.create(user: current_user, service: @service, stripe_id: subscription.id, stripe_account_id: seller_stripe_account_id)

    options = {
      stripe_id: customer.id,
      subscribed: true,
    }

    options.merge!(
      card_last4: params[:user][:card_last4],
      card_exp_month: params[:user][:card_exp_month],
      card_exp_year: params[:user][:card_exp_year],
      card_type: params[:user][:card_brand]
    )

    current_user.feature_subscriptions << plan_id
    current_user.update(options)

    project_updates = {
      backings_count: @service.backings_count.next,
      current_amount: @service.current_amount + (plan.amount/100).to_i,
    }
    @service.update(project_updates)

    redirect_to root_path, notice: "Your subscription was setup successfully!"
  end

  def destroy
    subscription_to_remove = params[:id]
    plan_to_remove = params[:plan_id]

    # 从数据库获取订阅关联的卖家账号ID(基于新增的Subscription模型)
    user_subscription = current_user.subscriptions.find_by(stripe_id: subscription_to_remove)
    seller_stripe_account_id = user_subscription.stripe_account_id

    # 删除订阅时指定卖家账号ID
    Stripe::Subscription.delete(
      subscription_to_remove,
      stripe_account: seller_stripe_account_id
    )

    current_user.subscribed = false
    current_user.feature_subscriptions.delete(plan_to_remove)
    user_subscription.destroy # 删除数据库中的订阅记录
    current_user.save

    redirect_to root_path, notice: "Your subscription has been cancelled."
  end
end

2. 修正订阅查询视图

优先从自身数据库获取订阅记录,再关联Stripe接口查询详情:

<% if resource.subscribed? %>
  <% current_user.subscriptions.each do |user_sub| %>
    <%# 查询对应卖家账号下的Stripe订阅详情 %>
    <% stripe_sub = Stripe::Subscription.retrieve(
          user_sub.stripe_id,
          stripe_account: user_sub.stripe_account_id
        ) %>
    <div class="p-6 mt-10 text-gray-900 bg-white rounded shadow-lg">
      <h4 class="font-bold text-gray-900">Active subscriptions</h4>
      <ul>
        <li class="flex items-center justify-between py-4 border-b">
          <div><%= stripe_sub.plan.nickname %></div>
          <%= link_to "Cancel Subscription", subscription_path(id: user_sub.stripe_id, plan_id: stripe_sub.plan.id), method: :delete, data: { confirm: "Are you sure?" } %>
        </li>
      </ul>
    </div>
  <% end %>
<% end %>
</div>

关键注意事项

  1. 确保卖家的access_code字段存储的是Stripe Connect账号ID(acct_xxx格式),而非API密钥
  2. 必须新增Subscription模型来关联用户、服务、Stripe订阅ID和卖家账号ID,避免依赖Stripe API查询所有订阅
  3. 所有涉及卖家账号资源的Stripe请求,都必须携带stripe_account参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:40:59