ruby-on-rails - Stripe and Rails 5 - Stripe::InvalidRequestError: 没有这样的计划:starter
问题描述
我几乎完成了 Ryan Bigg 的 Multitenancy with Rails - 第 2 版书,并且发现自己在将我的应用程序与 Stripe 集成时陷入困境。特别是,我遇到了这个问题:
测试失败如下所示:
Failures:
1) Subscriptions can be cancelled
Failure/Error: subscription = customer.subscriptions.create(plan: "starter")
Stripe::InvalidRequestError:
No such plan: starter
# ./spec/features/accounts/subscriptions_spec.rb:20:in `block (2 levels) in <top (required)>'
# ./spec/rails_helper.rb:40:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:39:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# RestClient::BadRequest:
# 400 Bad Request
# ./spec/features/accounts/subscriptions_spec.rb:20:in `block (2 levels) in <top (required)>'
Finished in 1.42 seconds (files took 5.1 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/features/accounts/subscriptions_spec.rb:30 # Subscriptions can be cancelled
我的测试代码如下所示:
require "rails_helper"
require "stripe_plan_fetcher"
describe StripePlanFetcher do
let(:faux_plan) do
double("plan",
id: "starter",
nickname: "Starter",
amount: 995)
end
it "fetches and stores plans" do
expect(Stripe::Plan).to receive(:all).and_return([faux_plan])
expect(Plan).to receive(:create).with({
stripe_id: "starter",
name: "Starter",
amount: 995
})
StripePlanFetcher.store_locally
end
it "checks and updates plans" do
expect(Stripe::Plan).to receive(:all).and_return([faux_plan])
expect(Plan).to receive(:find_by).
with(stripe_id: faux_plan.id).
and_return(plan = double)
expect(plan).to receive(:update).with({
name: "Starter",
amount: 995
})
expect(Plan).to_not receive(:create)
StripePlanFetcher.store_locally
end
end
除了测试规范失败之外,当我访问 subdomain.lvh.me:3000 并完成注册用户 + 输入测试 cc 信息的过程时,Stripe 过程似乎正在工作 - 在一定程度上 - 但我是重定向到这个错误:
Stripe::InvalidRequestError in Accounts::PlansController#chosen
Received unknown parameter: source
customer = Stripe::Customer.retrieve(current_account.stripe_customer_id)
plan = Plan.find(params[:account][:plan_id])
subscription = customer.subscriptions.create(
plan: plan.stripe_id,
source: params[:token]
)
我的计划控制器代码如下所示:
class Accounts::PlansController < Accounts::BaseController
skip_before_action :subscription_required!
def choose
@plans = Plan.order(:amount)
end
def chosen
customer = Stripe::Customer.retrieve(current_account.stripe_customer_id)
plan = Plan.find(params[:account][:plan_id])
subscription = customer.subscriptions.create(
plan: plan.stripe_id,
source: params[:token]
)
current_account.plan = plan
current_account.stripe_subscription_id = subscription.id
current_account.stripe_subscription_status = "active"
current_account.save
flash[:notice] = "Your account has been created."
redirect_to root_url(subdomain: current_account.subdomain)
end
def cancel
customer = Stripe::Customer.retrieve(current_account.stripe_customer_id)
subscription = customer.subscriptions.retrieve(current_account.stripe_subscription_id).delete
if subscription.status == "canceled"
current_account.update_column(:stripe_subscription_id, nil)
flash[:notice] = "Your subscription to Twist has been cancelled."
redirect_to root_url(subdomain: nil)
end
end
end
--- 更新 1 ---
架构计划:
create_table "plans", force: :cascade do |t|
t.string "name"
t.integer "amount"
t.string "stripe_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
架构帐户:
create_table "accounts", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "owner_id"
t.string "subdomain"
t.string "stripe_customer_id"
t.integer "plan_id"
t.string "stripe_subscription_id"
t.index ["plan_id"], name: "index_accounts_on_plan_id", using: :btree
t.index ["subdomain"], name: "index_accounts_on_subdomain", using: :btree
end
条纹计划提取器
class StripePlanFetcher
def self.store_locally
Stripe::Plan.all.each do |plan|
if local_plan = Plan.find_by(stripe_id: plan.id)
local_plan.update(
name: plan.nickname,
amount: plan.amount
)
else
Plan.create(
name: plan.nickname,
amount: plan.amount,
stripe_id: plan.id
)
end
end
end
end
解决方案
问题是您正在尝试使用属性创建订阅plan = "starter"
,但“计划”不是订阅的属性,它是对计划记录的引用。大多数可能的订阅有一个名为的属性plan_id
(在未来发布所有模式 - 在这种情况下,知道订阅的模式会有所帮助)
因此,在这种情况下,您可能需要声明plan
如下内容:
@plan = Plan.find_by(name: 'starter')
customer.subscriptions.create(plan: @plan)
推荐阅读
- yaml - 无法将 yaml 文件转换为 toml 文件
- java - 如何让休眠以急切地获取 EmbeddedId?
- git - Git 维护日志
- vba - 这个长公式导致语法错误有解决方案吗?
- keras - Seq2seq 推理模型仅预测起始标记
- python - 在python中替换JSON键值和分解值
- python - 如何在 BeautifulSoup 中获取嵌套标签的所有元素?
- ios - 在重新排序单元格时,同时使用 NSDiffableDataSourceSnapshot 和 NSDiffableDataSourceSectionSnapshot 可能会导致 UICollectionView 中的断言失败
- react-native - 最近我开始使用 react-native-modalize 但遇到了单元测试的问题。如何对 react-native-modalize 进行单元测试
- go - golang,测试中的 goroutines 竞争条件