reji 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +73 -0
- data/.rubocop_todo.yml +31 -0
- data/Appraisals +2 -0
- data/Gemfile +1 -1
- data/README.md +41 -17
- data/Rakefile +8 -2
- data/app/controllers/reji/payment_controller.rb +4 -4
- data/app/controllers/reji/webhook_controller.rb +51 -62
- data/app/views/payment.html.erb +4 -4
- data/app/views/receipt.html.erb +16 -16
- data/config/routes.rb +2 -0
- data/gemfiles/rails_5.0.gemfile +9 -9
- data/gemfiles/rails_5.1.gemfile +7 -9
- data/gemfiles/rails_5.2.gemfile +7 -9
- data/gemfiles/rails_6.0.gemfile +7 -9
- data/lib/generators/reji/install/install_generator.rb +20 -24
- data/lib/generators/reji/install/templates/reji.rb +2 -2
- data/lib/reji.rb +12 -8
- data/lib/reji/concerns/manages_customer.rb +25 -29
- data/lib/reji/concerns/manages_invoices.rb +37 -44
- data/lib/reji/concerns/manages_payment_methods.rb +45 -62
- data/lib/reji/concerns/manages_subscriptions.rb +13 -13
- data/lib/reji/concerns/performs_charges.rb +7 -7
- data/lib/reji/concerns/prorates.rb +1 -1
- data/lib/reji/configuration.rb +2 -2
- data/lib/reji/engine.rb +2 -0
- data/lib/reji/errors.rb +9 -9
- data/lib/reji/invoice.rb +57 -56
- data/lib/reji/invoice_line_item.rb +21 -23
- data/lib/reji/payment.rb +9 -5
- data/lib/reji/payment_method.rb +8 -4
- data/lib/reji/subscription.rb +165 -183
- data/lib/reji/subscription_builder.rb +41 -49
- data/lib/reji/subscription_item.rb +26 -26
- data/lib/reji/tax.rb +8 -10
- data/lib/reji/version.rb +1 -1
- data/reji.gemspec +5 -4
- data/spec/dummy/app/models/user.rb +3 -7
- data/spec/dummy/application.rb +3 -7
- data/spec/dummy/db/schema.rb +3 -4
- data/spec/feature/charges_spec.rb +1 -1
- data/spec/feature/customer_spec.rb +1 -1
- data/spec/feature/invoices_spec.rb +6 -6
- data/spec/feature/multiplan_subscriptions_spec.rb +51 -53
- data/spec/feature/payment_methods_spec.rb +25 -25
- data/spec/feature/pending_updates_spec.rb +26 -26
- data/spec/feature/subscriptions_spec.rb +78 -78
- data/spec/feature/webhooks_spec.rb +72 -72
- data/spec/spec_helper.rb +2 -2
- data/spec/support/feature_helpers.rb +6 -12
- data/spec/unit/customer_spec.rb +13 -13
- data/spec/unit/invoice_line_item_spec.rb +12 -14
- data/spec/unit/invoice_spec.rb +7 -9
- data/spec/unit/payment_spec.rb +3 -3
- data/spec/unit/subscription_spec.rb +29 -30
- metadata +26 -11
- data/Gemfile.lock +0 -133
@@ -55,7 +55,7 @@ describe 'charges', type: :request do
|
|
55
55
|
begin
|
56
56
|
user.charge(1000, 'pm_card_threeDSecure2Required')
|
57
57
|
|
58
|
-
raise RSpec::Expectations::ExpectationNotMetError
|
58
|
+
raise RSpec::Expectations::ExpectationNotMetError, 'Expected exception PaymentActionRequiredError was not thrown.'
|
59
59
|
rescue Reji::PaymentActionRequiredError => e
|
60
60
|
# Assert that the payment needs an extra action.
|
61
61
|
expect(e.payment.requires_action).to be true
|
@@ -7,7 +7,7 @@ describe 'customer', type: :request do
|
|
7
7
|
user = create_customer('customers_in_stripe_can_be_updated')
|
8
8
|
user.create_as_stripe_customer
|
9
9
|
|
10
|
-
customer = user.update_stripe_customer({:
|
10
|
+
customer = user.update_stripe_customer({ description: 'Van Cam' })
|
11
11
|
|
12
12
|
expect(customer.description).to eq('Van Cam')
|
13
13
|
end
|
@@ -6,9 +6,9 @@ describe 'invoices', type: :request do
|
|
6
6
|
it 'test_require_stripe_customer_for_invoicing' do
|
7
7
|
user = create_customer('require_stripe_customer_for_invoicing')
|
8
8
|
|
9
|
-
expect
|
9
|
+
expect do
|
10
10
|
user.invoice
|
11
|
-
|
11
|
+
end.to raise_error(Reji::InvalidCustomerError)
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'test_invoicing_fails_with_nothing_to_invoice' do
|
@@ -53,9 +53,9 @@ describe 'invoices', type: :request do
|
|
53
53
|
user.update_default_payment_method('pm_card_visa')
|
54
54
|
invoice = user.invoice_for('Rails Reji', 1000)
|
55
55
|
|
56
|
-
expect
|
56
|
+
expect do
|
57
57
|
other_user.find_invoice(invoice.id)
|
58
|
-
|
58
|
+
end.to raise_error(Reji::InvalidInvoiceError, "The invoice `#{invoice.id}` does not belong to this customer `#{other_user.stripe_id}`.")
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'test_find_invoice_by_id_or_fail' do
|
@@ -66,8 +66,8 @@ describe 'invoices', type: :request do
|
|
66
66
|
user.update_default_payment_method('pm_card_visa')
|
67
67
|
invoice = user.invoice_for('Rails Reji', 1000)
|
68
68
|
|
69
|
-
expect
|
69
|
+
expect do
|
70
70
|
other_user.find_invoice_or_fail(invoice.id)
|
71
|
-
|
71
|
+
end.to raise_error(Reji::AccessDeniedHttpError)
|
72
72
|
end
|
73
73
|
end
|
@@ -10,47 +10,47 @@ describe 'multiplan subscriptions', type: :request do
|
|
10
10
|
@premium_plan_id = "#{stripe_prefix}monthly-20-premium-#{SecureRandom.hex(5)}"
|
11
11
|
|
12
12
|
Stripe::Product.create({
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
13
|
+
id: @product_id,
|
14
|
+
name: 'Rails Reji Test Product',
|
15
|
+
type: 'service',
|
16
16
|
})
|
17
17
|
|
18
18
|
Stripe::Plan.create({
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
19
|
+
id: @plan_id,
|
20
|
+
nickname: 'Monthly $10',
|
21
|
+
currency: 'USD',
|
22
|
+
interval: 'month',
|
23
|
+
billing_scheme: 'per_unit',
|
24
|
+
amount: 1000,
|
25
|
+
product: @product_id,
|
26
26
|
})
|
27
27
|
|
28
28
|
Stripe::Plan.create({
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
29
|
+
id: @other_plan_id,
|
30
|
+
nickname: 'Monthly $10 Other',
|
31
|
+
currency: 'USD',
|
32
|
+
interval: 'month',
|
33
|
+
billing_scheme: 'per_unit',
|
34
|
+
amount: 1000,
|
35
|
+
product: @product_id,
|
36
36
|
})
|
37
37
|
|
38
38
|
Stripe::Plan.create({
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
39
|
+
id: @premium_plan_id,
|
40
|
+
nickname: 'Monthly $20 Premium',
|
41
|
+
currency: 'USD',
|
42
|
+
interval: 'month',
|
43
|
+
billing_scheme: 'per_unit',
|
44
|
+
amount: 2000,
|
45
|
+
product: @product_id,
|
46
46
|
})
|
47
47
|
|
48
48
|
@tax_rate_id = Stripe::TaxRate.create({
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
49
|
+
display_name: 'VAT',
|
50
|
+
description: 'VAT Belgium',
|
51
|
+
jurisdiction: 'BE',
|
52
|
+
percentage: 21,
|
53
|
+
inclusive: false,
|
54
54
|
}).id
|
55
55
|
end
|
56
56
|
|
@@ -64,7 +64,7 @@ describe 'multiplan subscriptions', type: :request do
|
|
64
64
|
it 'test_customers_can_have_multiplan_subscriptions' do
|
65
65
|
user = create_customer('customers_can_have_multiplan_subscriptions')
|
66
66
|
|
67
|
-
user.plan_tax_rates = {@other_plan_id => [@tax_rate_id]}
|
67
|
+
user.plan_tax_rates = { @other_plan_id => [@tax_rate_id] }
|
68
68
|
|
69
69
|
subscription = user.new_subscription('main', [@plan_id, @other_plan_id])
|
70
70
|
.plan(@premium_plan_id, 5)
|
@@ -124,11 +124,11 @@ describe 'multiplan subscriptions', type: :request do
|
|
124
124
|
it 'test_customers_cannot_remove_the_last_plan' do
|
125
125
|
user = create_customer('customers_cannot_remove_the_last_plan')
|
126
126
|
|
127
|
-
subscription =
|
127
|
+
subscription = create_subscription_with_single_plan(user)
|
128
128
|
|
129
|
-
expect
|
129
|
+
expect do
|
130
130
|
subscription.remove_plan(@plan_id)
|
131
|
-
|
131
|
+
end.to raise_error(Reji::SubscriptionUpdateFailureError)
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'test_multiplan_subscriptions_can_be_resumed' do
|
@@ -152,11 +152,11 @@ describe 'multiplan subscriptions', type: :request do
|
|
152
152
|
it 'test_plan_is_required_when_updating_quantities_for_multiplan_subscriptions' do
|
153
153
|
user = create_customer('plan_is_required_when_updating_quantities_for_multiplan_subscriptions')
|
154
154
|
|
155
|
-
subscription =
|
155
|
+
subscription = create_subscription_with_multiple_plans(user)
|
156
156
|
|
157
|
-
expect
|
157
|
+
expect do
|
158
158
|
subscription.update_quantity(5)
|
159
|
-
|
159
|
+
end.to raise_error(ArgumentError)
|
160
160
|
end
|
161
161
|
|
162
162
|
it 'test_subscription_item_quantities_can_be_updated' do
|
@@ -227,7 +227,7 @@ describe 'multiplan subscriptions', type: :request do
|
|
227
227
|
|
228
228
|
subscription = user.new_subscription('main', @plan_id).create('pm_card_visa')
|
229
229
|
|
230
|
-
item = subscription.items.first.swap(@other_plan_id, {:
|
230
|
+
item = subscription.items.first.swap(@other_plan_id, { quantity: 3 })
|
231
231
|
|
232
232
|
expect(subscription.items.count).to eq(1)
|
233
233
|
expect(subscription.stripe_plan).to eq(@other_plan_id)
|
@@ -279,39 +279,37 @@ describe 'multiplan subscriptions', type: :request do
|
|
279
279
|
expect(user.upcoming_invoice.raw_total).to eq(2000)
|
280
280
|
end
|
281
281
|
|
282
|
-
protected
|
283
|
-
|
284
282
|
# Create a subscription with a single plan.
|
285
|
-
def create_subscription_with_single_plan(user)
|
283
|
+
protected def create_subscription_with_single_plan(user)
|
286
284
|
subscription = user.subscriptions.create({
|
287
|
-
:
|
288
|
-
:
|
289
|
-
:
|
290
|
-
:
|
291
|
-
:
|
285
|
+
name: 'main',
|
286
|
+
stripe_id: 'sub_foo',
|
287
|
+
stripe_plan: @plan_id,
|
288
|
+
quantity: 1,
|
289
|
+
stripe_status: 'active',
|
292
290
|
})
|
293
291
|
|
294
292
|
subscription.items.create({
|
295
|
-
:
|
296
|
-
:
|
297
|
-
:
|
293
|
+
stripe_id: 'it_foo',
|
294
|
+
stripe_plan: @plan_id,
|
295
|
+
quantity: 1,
|
298
296
|
})
|
299
297
|
|
300
298
|
subscription
|
301
299
|
end
|
302
300
|
|
303
301
|
# Create a subscription with multiple plans.
|
304
|
-
def create_subscription_with_multiple_plans(user)
|
305
|
-
subscription =
|
302
|
+
protected def create_subscription_with_multiple_plans(user)
|
303
|
+
subscription = create_subscription_with_single_plan(user)
|
306
304
|
|
307
305
|
subscription.stripe_plan = nil
|
308
306
|
subscription.quantity = nil
|
309
307
|
subscription.save
|
310
308
|
|
311
309
|
subscription.items.new({
|
312
|
-
:
|
313
|
-
:
|
314
|
-
:
|
310
|
+
stripe_id: 'it_foo',
|
311
|
+
stripe_plan: @other_plan_id,
|
312
|
+
quantity: 1,
|
315
313
|
})
|
316
314
|
|
317
315
|
subscription
|
@@ -3,13 +3,13 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe 'payment_methods', type: :request do
|
6
|
-
it '
|
6
|
+
it 'test_we_can_start_a_new_setup_intent_session' do
|
7
7
|
user = create_customer('we_can_start_a_new_setup_intent_session')
|
8
8
|
setup_intent = user.create_setup_intent
|
9
9
|
expect(setup_intent).to be_an_instance_of(Stripe::SetupIntent)
|
10
10
|
end
|
11
11
|
|
12
|
-
it '
|
12
|
+
it 'test_we_can_add_payment_methods' do
|
13
13
|
user = create_customer('we_can_add_payment_methods')
|
14
14
|
user.create_as_stripe_customer
|
15
15
|
|
@@ -18,34 +18,34 @@ describe 'payment_methods', type: :request do
|
|
18
18
|
expect(payment_method).to be_an_instance_of(Reji::PaymentMethod)
|
19
19
|
expect(payment_method.card.brand).to eq('visa')
|
20
20
|
expect(payment_method.card.last4).to eq('4242')
|
21
|
-
expect(user.
|
22
|
-
expect(user.
|
21
|
+
expect(user.payment_method?).to be true
|
22
|
+
expect(user.default_payment_method?).to be false
|
23
23
|
end
|
24
24
|
|
25
|
-
it '
|
25
|
+
it 'test_we_can_remove_payment_methods' do
|
26
26
|
user = create_customer('we_can_remove_payment_methods')
|
27
27
|
user.create_as_stripe_customer
|
28
28
|
|
29
29
|
payment_method = user.add_payment_method('pm_card_visa')
|
30
30
|
|
31
31
|
expect(user.payment_methods.count).to eq(1)
|
32
|
-
expect(user.
|
32
|
+
expect(user.payment_method?).to be true
|
33
33
|
|
34
34
|
user.remove_payment_method(payment_method.as_stripe_payment_method)
|
35
35
|
|
36
36
|
expect(user.payment_methods.count).to eq(0)
|
37
|
-
expect(user.
|
37
|
+
expect(user.payment_method?).to be false
|
38
38
|
end
|
39
39
|
|
40
|
-
it '
|
40
|
+
it 'test_we_can_remove_the_default_payment_method' do
|
41
41
|
user = create_customer('we_can_remove_the_default_payment_method')
|
42
42
|
user.create_as_stripe_customer
|
43
43
|
|
44
44
|
payment_method = user.update_default_payment_method('pm_card_visa')
|
45
45
|
|
46
46
|
expect(user.payment_methods.count).to eq(1)
|
47
|
-
expect(user.
|
48
|
-
expect(user.
|
47
|
+
expect(user.payment_method?).to be true
|
48
|
+
expect(user.default_payment_method?).to be true
|
49
49
|
|
50
50
|
user.remove_payment_method(payment_method.as_stripe_payment_method)
|
51
51
|
|
@@ -53,11 +53,11 @@ describe 'payment_methods', type: :request do
|
|
53
53
|
expect(user.default_payment_method).to be_nil
|
54
54
|
expect(user.card_brand).to be_nil
|
55
55
|
expect(user.card_last_four).to be_nil
|
56
|
-
expect(user.
|
57
|
-
expect(user.
|
56
|
+
expect(user.payment_method?).to be false
|
57
|
+
expect(user.default_payment_method?).to be false
|
58
58
|
end
|
59
59
|
|
60
|
-
it '
|
60
|
+
it 'test_we_can_set_a_default_payment_method' do
|
61
61
|
user = create_customer('we_can_set_a_default_payment_method')
|
62
62
|
user.create_as_stripe_customer
|
63
63
|
|
@@ -66,7 +66,7 @@ describe 'payment_methods', type: :request do
|
|
66
66
|
expect(payment_method).to be_an_instance_of(Reji::PaymentMethod)
|
67
67
|
expect(payment_method.card.brand).to eq('visa')
|
68
68
|
expect(payment_method.card.last4).to eq('4242')
|
69
|
-
expect(user.
|
69
|
+
expect(user.default_payment_method?).to be true
|
70
70
|
|
71
71
|
payment_method = user.default_payment_method
|
72
72
|
|
@@ -75,10 +75,10 @@ describe 'payment_methods', type: :request do
|
|
75
75
|
expect(payment_method.card.last4).to eq('4242')
|
76
76
|
end
|
77
77
|
|
78
|
-
it '
|
78
|
+
it 'test_legacy_we_can_retrieve_an_old_default_source_as_a_default_payment_method' do
|
79
79
|
user = create_customer('we_can_retrieve_an_old_default_source_as_a_default_payment_method')
|
80
80
|
customer = user.create_as_stripe_customer
|
81
|
-
card = Stripe::Customer.create_source(customer.id, {:
|
81
|
+
card = Stripe::Customer.create_source(customer.id, { source: 'tok_visa' }, user.stripe_options)
|
82
82
|
customer.default_source = card.id
|
83
83
|
customer.save
|
84
84
|
|
@@ -89,15 +89,15 @@ describe 'payment_methods', type: :request do
|
|
89
89
|
expect(payment_method.last4).to eq('4242')
|
90
90
|
end
|
91
91
|
|
92
|
-
it '
|
92
|
+
it 'test_we_can_retrieve_all_payment_methods' do
|
93
93
|
user = create_customer('we_can_retrieve_all_payment_methods')
|
94
94
|
customer = user.create_as_stripe_customer
|
95
95
|
|
96
96
|
payment_method = Stripe::PaymentMethod.retrieve('pm_card_visa', user.stripe_options)
|
97
|
-
payment_method.attach({:
|
97
|
+
payment_method.attach({ customer: customer.id })
|
98
98
|
|
99
99
|
payment_method = Stripe::PaymentMethod.retrieve('pm_card_mastercard', user.stripe_options)
|
100
|
-
payment_method.attach({:
|
100
|
+
payment_method.attach({ customer: customer.id })
|
101
101
|
|
102
102
|
payment_methods = user.payment_methods
|
103
103
|
|
@@ -106,14 +106,14 @@ describe 'payment_methods', type: :request do
|
|
106
106
|
expect(payment_methods.last.card.brand).to eq('visa')
|
107
107
|
end
|
108
108
|
|
109
|
-
it '
|
109
|
+
it 'test_we_can_sync_the_default_payment_method_from_stripe' do
|
110
110
|
user = create_customer('we_can_sync_the_payment_method_from_stripe')
|
111
111
|
customer = user.create_as_stripe_customer
|
112
112
|
|
113
113
|
payment_method = Stripe::PaymentMethod.retrieve('pm_card_visa', user.stripe_options)
|
114
|
-
payment_method.attach({:
|
114
|
+
payment_method.attach({ customer: customer.id })
|
115
115
|
|
116
|
-
customer.invoice_settings = {:
|
116
|
+
customer.invoice_settings = { default_payment_method: payment_method.id }
|
117
117
|
|
118
118
|
customer.save
|
119
119
|
|
@@ -126,15 +126,15 @@ describe 'payment_methods', type: :request do
|
|
126
126
|
expect(user.card_last_four).to eq('4242')
|
127
127
|
end
|
128
128
|
|
129
|
-
it '
|
129
|
+
it 'test_we_delete_all_payment_methods' do
|
130
130
|
user = create_customer('we_delete_all_payment_methods')
|
131
131
|
customer = user.create_as_stripe_customer
|
132
132
|
|
133
133
|
payment_method = Stripe::PaymentMethod.retrieve('pm_card_visa', user.stripe_options)
|
134
|
-
payment_method.attach({:
|
134
|
+
payment_method.attach({ customer: customer.id })
|
135
135
|
|
136
136
|
payment_method = Stripe::PaymentMethod.retrieve('pm_card_mastercard', user.stripe_options)
|
137
|
-
payment_method.attach({:
|
137
|
+
payment_method.attach({ customer: customer.id })
|
138
138
|
|
139
139
|
payment_methods = user.payment_methods
|
140
140
|
|
@@ -10,39 +10,39 @@ describe 'pending updates', type: :request do
|
|
10
10
|
@premium_plan_id = "#{stripe_prefix}monthly-20-premium-#{SecureRandom.hex(5)}"
|
11
11
|
|
12
12
|
Stripe::Product.create({
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
13
|
+
id: @product_id,
|
14
|
+
name: 'Rails Reji Test Product',
|
15
|
+
type: 'service',
|
16
16
|
})
|
17
17
|
|
18
18
|
Stripe::Plan.create({
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
19
|
+
id: @plan_id,
|
20
|
+
nickname: 'Monthly $10',
|
21
|
+
currency: 'USD',
|
22
|
+
interval: 'month',
|
23
|
+
billing_scheme: 'per_unit',
|
24
|
+
amount: 1000,
|
25
|
+
product: @product_id,
|
26
26
|
})
|
27
27
|
|
28
28
|
Stripe::Plan.create({
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
29
|
+
id: @other_plan_id,
|
30
|
+
nickname: 'Monthly $10 Other',
|
31
|
+
currency: 'USD',
|
32
|
+
interval: 'month',
|
33
|
+
billing_scheme: 'per_unit',
|
34
|
+
amount: 1000,
|
35
|
+
product: @product_id,
|
36
36
|
})
|
37
37
|
|
38
38
|
Stripe::Plan.create({
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
39
|
+
id: @premium_plan_id,
|
40
|
+
nickname: 'Monthly $20 Premium',
|
41
|
+
currency: 'USD',
|
42
|
+
interval: 'month',
|
43
|
+
billing_scheme: 'per_unit',
|
44
|
+
amount: 2000,
|
45
|
+
product: @product_id,
|
46
46
|
})
|
47
47
|
end
|
48
48
|
|
@@ -65,8 +65,8 @@ describe 'pending updates', type: :request do
|
|
65
65
|
# Attempt to swap and pay with a faulty card.
|
66
66
|
subscription = subscription.error_if_payment_fails.swap_and_invoice(@premium_plan_id)
|
67
67
|
|
68
|
-
raise RSpec::Expectations::ExpectationNotMetError
|
69
|
-
rescue Stripe::CardError =>
|
68
|
+
raise RSpec::Expectations::ExpectationNotMetError, 'Expected exception PaymentFailureError was not thrown.'
|
69
|
+
rescue Stripe::CardError => _e
|
70
70
|
# Assert that the plan was not swapped.
|
71
71
|
expect(subscription.stripe_plan).to eq(@plan_id)
|
72
72
|
|