stripe-ruby-mock 3.0.1 → 3.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 +5 -5
- data/.github/workflows/rspec_tests.yml +38 -0
- data/.rspec +2 -1
- data/CHANGELOG.md +62 -15
- data/Gemfile +1 -0
- data/README.md +5 -3
- data/lib/stripe_mock/api/client.rb +1 -1
- data/lib/stripe_mock/api/instance.rb +1 -1
- data/lib/stripe_mock/api/webhooks.rb +66 -25
- data/lib/stripe_mock/client.rb +2 -1
- data/lib/stripe_mock/data/list.rb +31 -6
- data/lib/stripe_mock/data.rb +201 -30
- data/lib/stripe_mock/instance.rb +12 -3
- data/lib/stripe_mock/request_handlers/account_links.rb +15 -0
- data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
- data/lib/stripe_mock/request_handlers/charges.rb +11 -4
- data/lib/stripe_mock/request_handlers/checkout_session.rb +179 -0
- data/lib/stripe_mock/request_handlers/customers.rb +22 -13
- data/lib/stripe_mock/request_handlers/ephemeral_key.rb +1 -1
- data/lib/stripe_mock/request_handlers/events.rb +30 -3
- data/lib/stripe_mock/request_handlers/express_login_links.rb +15 -0
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +1 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +36 -12
- data/lib/stripe_mock/request_handlers/invoices.rb +10 -4
- data/lib/stripe_mock/request_handlers/payment_intents.rb +13 -2
- data/lib/stripe_mock/request_handlers/payment_methods.rb +11 -4
- data/lib/stripe_mock/request_handlers/prices.rb +62 -0
- data/lib/stripe_mock/request_handlers/promotion_codes.rb +43 -0
- data/lib/stripe_mock/request_handlers/refunds.rb +13 -2
- data/lib/stripe_mock/request_handlers/setup_intents.rb +16 -9
- data/lib/stripe_mock/request_handlers/sources.rb +12 -6
- data/lib/stripe_mock/request_handlers/subscriptions.rb +120 -21
- data/lib/stripe_mock/request_handlers/tokens.rb +6 -4
- data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +33 -4
- data/lib/stripe_mock/server.rb +2 -2
- data/lib/stripe_mock/test_strategies/base.rb +62 -10
- data/lib/stripe_mock/version.rb +1 -1
- data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/balance.available.json +27 -15
- data/lib/stripe_mock/webhook_fixtures/charge.captured.json +143 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +63 -16
- data/lib/stripe_mock/webhook_fixtures/charge.failed.json +49 -120
- data/lib/stripe_mock/webhook_fixtures/charge.refund.updated.json +35 -0
- data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +145 -50
- data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +114 -43
- data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.json +79 -0
- data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.payment_mode.json +53 -0
- data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.setup_mode.json +45 -0
- data/lib/stripe_mock/webhook_fixtures/customer.created.json +37 -46
- data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +36 -32
- data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +31 -22
- data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -25
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +135 -47
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +134 -45
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +135 -56
- data/lib/stripe_mock/webhook_fixtures/customer.updated.json +38 -47
- data/lib/stripe_mock/webhook_fixtures/invoice.created.json +176 -49
- data/lib/stripe_mock/webhook_fixtures/invoice.finalized.json +171 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.paid.json +171 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_action_required.json +171 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +149 -83
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +149 -90
- data/lib/stripe_mock/webhook_fixtures/invoice.upcoming.json +70 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +178 -50
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +87 -13
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +88 -14
- data/lib/stripe_mock/webhook_fixtures/mandate.updated.json +34 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.amount_capturable_updated.json +170 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.canceled.json +73 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.created.json +86 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +225 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.processing.json +162 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.requires_action.json +191 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +196 -0
- data/lib/stripe_mock/webhook_fixtures/payment_link.created.json +47 -0
- data/lib/stripe_mock/webhook_fixtures/payment_link.updated.json +50 -0
- data/lib/stripe_mock/webhook_fixtures/payment_method.attached.json +63 -0
- data/lib/stripe_mock/webhook_fixtures/payment_method.detached.json +62 -0
- data/lib/stripe_mock/webhook_fixtures/payout.created.json +40 -0
- data/lib/stripe_mock/webhook_fixtures/payout.paid.json +40 -0
- data/lib/stripe_mock/webhook_fixtures/payout.updated.json +46 -0
- data/lib/stripe_mock/webhook_fixtures/plan.created.json +30 -13
- data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +30 -13
- data/lib/stripe_mock/webhook_fixtures/plan.updated.json +34 -14
- data/lib/stripe_mock/webhook_fixtures/price.created.json +42 -0
- data/lib/stripe_mock/webhook_fixtures/price.deleted.json +42 -0
- data/lib/stripe_mock/webhook_fixtures/price.updated.json +48 -0
- data/lib/stripe_mock/webhook_fixtures/product.created.json +19 -13
- data/lib/stripe_mock/webhook_fixtures/product.deleted.json +20 -14
- data/lib/stripe_mock/webhook_fixtures/product.updated.json +24 -15
- data/lib/stripe_mock/webhook_fixtures/quote.accepted.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/quote.canceled.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/quote.created.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/quote.finalized.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.canceled.json +46 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.created.json +51 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.setup_failed.json +100 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.succeeded.json +46 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.canceled.json +119 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.created.json +114 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.released.json +111 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.updated.json +125 -0
- data/lib/stripe_mock/webhook_fixtures/tax_rate.created.json +32 -0
- data/lib/stripe_mock/webhook_fixtures/tax_rate.updated.json +37 -0
- data/lib/stripe_mock.rb +7 -1
- data/spec/instance_spec.rb +7 -7
- data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
- data/spec/list_spec.rb +23 -0
- data/spec/readme_spec.rb +1 -1
- data/spec/server_spec.rb +4 -2
- data/spec/shared_stripe_examples/account_examples.rb +9 -1
- data/spec/shared_stripe_examples/account_link_examples.rb +16 -0
- data/spec/shared_stripe_examples/balance_examples.rb +6 -0
- data/spec/shared_stripe_examples/card_token_examples.rb +17 -21
- data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
- data/spec/shared_stripe_examples/customer_examples.rb +11 -13
- data/spec/shared_stripe_examples/express_login_link_examples.rb +12 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +29 -8
- data/spec/shared_stripe_examples/payment_intent_examples.rb +74 -0
- data/spec/shared_stripe_examples/payment_method_examples.rb +336 -67
- data/spec/shared_stripe_examples/price_examples.rb +223 -0
- data/spec/shared_stripe_examples/product_examples.rb +1 -9
- data/spec/shared_stripe_examples/promotion_code_examples.rb +68 -0
- data/spec/shared_stripe_examples/refund_examples.rb +13 -0
- data/spec/shared_stripe_examples/setup_intent_examples.rb +17 -0
- data/spec/shared_stripe_examples/subscription_examples.rb +327 -9
- data/spec/shared_stripe_examples/transfer_examples.rb +10 -1
- data/spec/shared_stripe_examples/webhook_event_examples.rb +51 -5
- data/spec/spec_helper.rb +4 -0
- data/spec/stripe_mock_spec.rb +2 -2
- data/spec/support/stripe_examples.rb +8 -2
- data/stripe-ruby-mock.gemspec +7 -2
- metadata +72 -15
- data/.travis.yml +0 -28
- data/lib/stripe_mock/request_handlers/checkout.rb +0 -15
- data/spec/shared_stripe_examples/checkout_examples.rb +0 -19
data/lib/stripe_mock/data.rb
CHANGED
@@ -101,6 +101,27 @@ module StripeMock
|
|
101
101
|
}.merge(params)
|
102
102
|
end
|
103
103
|
|
104
|
+
def self.mock_account_link(params = {})
|
105
|
+
now = Time.now.to_i
|
106
|
+
{
|
107
|
+
object: 'account_link',
|
108
|
+
created: now,
|
109
|
+
expires_at: now + 300,
|
110
|
+
url: 'https://connect.stripe.com/setup/c/iB0ph1cPnRLY',
|
111
|
+
data: {}
|
112
|
+
}.merge(params)
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.mock_express_login_link(params = {})
|
116
|
+
now = Time.now.to_i
|
117
|
+
{
|
118
|
+
object: 'login_link',
|
119
|
+
created: now,
|
120
|
+
url: 'https://connect.stripe.com/express/Ln7FfnNpUcCU',
|
121
|
+
data: {}
|
122
|
+
}.merge(params)
|
123
|
+
end
|
124
|
+
|
104
125
|
def self.mock_tax_rate(params)
|
105
126
|
{
|
106
127
|
id: 'test_cus_default',
|
@@ -119,7 +140,7 @@ module StripeMock
|
|
119
140
|
|
120
141
|
def self.mock_customer(sources, params)
|
121
142
|
cus_id = params[:id] || "test_cus_default"
|
122
|
-
currency = params[:currency]
|
143
|
+
currency = params[:currency]
|
123
144
|
sources.each {|source| source[:customer] = cus_id}
|
124
145
|
{
|
125
146
|
email: 'stripe_mock@example.com',
|
@@ -142,12 +163,14 @@ module StripeMock
|
|
142
163
|
sources: {
|
143
164
|
object: "list",
|
144
165
|
total_count: sources.size,
|
166
|
+
has_more: false,
|
145
167
|
url: "/v1/customers/#{cus_id}/sources",
|
146
168
|
data: sources
|
147
169
|
},
|
148
170
|
subscriptions: {
|
149
171
|
object: "list",
|
150
172
|
total_count: 0,
|
173
|
+
has_more: false,
|
151
174
|
url: "/v1/customers/#{cus_id}/subscriptions",
|
152
175
|
data: []
|
153
176
|
},
|
@@ -166,11 +189,34 @@ module StripeMock
|
|
166
189
|
paid: true,
|
167
190
|
amount: 0,
|
168
191
|
application_fee: nil,
|
192
|
+
application_fee_amount: nil,
|
169
193
|
currency: currency,
|
170
194
|
destination: nil,
|
171
195
|
fraud_details: {},
|
196
|
+
payment_method_details: {
|
197
|
+
card: {
|
198
|
+
brand: "visa",
|
199
|
+
checks: {
|
200
|
+
address_line1_check: nil,
|
201
|
+
address_postal_code_check: nil,
|
202
|
+
cvc_check: "pass"
|
203
|
+
},
|
204
|
+
country: "US",
|
205
|
+
exp_month: 12,
|
206
|
+
exp_year: 2013,
|
207
|
+
fingerprint: "3TQGpK9JoY1GgXPw",
|
208
|
+
funding: "credit",
|
209
|
+
installments: nil,
|
210
|
+
last4: "4242",
|
211
|
+
network: "visa",
|
212
|
+
three_d_secure: nil,
|
213
|
+
wallet: nil
|
214
|
+
},
|
215
|
+
type: "card"
|
216
|
+
},
|
172
217
|
receipt_email: nil,
|
173
218
|
receipt_number: nil,
|
219
|
+
receipt_url: nil,
|
174
220
|
refunded: false,
|
175
221
|
shipping: {},
|
176
222
|
statement_descriptor: "Charge #{charge_id}",
|
@@ -231,7 +277,8 @@ module StripeMock
|
|
231
277
|
charge: "ch_4fWhYjzQ23UFWT",
|
232
278
|
receipt_number: nil,
|
233
279
|
status: "succeeded",
|
234
|
-
reason: "requested_by_customer"
|
280
|
+
reason: "requested_by_customer",
|
281
|
+
receipt_url: nil
|
235
282
|
}.merge(params)
|
236
283
|
end
|
237
284
|
|
@@ -339,8 +386,9 @@ module StripeMock
|
|
339
386
|
},
|
340
387
|
cancel_at_period_end: false,
|
341
388
|
canceled_at: nil,
|
389
|
+
collection_method: 'charge_automatically',
|
342
390
|
ended_at: nil,
|
343
|
-
|
391
|
+
start_date: 1308595038,
|
344
392
|
object: 'subscription',
|
345
393
|
trial_start: 1308595038,
|
346
394
|
trial_end: 1308681468,
|
@@ -350,8 +398,10 @@ module StripeMock
|
|
350
398
|
discount: nil,
|
351
399
|
metadata: {},
|
352
400
|
default_tax_rates: nil,
|
401
|
+
default_payment_method: nil,
|
353
402
|
pending_invoice_item_interval: nil,
|
354
|
-
next_pending_invoice_item_invoice: nil
|
403
|
+
next_pending_invoice_item_invoice: nil,
|
404
|
+
latest_invoice: nil
|
355
405
|
}, params)
|
356
406
|
end
|
357
407
|
|
@@ -371,6 +421,7 @@ module StripeMock
|
|
371
421
|
lines: {
|
372
422
|
object: "list",
|
373
423
|
total_count: lines.count,
|
424
|
+
has_more: false,
|
374
425
|
url: "/v1/invoices/#{in_id}/lines",
|
375
426
|
data: lines
|
376
427
|
},
|
@@ -399,7 +450,8 @@ module StripeMock
|
|
399
450
|
next_payment_attempt: 1349825350,
|
400
451
|
charge: nil,
|
401
452
|
discount: nil,
|
402
|
-
subscription: nil
|
453
|
+
subscription: nil,
|
454
|
+
number: "6C41730-0001"
|
403
455
|
}.merge(params)
|
404
456
|
if invoice[:discount]
|
405
457
|
invoice[:total] = [0, invoice[:subtotal] - invoice[:discount][:coupon][:amount_off]].max if invoice[:discount][:coupon][:amount_off]
|
@@ -554,6 +606,34 @@ module StripeMock
|
|
554
606
|
}.merge(params)
|
555
607
|
end
|
556
608
|
|
609
|
+
def self.mock_price(params={})
|
610
|
+
currency = params[:currency] || StripeMock.default_currency
|
611
|
+
{
|
612
|
+
id: "mock_price_123",
|
613
|
+
object: "price",
|
614
|
+
active: true,
|
615
|
+
billing_scheme: "per_unit",
|
616
|
+
created: 1593044959,
|
617
|
+
currency: currency,
|
618
|
+
livemode: false,
|
619
|
+
lookup_key: nil,
|
620
|
+
metadata: {},
|
621
|
+
nickname: 'My Mock Price',
|
622
|
+
product: "mock_prod_NONEXIST", # override this with your own existing product id
|
623
|
+
recurring: {
|
624
|
+
aggregate_usage: nil,
|
625
|
+
interval: "month",
|
626
|
+
interval_count: 1,
|
627
|
+
usage_type: "licensed"
|
628
|
+
},
|
629
|
+
tiers_mode: nil,
|
630
|
+
transform_quantity: nil,
|
631
|
+
type: "recurring",
|
632
|
+
unit_amount: 2000,
|
633
|
+
unit_amount_decimal: "2000"
|
634
|
+
}.merge(params)
|
635
|
+
end
|
636
|
+
|
557
637
|
def self.mock_product(params={})
|
558
638
|
{
|
559
639
|
id: "mock_prod_abc123",
|
@@ -578,6 +658,44 @@ module StripeMock
|
|
578
658
|
}.merge(params)
|
579
659
|
end
|
580
660
|
|
661
|
+
def self.mock_promotion_code(params={})
|
662
|
+
{
|
663
|
+
id: "mock_promo_abc123",
|
664
|
+
object: "promotion_code",
|
665
|
+
active: true,
|
666
|
+
code: "TESTCODE",
|
667
|
+
coupon: {
|
668
|
+
id: "mock_coupon_abc123",
|
669
|
+
object: "coupon",
|
670
|
+
amount_off: nil,
|
671
|
+
created: 1665773498,
|
672
|
+
currency: "usd",
|
673
|
+
duration: "repeating",
|
674
|
+
duration_in_months: 1,
|
675
|
+
livemode: false,
|
676
|
+
max_redemptions: nil,
|
677
|
+
metadata: {},
|
678
|
+
name: "Mock Coupon",
|
679
|
+
percent_off: 10.0,
|
680
|
+
redeem_by: nil,
|
681
|
+
times_redeemed: 0,
|
682
|
+
valid: true
|
683
|
+
},
|
684
|
+
created: 1665773499,
|
685
|
+
customer: nil,
|
686
|
+
expires_at: nil,
|
687
|
+
livemode: false,
|
688
|
+
max_redemptions: nil,
|
689
|
+
metadata: {},
|
690
|
+
restrictions: {
|
691
|
+
first_time_transaction: false,
|
692
|
+
minimum_amount: nil,
|
693
|
+
minimum_amount_currency: nil
|
694
|
+
},
|
695
|
+
times_redeemed: 0
|
696
|
+
}.merge(params)
|
697
|
+
end
|
698
|
+
|
581
699
|
def self.mock_recipient(cards, params={})
|
582
700
|
rp_id = params[:id] || "test_rp_default"
|
583
701
|
cards.each {|card| card[:recipient] = rp_id}
|
@@ -601,6 +719,7 @@ module StripeMock
|
|
601
719
|
object: "list",
|
602
720
|
url: "/v1/recipients/#{rp_id}/cards",
|
603
721
|
data: cards,
|
722
|
+
has_more: false,
|
604
723
|
total_count: cards.count
|
605
724
|
},
|
606
725
|
default_card: nil
|
@@ -1008,6 +1127,16 @@ module StripeMock
|
|
1008
1127
|
bitcoin_receiver: 1545182
|
1009
1128
|
}
|
1010
1129
|
}],
|
1130
|
+
instant_available: [
|
1131
|
+
{
|
1132
|
+
currency: "usd",
|
1133
|
+
amount: usd_balance,
|
1134
|
+
source_types: {
|
1135
|
+
card: 25907032203,
|
1136
|
+
bank_account: 108476658,
|
1137
|
+
bitcoin_receiver: 1545182
|
1138
|
+
}
|
1139
|
+
}],
|
1011
1140
|
connect_reserved: [
|
1012
1141
|
{
|
1013
1142
|
currency: "usd",
|
@@ -1072,13 +1201,12 @@ module StripeMock
|
|
1072
1201
|
end
|
1073
1202
|
|
1074
1203
|
def self.mock_subscription_item(params = {})
|
1075
|
-
|
1204
|
+
id = params[:id] || 'test_si_default'
|
1076
1205
|
{
|
1077
|
-
id:
|
1206
|
+
id: id,
|
1078
1207
|
object: 'subscription_item',
|
1079
1208
|
created: 1504716183,
|
1080
|
-
metadata: {
|
1081
|
-
},
|
1209
|
+
metadata: {},
|
1082
1210
|
plan: {
|
1083
1211
|
id: 'PER_USER_PLAN1',
|
1084
1212
|
object: 'plan',
|
@@ -1167,29 +1295,72 @@ module StripeMock
|
|
1167
1295
|
end
|
1168
1296
|
|
1169
1297
|
def self.mock_payment_method(params = {})
|
1170
|
-
payment_method_id = params[:id] ||
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1298
|
+
payment_method_id = params[:id] || 'pm_1ExEuFL2DI6wht39WNJgbybl'
|
1299
|
+
|
1300
|
+
type = params[:type].to_sym
|
1301
|
+
last4 = params.dig(:card, :number)
|
1302
|
+
data = {
|
1303
|
+
card: {
|
1304
|
+
brand: case last4&.to_s
|
1305
|
+
when /^4/, nil
|
1306
|
+
'visa'
|
1307
|
+
when /^5[1-5]/
|
1308
|
+
'mastercard'
|
1309
|
+
else
|
1310
|
+
'unknown'
|
1311
|
+
end,
|
1312
|
+
checks: {
|
1313
|
+
address_line1_check: nil,
|
1314
|
+
address_postal_code_check: nil,
|
1315
|
+
cvc_check: 'pass'
|
1186
1316
|
},
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1317
|
+
country: 'FR',
|
1318
|
+
exp_month: params.dig(:card, :exp_month) || 2,
|
1319
|
+
exp_year: params.dig(:card, :exp_year) || 2022,
|
1320
|
+
fingerprint: 'Hr3Ly5z5IYxsokWA',
|
1321
|
+
funding: 'credit',
|
1322
|
+
generated_from: nil,
|
1323
|
+
last4: last4.nil? ? '3155' : last4.to_s[-4..],
|
1324
|
+
three_d_secure_usage: { supported: true },
|
1325
|
+
wallet: nil
|
1326
|
+
},
|
1327
|
+
ideal: {
|
1328
|
+
bank: 'ing',
|
1329
|
+
bic: 'INGBNL2A',
|
1330
|
+
iban_last4: '****',
|
1331
|
+
verified_name: 'JENNY ROSEN'
|
1332
|
+
},
|
1333
|
+
sepa_debit: {
|
1334
|
+
bank_code: '37040044',
|
1335
|
+
branch_code: '',
|
1336
|
+
country: 'DE',
|
1337
|
+
fingerprint: 'FD81kbVPe7M05BMj',
|
1338
|
+
last4: params.dig(:sepa_debit, :iban)&.[](-4..) || '3000'
|
1339
|
+
}
|
1340
|
+
}
|
1191
1341
|
|
1192
|
-
|
1342
|
+
{
|
1343
|
+
id: payment_method_id,
|
1344
|
+
object: 'payment_method',
|
1345
|
+
type: params[:type],
|
1346
|
+
billing_details: {
|
1347
|
+
address: {
|
1348
|
+
city: 'New Orleans',
|
1349
|
+
country: 'US',
|
1350
|
+
line1: 'Bourbon Street 23',
|
1351
|
+
line2: nil,
|
1352
|
+
postal_code: '10000',
|
1353
|
+
state: nil
|
1354
|
+
},
|
1355
|
+
email: 'foo@bar.com',
|
1356
|
+
name: 'John Dolton',
|
1357
|
+
phone: nil
|
1358
|
+
},
|
1359
|
+
customer: params[:customer] || nil,
|
1360
|
+
metadata: {
|
1361
|
+
order_id: '123456789'
|
1362
|
+
}
|
1363
|
+
}.merge(params).merge(type => data[type])
|
1193
1364
|
end
|
1194
1365
|
|
1195
1366
|
def self.mock_setup_intent(params = {})
|
data/lib/stripe_mock/instance.rb
CHANGED
@@ -24,6 +24,8 @@ module StripeMock
|
|
24
24
|
include StripeMock::RequestHandlers::PaymentMethods
|
25
25
|
include StripeMock::RequestHandlers::SetupIntents
|
26
26
|
include StripeMock::RequestHandlers::ExternalAccounts
|
27
|
+
include StripeMock::RequestHandlers::AccountLinks
|
28
|
+
include StripeMock::RequestHandlers::ExpressLoginLinks
|
27
29
|
include StripeMock::RequestHandlers::Accounts
|
28
30
|
include StripeMock::RequestHandlers::Balance
|
29
31
|
include StripeMock::RequestHandlers::BalanceTransactions
|
@@ -40,7 +42,9 @@ module StripeMock
|
|
40
42
|
include StripeMock::RequestHandlers::InvoiceItems
|
41
43
|
include StripeMock::RequestHandlers::Orders
|
42
44
|
include StripeMock::RequestHandlers::Plans
|
45
|
+
include StripeMock::RequestHandlers::Prices
|
43
46
|
include StripeMock::RequestHandlers::Products
|
47
|
+
include StripeMock::RequestHandlers::PromotionCodes
|
44
48
|
include StripeMock::RequestHandlers::Refunds
|
45
49
|
include StripeMock::RequestHandlers::Recipients
|
46
50
|
include StripeMock::RequestHandlers::Transfers
|
@@ -50,11 +54,13 @@ module StripeMock
|
|
50
54
|
include StripeMock::RequestHandlers::EphemeralKey
|
51
55
|
include StripeMock::RequestHandlers::TaxRates
|
52
56
|
include StripeMock::RequestHandlers::Checkout
|
57
|
+
include StripeMock::RequestHandlers::Checkout::Session
|
53
58
|
|
54
59
|
attr_reader :accounts, :balance, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
|
55
60
|
:disputes, :events, :invoices, :invoice_items, :orders, :payment_intents, :payment_methods,
|
56
|
-
:setup_intents, :plans, :
|
57
|
-
:subscriptions_items, :products, :tax_rates, :checkout_sessions
|
61
|
+
:setup_intents, :plans, :prices, :promotion_codes, :recipients, :refunds, :transfers, :payouts,
|
62
|
+
:subscriptions, :country_spec, :subscriptions_items, :products, :tax_rates, :checkout_sessions,
|
63
|
+
:checkout_session_line_items
|
58
64
|
|
59
65
|
attr_accessor :error_queue, :debug, :conversion_rate, :account_balance
|
60
66
|
|
@@ -64,7 +70,7 @@ module StripeMock
|
|
64
70
|
@balance_transactions = Data.mock_balance_transactions(['txn_05RsQX2eZvKYlo2C0FRTGSSA','txn_15RsQX2eZvKYlo2C0ERTYUIA', 'txn_25RsQX2eZvKYlo2C0ZXCVBNM', 'txn_35RsQX2eZvKYlo2C0QAZXSWE', 'txn_45RsQX2eZvKYlo2C0EDCVFRT', 'txn_55RsQX2eZvKYlo2C0OIKLJUY', 'txn_65RsQX2eZvKYlo2C0ASDFGHJ', 'txn_75RsQX2eZvKYlo2C0EDCXSWQ', 'txn_85RsQX2eZvKYlo2C0UJMCDET', 'txn_95RsQX2eZvKYlo2C0EDFRYUI'])
|
65
71
|
@bank_tokens = {}
|
66
72
|
@card_tokens = {}
|
67
|
-
@customers = {}
|
73
|
+
@customers = { Stripe.api_key => {} }
|
68
74
|
@charges = {}
|
69
75
|
@payment_intents = {}
|
70
76
|
@payment_methods = {}
|
@@ -77,7 +83,9 @@ module StripeMock
|
|
77
83
|
@orders = {}
|
78
84
|
@payment_methods = {}
|
79
85
|
@plans = {}
|
86
|
+
@prices = {}
|
80
87
|
@products = {}
|
88
|
+
@promotion_codes = {}
|
81
89
|
@recipients = {}
|
82
90
|
@refunds = {}
|
83
91
|
@transfers = {}
|
@@ -87,6 +95,7 @@ module StripeMock
|
|
87
95
|
@country_spec = {}
|
88
96
|
@tax_rates = {}
|
89
97
|
@checkout_sessions = {}
|
98
|
+
@checkout_session_line_items = {}
|
90
99
|
|
91
100
|
@debug = false
|
92
101
|
@error_queue = ErrorQueue.new
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module AccountLinks
|
4
|
+
|
5
|
+
def AccountLinks.included(klass)
|
6
|
+
klass.add_handler 'post /v1/account_links', :new_account_link
|
7
|
+
end
|
8
|
+
|
9
|
+
def new_account_link(route, method_url, params, headers)
|
10
|
+
route =~ method_url
|
11
|
+
Data.mock_account_link(params)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -4,12 +4,13 @@ module StripeMock
|
|
4
4
|
VALID_START_YEAR = 2009
|
5
5
|
|
6
6
|
def Accounts.included(klass)
|
7
|
-
klass.add_handler 'post /v1/accounts',
|
8
|
-
klass.add_handler 'get /v1/account',
|
9
|
-
klass.add_handler 'get /v1/accounts/(.*)',
|
10
|
-
klass.add_handler 'post /v1/accounts/(.*)',
|
11
|
-
klass.add_handler 'get /v1/accounts',
|
12
|
-
klass.add_handler 'post /oauth/deauthorize'
|
7
|
+
klass.add_handler 'post /v1/accounts', :new_account
|
8
|
+
klass.add_handler 'get /v1/account', :get_account
|
9
|
+
klass.add_handler 'get /v1/accounts/(.*)', :get_account
|
10
|
+
klass.add_handler 'post /v1/accounts/(.*)', :update_account
|
11
|
+
klass.add_handler 'get /v1/accounts', :list_accounts
|
12
|
+
klass.add_handler 'post /oauth/deauthorize', :deauthorize
|
13
|
+
klass.add_handler 'delete /v1/accounts/(.*)', :delete_account
|
13
14
|
end
|
14
15
|
|
15
16
|
def new_account(route, method_url, params, headers)
|
@@ -48,6 +49,16 @@ module StripeMock
|
|
48
49
|
Stripe::StripeObject.construct_from(:stripe_user_id => params[:stripe_user_id])
|
49
50
|
end
|
50
51
|
|
52
|
+
def delete_account(route, method_url, params, headers)
|
53
|
+
init_account
|
54
|
+
route =~ method_url
|
55
|
+
assert_existence :account, $1, accounts[$1]
|
56
|
+
accounts[$1] = {
|
57
|
+
id: accounts[$1][:id],
|
58
|
+
deleted: true
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
51
62
|
private
|
52
63
|
|
53
64
|
def init_account
|
@@ -12,7 +12,9 @@ module StripeMock
|
|
12
12
|
klass.add_handler 'post /v1/charges/(.*)', :update_charge
|
13
13
|
end
|
14
14
|
|
15
|
-
def new_charge(route, method_url, params, headers)
|
15
|
+
def new_charge(route, method_url, params, headers = {})
|
16
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
17
|
+
|
16
18
|
if headers && headers[:idempotency_key]
|
17
19
|
params[:idempotency_key] = headers[:idempotency_key]
|
18
20
|
if charges.any?
|
@@ -29,7 +31,7 @@ module StripeMock
|
|
29
31
|
# card id, not a token. in this case we'll find the card in the customer
|
30
32
|
# object and return that.
|
31
33
|
if params[:customer]
|
32
|
-
params[:source] = get_card(customers[params[:customer]], params[:source])
|
34
|
+
params[:source] = get_card(customers[stripe_account][params[:customer]], params[:source])
|
33
35
|
else
|
34
36
|
params[:source] = get_card_or_bank_by_token(params[:source])
|
35
37
|
end
|
@@ -37,7 +39,7 @@ module StripeMock
|
|
37
39
|
raise Stripe::InvalidRequestError.new("Invalid token id: #{params[:source]}", 'card', http_status: 400)
|
38
40
|
end
|
39
41
|
elsif params[:customer]
|
40
|
-
customer = customers[params[:customer]]
|
42
|
+
customer = customers[stripe_account][params[:customer]]
|
41
43
|
if customer && customer[:default_source]
|
42
44
|
params[:source] = get_card(customer, customer[:default_source])
|
43
45
|
end
|
@@ -146,7 +148,7 @@ module StripeMock
|
|
146
148
|
elsif non_positive_charge_amount?(params)
|
147
149
|
raise Stripe::InvalidRequestError.new('Invalid positive integer', 'amount', http_status: 400)
|
148
150
|
elsif params[:source].nil? && params[:customer].nil?
|
149
|
-
raise Stripe::InvalidRequestError.new('Must provide source or customer.', http_status: nil)
|
151
|
+
raise Stripe::InvalidRequestError.new('Must provide source or customer.', nil, http_status: nil)
|
150
152
|
end
|
151
153
|
end
|
152
154
|
|
@@ -169,6 +171,11 @@ module StripeMock
|
|
169
171
|
params[:refunds].has_key?(:data) && params[:refunds][:data].nil?)
|
170
172
|
allowed << :refunds
|
171
173
|
end
|
174
|
+
if params.has_key?(:payment_method_details) && (params[:payment_method_details].empty? ||
|
175
|
+
params[:payment_method_details].has_key?(:card) && (params[:payment_method_details][:card].empty? ||
|
176
|
+
params[:payment_method_details][:card].has_key?(:checks) && params[:payment_method_details][:card][:checks].empty?))
|
177
|
+
allowed << :payment_method_details
|
178
|
+
end
|
172
179
|
|
173
180
|
allowed
|
174
181
|
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module Checkout
|
4
|
+
module Session
|
5
|
+
def Session.included(klass)
|
6
|
+
klass.add_handler 'post /v1/checkout/sessions', :new_session
|
7
|
+
klass.add_handler 'get /v1/checkout/sessions', :list_checkout_sessions
|
8
|
+
klass.add_handler 'get /v1/checkout/sessions/([^/]*)', :get_checkout_session
|
9
|
+
klass.add_handler 'get /v1/checkout/sessions/([^/]*)/line_items', :list_line_items
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_session(route, method_url, params, headers)
|
13
|
+
id = params[:id] || new_id('cs')
|
14
|
+
|
15
|
+
[:cancel_url, :success_url].each do |p|
|
16
|
+
require_param(p) if params[p].nil? || params[p].empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
line_items = nil
|
20
|
+
if params[:line_items]
|
21
|
+
line_items = params[:line_items].each_with_index.map do |line_item, i|
|
22
|
+
throw Stripe::InvalidRequestError("Quantity is required. Add `quantity` to `line_items[#{i}]`") unless line_item[:quantity]
|
23
|
+
unless line_item[:price] || line_item[:price_data] || (line_item[:amount] && line_item[:currency] && line_item[:name])
|
24
|
+
throw Stripe::InvalidRequestError("Price or amount and currency is required. Add `price`, `price_data`, or `amount`, `currency` and `name` to `line_items[#{i}]`")
|
25
|
+
end
|
26
|
+
{
|
27
|
+
id: new_id("li"),
|
28
|
+
price: if line_item[:price]
|
29
|
+
line_item[:price]
|
30
|
+
elsif line_item[:price_data]
|
31
|
+
new_price(nil, nil, line_item[:price_data], nil)[:id]
|
32
|
+
else
|
33
|
+
new_price(nil, nil, {
|
34
|
+
unit_amount: line_item[:amount],
|
35
|
+
currency: line_item[:currency],
|
36
|
+
product_data: {
|
37
|
+
name: line_item[:name]
|
38
|
+
}
|
39
|
+
}, nil)[:id]
|
40
|
+
end,
|
41
|
+
quantity: line_item[:quantity]
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
amount = nil
|
47
|
+
currency = nil
|
48
|
+
if line_items
|
49
|
+
amount = 0
|
50
|
+
|
51
|
+
line_items.each do |line_item|
|
52
|
+
price = prices[line_item[:price]]
|
53
|
+
|
54
|
+
if price.nil?
|
55
|
+
raise StripeMock::StripeMockError.new("Price not found for ID: #{line_item[:price]}")
|
56
|
+
end
|
57
|
+
|
58
|
+
amount += (price[:unit_amount] * line_item[:quantity])
|
59
|
+
end
|
60
|
+
|
61
|
+
currency = prices[line_items.first[:price]][:currency]
|
62
|
+
end
|
63
|
+
|
64
|
+
payment_status = "unpaid"
|
65
|
+
payment_intent = nil
|
66
|
+
setup_intent = nil
|
67
|
+
case params[:mode]
|
68
|
+
when nil, "payment"
|
69
|
+
params[:customer] ||= new_customer(nil, nil, {email: params[:customer_email]}, nil)[:id]
|
70
|
+
require_param(:line_items) if params[:line_items].nil? || params[:line_items].empty?
|
71
|
+
payment_intent = new_payment_intent(nil, nil, {
|
72
|
+
amount: amount,
|
73
|
+
currency: currency,
|
74
|
+
customer: params[:customer],
|
75
|
+
payment_method_options: params[:payment_method_options],
|
76
|
+
payment_method_types: params[:payment_method_types]
|
77
|
+
}.merge(params[:payment_intent_data] || {}), nil)[:id]
|
78
|
+
checkout_session_line_items[id] = line_items
|
79
|
+
when "setup"
|
80
|
+
if !params[:line_items].nil? && !params[:line_items].empty?
|
81
|
+
throw Stripe::InvalidRequestError.new("You cannot pass `line_items` in `setup` mode", :line_items, http_status: 400)
|
82
|
+
end
|
83
|
+
setup_intent = new_setup_intent(nil, nil, {
|
84
|
+
customer: params[:customer],
|
85
|
+
payment_method_options: params[:payment_method_options],
|
86
|
+
payment_method_types: params[:payment_method_types]
|
87
|
+
}.merge(params[:setup_intent_data] || {}), nil)[:id]
|
88
|
+
payment_status = "no_payment_required"
|
89
|
+
when "subscription"
|
90
|
+
params[:customer] ||= new_customer(nil, nil, {email: params[:customer_email]}, nil)[:id]
|
91
|
+
require_param(:line_items) if params[:line_items].nil? || params[:line_items].empty?
|
92
|
+
checkout_session_line_items[id] = line_items
|
93
|
+
else
|
94
|
+
throw Stripe::InvalidRequestError.new("Invalid mode: must be one of payment, setup, or subscription", :mode, http_status: 400)
|
95
|
+
end
|
96
|
+
|
97
|
+
checkout_sessions[id] = {
|
98
|
+
id: id,
|
99
|
+
object: "checkout.session",
|
100
|
+
allow_promotion_codes: nil,
|
101
|
+
amount_subtotal: amount,
|
102
|
+
amount_total: amount,
|
103
|
+
automatic_tax: {
|
104
|
+
enabled: false,
|
105
|
+
status: nil
|
106
|
+
},
|
107
|
+
billing_address_collection: nil,
|
108
|
+
cancel_url: params[:cancel_url],
|
109
|
+
client_reference_id: nil,
|
110
|
+
currency: currency,
|
111
|
+
customer: params[:customer],
|
112
|
+
customer_details: nil,
|
113
|
+
customer_email: params[:customer_email],
|
114
|
+
livemode: false,
|
115
|
+
locale: nil,
|
116
|
+
metadata: params[:metadata],
|
117
|
+
mode: params[:mode],
|
118
|
+
payment_intent: payment_intent,
|
119
|
+
payment_method_options: params[:payment_method_options],
|
120
|
+
payment_method_types: params[:payment_method_types],
|
121
|
+
payment_status: payment_status,
|
122
|
+
setup_intent: setup_intent,
|
123
|
+
shipping: nil,
|
124
|
+
shipping_address_collection: nil,
|
125
|
+
submit_type: nil,
|
126
|
+
subscription: nil,
|
127
|
+
success_url: params[:success_url],
|
128
|
+
total_details: nil,
|
129
|
+
url: URI.join(StripeMock.checkout_base, id).to_s
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
def list_checkout_sessions(route, method_url, params, headers)
|
134
|
+
Data.mock_list_object(checkout_sessions.values)
|
135
|
+
end
|
136
|
+
|
137
|
+
def get_checkout_session(route, method_url, params, headers)
|
138
|
+
route =~ method_url
|
139
|
+
checkout_session = assert_existence :checkout_session, $1, checkout_sessions[$1]
|
140
|
+
|
141
|
+
checkout_session = checkout_session.clone
|
142
|
+
if params[:expand]&.include?('setup_intent') && checkout_session[:setup_intent]
|
143
|
+
checkout_session[:setup_intent] = setup_intents[checkout_session[:setup_intent]]
|
144
|
+
end
|
145
|
+
checkout_session
|
146
|
+
end
|
147
|
+
|
148
|
+
def list_line_items(route, method_url, params, headers)
|
149
|
+
route =~ method_url
|
150
|
+
checkout_session = assert_existence :checkout_session, $1, checkout_sessions[$1]
|
151
|
+
|
152
|
+
case checkout_session[:mode]
|
153
|
+
when "payment", "subscription"
|
154
|
+
line_items = assert_existence :checkout_session_line_items, $1, checkout_session_line_items[$1]
|
155
|
+
line_items.map do |line_item|
|
156
|
+
price = prices[line_item[:price]].clone
|
157
|
+
|
158
|
+
if price.nil?
|
159
|
+
raise StripeMock::StripeMockError.new("Price not found for ID: #{line_item[:price]}")
|
160
|
+
end
|
161
|
+
|
162
|
+
{
|
163
|
+
id: line_item[:id],
|
164
|
+
object: "item",
|
165
|
+
amount_subtotal: price[:unit_amount] * line_item[:quantity],
|
166
|
+
amount_total: price[:unit_amount] * line_item[:quantity],
|
167
|
+
currency: price[:currency],
|
168
|
+
price: price.clone,
|
169
|
+
quantity: line_item[:quantity]
|
170
|
+
}
|
171
|
+
end
|
172
|
+
else
|
173
|
+
throw Stripe::InvalidRequestError("Only payment and subscription sessions have line items")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|