我几乎完成了Ryan Bigg的《 Rails多租户》-第二版书,发现自己在将我的应用程序与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并经历了注册用户+输入测试抄送信息的过程时,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]
)
我对Planning Controller的代码如下:
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
答案 0 :(得分:1)
问题是您正在尝试创建具有属性plan = "starter"
的预订,但是'plan'不是预订的属性,它是对计划记录的引用。多数情况下,订阅都有一个名为plan_id
的属性(以后发布所有架构-在这种情况下,了解订阅的架构会有所帮助)
因此,在这种情况下,您可能需要声明plan
的样子:
@plan = Plan.find_by(name: 'starter')
customer.subscriptions.create(plan: @plan)