FEATURE: Allow one-time purchases on products (#18)
Building off the foundation of using the Prices API, this PR adds the ability to create a one-time purchase plan for any product, which then can add a user to the specified plan group.
Some things to be aware of:
One-time purchases cannot have trials.
One-time purchases use the Invoice API instead of Subscriptions. Invoices are created then charged immediately.
Users should receive emails for these invoices directly from Stripe just like subscriptions.
This commit is contained in:
@@ -98,7 +98,12 @@ module DiscourseSubscriptions
|
||||
|
||||
it "creates a plan with an interval" do
|
||||
::Stripe::Price.expects(:create).with(has_entry(recurring: { interval: 'week' }))
|
||||
post "/s/admin/plans.json", params: { interval: 'week', metadata: { group_name: '' } }
|
||||
post "/s/admin/plans.json", params: { type: 'recurring', interval: 'week', metadata: { group_name: '' } }
|
||||
end
|
||||
|
||||
it "creates a plan as a one-time purchase" do
|
||||
::Stripe::Price.expects(:create).with(Not(has_key(:recurring)))
|
||||
post "/s/admin/plans.json", params: { metadata: { group_name: '' } }
|
||||
end
|
||||
|
||||
it "creates a plan with an amount" do
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
module DiscourseSubscriptions
|
||||
RSpec.describe InvoicesController do
|
||||
describe "index" do
|
||||
describe "not authenticated" do
|
||||
it "does not list the invoices" do
|
||||
::Stripe::Invoice.expects(:list).never
|
||||
get "/s/invoices.json"
|
||||
expect(response.status).to eq 403
|
||||
end
|
||||
end
|
||||
|
||||
describe "authenticated" do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:stripe_customer) { { id: 'cus_id4567' } }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
describe "other user invoices" do
|
||||
it "does not list the invoices" do
|
||||
::Stripe::Invoice.expects(:list).never
|
||||
get "/s/invoices.json", params: { user_id: 999999 }
|
||||
end
|
||||
end
|
||||
|
||||
describe "own invoices" do
|
||||
context "stripe customer does not exist" do
|
||||
it "lists empty" do
|
||||
::Stripe::Invoice.expects(:list).never
|
||||
get "/s/invoices.json", params: { user_id: user.id }
|
||||
expect(response.body).to eq "[]"
|
||||
end
|
||||
end
|
||||
|
||||
context "stripe customer exists" do
|
||||
before do
|
||||
DiscourseSubscriptions::Customer.create_customer(user, stripe_customer)
|
||||
end
|
||||
|
||||
it "lists the invoices" do
|
||||
::Stripe::Invoice.expects(:list).with(customer: 'cus_id4567')
|
||||
get "/s/invoices.json", params: { user_id: user.id }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,50 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
module DiscourseSubscriptions
|
||||
RSpec.describe PaymentsController do
|
||||
context "not authenticated" do
|
||||
it "does not create a payment intent" do
|
||||
::Stripe::PaymentIntent.expects(:create).never
|
||||
|
||||
post "/s/payments.json", params: {
|
||||
payment_method: 'pm_123',
|
||||
amount: 999,
|
||||
currency: 'gdp'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "authenticated" do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
describe "create" do
|
||||
it "creates a payment intent" do
|
||||
::Stripe::Customer.expects(:create).with(
|
||||
email: user.email
|
||||
).returns(id: 'cus_87653')
|
||||
|
||||
::Stripe::PaymentIntent.expects(:create).with(
|
||||
payment_method_types: ['card'],
|
||||
payment_method: 'pm_123',
|
||||
amount: '999',
|
||||
currency: 'gdp',
|
||||
confirm: true,
|
||||
customer: 'cus_87653'
|
||||
)
|
||||
|
||||
post "/s/payments.json", params: {
|
||||
payment_method: 'pm_123',
|
||||
amount: 999,
|
||||
currency: 'gdp'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -22,6 +22,7 @@ module DiscourseSubscriptions
|
||||
describe "create" do
|
||||
it "creates a subscription" do
|
||||
::Stripe::Price.expects(:retrieve).returns(
|
||||
type: 'recurring',
|
||||
product: 'product_12345',
|
||||
metadata: {
|
||||
group_name: 'awesome',
|
||||
@@ -41,8 +42,29 @@ module DiscourseSubscriptions
|
||||
}.to change { DiscourseSubscriptions::Customer.count }
|
||||
end
|
||||
|
||||
it "creates a one time payment subscription" do
|
||||
::Stripe::Price.expects(:retrieve).returns(
|
||||
type: 'one_time',
|
||||
product: 'product_12345',
|
||||
metadata: {
|
||||
group_name: 'awesome'
|
||||
}
|
||||
)
|
||||
|
||||
::Stripe::InvoiceItem.expects(:create)
|
||||
|
||||
::Stripe::Invoice.expects(:create).returns(id: 'in_123')
|
||||
|
||||
::Stripe::Invoice.expects(:pay).returns(status: 'paid')
|
||||
|
||||
expect {
|
||||
post '/s/subscriptions.json', params: { plan: 'plan_1234', customer: 'cus_1234' }
|
||||
}.to change { DiscourseSubscriptions::Customer.count }
|
||||
|
||||
end
|
||||
|
||||
it "creates a customer model" do
|
||||
::Stripe::Price.expects(:retrieve).returns(metadata: {})
|
||||
::Stripe::Price.expects(:retrieve).returns(type: 'recurring', metadata: {})
|
||||
::Stripe::Subscription.expects(:create).returns(status: 'active')
|
||||
|
||||
expect {
|
||||
@@ -61,13 +83,13 @@ module DiscourseSubscriptions
|
||||
end
|
||||
|
||||
it "does not add the user to the admins group" do
|
||||
::Stripe::Price.expects(:retrieve).returns(metadata: { group_name: 'admins' })
|
||||
::Stripe::Price.expects(:retrieve).returns(type: 'recurring', metadata: { group_name: 'admins' })
|
||||
post "/s/subscriptions.json", params: { plan: 'plan_1234', customer: 'cus_1234' }
|
||||
expect(user.admin).to eq false
|
||||
end
|
||||
|
||||
it "does not add the user to other group" do
|
||||
::Stripe::Price.expects(:retrieve).returns(metadata: { group_name: 'other' })
|
||||
::Stripe::Price.expects(:retrieve).returns(type: 'recurring', metadata: { group_name: 'other' })
|
||||
post "/s/subscriptions.json", params: { plan: 'plan_1234', customer: 'cus_1234' }
|
||||
expect(user.groups).to be_empty
|
||||
end
|
||||
@@ -75,7 +97,7 @@ module DiscourseSubscriptions
|
||||
|
||||
context "plan has group in metadata" do
|
||||
before do
|
||||
::Stripe::Price.expects(:retrieve).returns(metadata: { group_name: group_name })
|
||||
::Stripe::Price.expects(:retrieve).returns(type: 'recurring', metadata: { group_name: group_name })
|
||||
end
|
||||
|
||||
it "does not add the user to the group when subscription fails" do
|
||||
|
||||
Reference in New Issue
Block a user