Stripe订阅创建失败及查询异常技术求助
问题分析与解决方案
错误根源解析
第一个权限错误 (PermissionError)
你错误地将Stripe.api_key设置为卖家的密钥,同时在stripe_account参数中传入了密钥而非卖家的Connect账号ID(格式为acct_xxx)。Stripe要求:
- 平台必须使用自身的API密钥发起请求,不能切换为卖家的密钥
stripe_account参数需要接收Connect账号ID,而非API密钥
第二个订阅查询错误 (undefined method 'subscriptions')
- Stripe Ruby SDK的
Customer对象没有直接的subscriptions属性,不能直接调用customer.subscriptions.any? - 若订阅创建在卖家的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>
关键注意事项
- 确保卖家的
access_code字段存储的是Stripe Connect账号ID(acct_xxx格式),而非API密钥 - 必须新增
Subscription模型来关联用户、服务、Stripe订阅ID和卖家账号ID,避免依赖Stripe API查询所有订阅 - 所有涉及卖家账号资源的Stripe请求,都必须携带
stripe_account参数
内容的提问来源于stack exchange,提问作者antnbaranov
相关产品推荐
相关产品推荐

