FEATURE: Validate coupon codes on form submit (#74)

This commit is contained in:
Justin DiRose 2021-06-16 12:54:54 -05:00 committed by GitHub
parent 5f9a84242b
commit 8ab7a63167
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 43 deletions

View File

@ -65,8 +65,13 @@ module DiscourseSubscriptions
begin
customer = create_customer(params[:source])
plan = ::Stripe::Price.retrieve(params[:plan])
promo_code = ::Stripe::PromotionCode.list({ code: params[:promo] }) if params[:promo].present?
promo_code = promo_code[:data][0] if promo_code && promo_code[:data] # we assume promo codes have a unique name
if params[:promo].present?
promo_code = ::Stripe::PromotionCode.list({ code: params[:promo] })
promo_code = promo_code[:data][0] # we assume promo codes have a unique name
return render_json_error I18n.t("js.discourse_subscriptions.subscribe.invalid_coupon") if promo_code.blank?
end
recurring_plan = plan[:type] == 'recurring'

View File

@ -121,7 +121,9 @@ export default Controller.extend({
}
})
.catch((result) => {
bootbox.alert(result.errorThrown);
bootbox.alert(
result.jqXHR.responseJSON.errors[0] || result.errorThrown
);
this.set("loading", false);
});
},

View File

@ -100,6 +100,7 @@ en:
view_past: View past purchases
no_products: There are currently no products available.
unauthenticated: Log in or create an account to subscribe.
invalid_coupon: You entered an invalid coupon code. Please try again.
card:
title: Payment
customer:

View File

@ -219,59 +219,87 @@ module DiscourseSubscriptions
end
context "with promo code" do
before do
::Stripe::PromotionCode.expects(:list).with({ code: '123' }).returns(
data: [{
id: 'promo123',
coupon: { id: 'c123' }
}]
)
context "invalid code" do
it "prevents use of invalid coupon codes" do
::Stripe::Price.expects(:retrieve).returns(
type: 'recurring',
product: 'product_12345',
metadata: {
group_name: 'awesome',
trial_period_days: 0
}
)
::Stripe::PromotionCode.expects(:list).with({ code: 'invalid' }).returns(
data: []
)
post "/s/create.json", params: { plan: 'plan_1234', source: 'tok_1234', promo: 'invalid' }
data = response.parsed_body
expect(data["errors"]).not_to be_blank
end
end
it "applies promo code to recurring subscription" do
::Stripe::Price.expects(:retrieve).returns(
type: 'recurring',
product: 'product_12345',
metadata: {
group_name: 'awesome',
trial_period_days: 0
}
)
context "valid code" do
before do
::Stripe::PromotionCode.expects(:list).with({ code: '123' }).returns(
data: [{
id: 'promo123',
coupon: { id: 'c123' }
}]
)
end
::Stripe::Subscription.expects(:create).with(
customer: 'cus_1234',
items: [ price: 'plan_1234' ],
metadata: { user_id: user.id, username: user.username_lower },
trial_period_days: 0,
promotion_code: 'promo123'
).returns(status: 'active', customer: 'cus_1234')
it "applies promo code to recurring subscription" do
::Stripe::Price.expects(:retrieve).returns(
type: 'recurring',
product: 'product_12345',
metadata: {
group_name: 'awesome',
trial_period_days: 0
}
)
post "/s/create.json", params: { plan: 'plan_1234', source: 'tok_1234', promo: '123' }
::Stripe::Subscription.expects(:create).with(
customer: 'cus_1234',
items: [ price: 'plan_1234' ],
metadata: { user_id: user.id, username: user.username_lower },
trial_period_days: 0,
promotion_code: 'promo123'
).returns(status: 'active', customer: 'cus_1234')
end
expect {
post "/s/create.json", params: { plan: 'plan_1234', source: 'tok_1234', promo: '123' }
}.to change { DiscourseSubscriptions::Customer.count }
it "applies promo code to one time purchase" do
::Stripe::Price.expects(:retrieve).returns(
type: 'one_time',
product: 'product_12345',
metadata: {
group_name: 'awesome'
}
)
end
::Stripe::InvoiceItem.expects(:create).with(customer: 'cus_1234', price: 'plan_1234', discounts: [{ coupon: 'c123' }])
it "applies promo code to one time purchase" do
::Stripe::Price.expects(:retrieve).returns(
type: 'one_time',
product: 'product_12345',
metadata: {
group_name: 'awesome'
}
)
::Stripe::Invoice.expects(:create).returns(status: 'open', id: 'in_123')
::Stripe::InvoiceItem.expects(:create).with(customer: 'cus_1234', price: 'plan_1234', discounts: [{ coupon: 'c123' }])
::Stripe::Invoice.expects(:finalize_invoice).returns(id: 'in_123', status: 'open', payment_intent: 'pi_123')
::Stripe::Invoice.expects(:create).returns(status: 'open', id: 'in_123')
::Stripe::Invoice.expects(:retrieve).returns(id: 'in_123', status: 'open', payment_intent: 'pi_123')
::Stripe::Invoice.expects(:finalize_invoice).returns(id: 'in_123', status: 'open', payment_intent: 'pi_123')
::Stripe::PaymentIntent.expects(:retrieve).returns(status: 'successful')
::Stripe::Invoice.expects(:retrieve).returns(id: 'in_123', status: 'open', payment_intent: 'pi_123')
::Stripe::Invoice.expects(:pay).returns(status: 'paid', customer: 'cus_1234')
::Stripe::PaymentIntent.expects(:retrieve).returns(status: 'successful')
post '/s/create.json', params: { plan: 'plan_1234', source: 'tok_1234', promo: '123' }
::Stripe::Invoice.expects(:pay).returns(status: 'paid', customer: 'cus_1234')
expect {
post '/s/create.json', params: { plan: 'plan_1234', source: 'tok_1234', promo: '123' }
}.to change { DiscourseSubscriptions::Customer.count }
end
end
end
end