Stripe and Rails 5 - Stripe :: InvalidRequestError: Нет такого плана: стартер - PullRequest
0 голосов
/ 06 января 2019

Я почти закончил с книгой Райана Бигга «Мультитенантность с 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

1 Ответ

0 голосов
/ 06 января 2019

Проблема в том, что вы пытаетесь создать подписку с атрибутом plan = "starter", но «план» - это не атрибут подписки, это ссылка на запись плана. В большинстве случаев подписка имеет атрибут plan_id (в будущем посте все схемы - в этом случае знание схемы подписки было бы полезно)

Итак, в этом случае вам, вероятно, нужно объявить, что такое plan:

@plan = Plan.find_by(name: 'starter')

customer.subscriptions.create(plan: @plan)

...