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 begin
customer = create_customer(params[:source]) customer = create_customer(params[:source])
plan = ::Stripe::Price.retrieve(params[:plan]) 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' recurring_plan = plan[:type] == 'recurring'

View File

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

View File

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

View File

@ -219,59 +219,87 @@ module DiscourseSubscriptions
end end
context "with promo code" do context "with promo code" do
before do context "invalid code" do
::Stripe::PromotionCode.expects(:list).with({ code: '123' }).returns( it "prevents use of invalid coupon codes" do
data: [{ ::Stripe::Price.expects(:retrieve).returns(
id: 'promo123', type: 'recurring',
coupon: { id: 'c123' } 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 end
it "applies promo code to recurring subscription" do context "valid code" do
::Stripe::Price.expects(:retrieve).returns( before do
type: 'recurring', ::Stripe::PromotionCode.expects(:list).with({ code: '123' }).returns(
product: 'product_12345', data: [{
metadata: { id: 'promo123',
group_name: 'awesome', coupon: { id: 'c123' }
trial_period_days: 0 }]
} )
) end
::Stripe::Subscription.expects(:create).with( it "applies promo code to recurring subscription" do
customer: 'cus_1234', ::Stripe::Price.expects(:retrieve).returns(
items: [ price: 'plan_1234' ], type: 'recurring',
metadata: { user_id: user.id, username: user.username_lower }, product: 'product_12345',
trial_period_days: 0, metadata: {
promotion_code: 'promo123' group_name: 'awesome',
).returns(status: 'active', customer: 'cus_1234') 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 end
::Stripe::Price.expects(:retrieve).returns(
type: 'one_time',
product: 'product_12345',
metadata: {
group_name: 'awesome'
}
)
::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 end
end end