stripe-ruby-mock 2.4.0 → 2.5.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.env +2 -0
  3. data/.travis.yml +8 -4
  4. data/README.md +12 -5
  5. data/lib/stripe_mock/api/account_balance.rb +14 -0
  6. data/lib/stripe_mock/api/client.rb +4 -4
  7. data/lib/stripe_mock/api/conversion_rate.rb +14 -0
  8. data/lib/stripe_mock/api/errors.rb +25 -14
  9. data/lib/stripe_mock/api/instance.rb +6 -6
  10. data/lib/stripe_mock/api/webhooks.rb +5 -1
  11. data/lib/stripe_mock/client.rb +18 -2
  12. data/lib/stripe_mock/data/list.rb +14 -2
  13. data/lib/stripe_mock/data.rb +217 -56
  14. data/lib/stripe_mock/instance.rb +93 -8
  15. data/lib/stripe_mock/request_handlers/accounts.rb +34 -2
  16. data/lib/stripe_mock/request_handlers/balance.rb +17 -0
  17. data/lib/stripe_mock/request_handlers/balance_transactions.rb +18 -2
  18. data/lib/stripe_mock/request_handlers/charges.rb +25 -17
  19. data/lib/stripe_mock/request_handlers/coupons.rb +5 -4
  20. data/lib/stripe_mock/request_handlers/customers.rb +26 -8
  21. data/lib/stripe_mock/request_handlers/ephemeral_key.rb +13 -0
  22. data/lib/stripe_mock/request_handlers/external_accounts.rb +55 -0
  23. data/lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb +1 -1
  24. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +9 -7
  25. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +10 -6
  26. data/lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb +49 -0
  27. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +55 -15
  28. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +2 -2
  29. data/lib/stripe_mock/request_handlers/invoices.rb +93 -14
  30. data/lib/stripe_mock/request_handlers/orders.rb +5 -5
  31. data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
  32. data/lib/stripe_mock/request_handlers/plans.rb +1 -0
  33. data/lib/stripe_mock/request_handlers/products.rb +43 -0
  34. data/lib/stripe_mock/request_handlers/refunds.rb +10 -7
  35. data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
  36. data/lib/stripe_mock/request_handlers/subscriptions.rb +95 -34
  37. data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
  38. data/lib/stripe_mock/request_handlers/tokens.rb +9 -3
  39. data/lib/stripe_mock/request_handlers/transfers.rb +11 -5
  40. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +10 -1
  41. data/lib/stripe_mock/server.rb +14 -1
  42. data/lib/stripe_mock/test_strategies/base.rb +7 -5
  43. data/lib/stripe_mock/test_strategies/live.rb +5 -0
  44. data/lib/stripe_mock/test_strategies/mock.rb +8 -0
  45. data/lib/stripe_mock/util.rb +8 -2
  46. data/lib/stripe_mock/version.rb +1 -1
  47. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  48. data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_reinstated.json +88 -0
  49. data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_withdrawn.json +88 -0
  50. data/lib/stripe_mock/webhook_fixtures/charge.updated.json +58 -0
  51. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +40 -10
  52. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +39 -10
  53. data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +39 -10
  54. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +40 -11
  55. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +3 -2
  56. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +1 -1
  57. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +92 -85
  58. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +3 -2
  59. data/lib/stripe_mock/webhook_fixtures/plan.created.json +1 -1
  60. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +1 -1
  61. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +1 -1
  62. data/lib/stripe_mock.rb +13 -0
  63. data/spec/instance_spec.rb +54 -4
  64. data/spec/integration_examples/prepare_error_examples.rb +6 -6
  65. data/spec/list_spec.rb +16 -3
  66. data/spec/readme_spec.rb +2 -0
  67. data/spec/server_spec.rb +6 -2
  68. data/spec/shared_stripe_examples/account_examples.rb +35 -0
  69. data/spec/shared_stripe_examples/balance_examples.rb +11 -0
  70. data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
  71. data/spec/shared_stripe_examples/bank_examples.rb +28 -1
  72. data/spec/shared_stripe_examples/card_examples.rb +10 -3
  73. data/spec/shared_stripe_examples/charge_examples.rb +73 -17
  74. data/spec/shared_stripe_examples/coupon_examples.rb +8 -2
  75. data/spec/shared_stripe_examples/customer_examples.rb +54 -2
  76. data/spec/shared_stripe_examples/dispute_examples.rb +19 -8
  77. data/spec/shared_stripe_examples/ephemeral_key_examples.rb +17 -0
  78. data/spec/shared_stripe_examples/error_mock_examples.rb +3 -3
  79. data/spec/shared_stripe_examples/external_account_examples.rb +170 -0
  80. data/spec/shared_stripe_examples/extra_features_examples.rb +2 -0
  81. data/spec/shared_stripe_examples/invoice_examples.rb +314 -51
  82. data/spec/shared_stripe_examples/payout_examples.rb +68 -0
  83. data/spec/shared_stripe_examples/plan_examples.rb +37 -5
  84. data/spec/shared_stripe_examples/product_example.rb +65 -0
  85. data/spec/shared_stripe_examples/recipient_examples.rb +7 -7
  86. data/spec/shared_stripe_examples/refund_examples.rb +17 -11
  87. data/spec/shared_stripe_examples/subscription_examples.rb +463 -33
  88. data/spec/shared_stripe_examples/subscription_items_examples.rb +75 -0
  89. data/spec/shared_stripe_examples/tax_rate_examples.rb +42 -0
  90. data/spec/shared_stripe_examples/transfer_examples.rb +72 -23
  91. data/spec/shared_stripe_examples/webhook_event_examples.rb +74 -5
  92. data/spec/spec_helper.rb +7 -6
  93. data/spec/stripe_mock_spec.rb +16 -3
  94. data/spec/support/stripe_examples.rb +7 -1
  95. data/spec/util_spec.rb +35 -1
  96. data/stripe-ruby-mock.gemspec +1 -1
  97. metadata +34 -7
  98. data/ChangeLog.rdoc +0 -4
@@ -3,7 +3,7 @@ module StripeMock
3
3
 
4
4
  def self.mock_account(params = {})
5
5
  id = params[:id] || 'acct_103ED82ePvKYlo2C'
6
- currency = params[:currency] || 'usd'
6
+ currency = params[:currency] || StripeMock.default_currency
7
7
  {
8
8
  id: id,
9
9
  email: "bob@example.com",
@@ -12,7 +12,7 @@ module StripeMock
12
12
  timezone: "US/Pacific",
13
13
  details_submitted: false,
14
14
  charges_enabled: false,
15
- transfers_enabled: false,
15
+ payouts_enabled: false,
16
16
  currencies_supported: [
17
17
  "usd"
18
18
  ],
@@ -101,9 +101,25 @@ module StripeMock
101
101
  }.merge(params)
102
102
  end
103
103
 
104
+ def self.mock_tax_rate(params)
105
+ {
106
+ id: 'test_cus_default',
107
+ object: 'tax_rate',
108
+ active: true,
109
+ created: 1559079603,
110
+ description: nil,
111
+ display_name: 'VAT',
112
+ inclusive: false,
113
+ jurisdiction: 'EU',
114
+ livemode: false,
115
+ metadata: {},
116
+ percentage: 21.0
117
+ }.merge(params)
118
+ end
119
+
104
120
  def self.mock_customer(sources, params)
105
121
  cus_id = params[:id] || "test_cus_default"
106
- currency = params[:currency] || nil
122
+ currency = params[:currency] || StripeMock.default_currency
107
123
  sources.each {|source| source[:customer] = cus_id}
108
124
  {
109
125
  email: 'stripe_mock@example.com',
@@ -111,6 +127,7 @@ module StripeMock
111
127
  object: "customer",
112
128
  created: 1372126710,
113
129
  id: cus_id,
130
+ name: nil,
114
131
  livemode: false,
115
132
  delinquent: false,
116
133
  discount: nil,
@@ -134,7 +151,7 @@ module StripeMock
134
151
 
135
152
  def self.mock_charge(params={})
136
153
  charge_id = params[:id] || "ch_1fD6uiR9FAA2zc"
137
- currency = params[:currency] || 'usd'
154
+ currency = params[:currency] || StripeMock.default_currency
138
155
  {
139
156
  id: charge_id,
140
157
  object: "charge",
@@ -196,7 +213,7 @@ module StripeMock
196
213
  end
197
214
 
198
215
  def self.mock_refund(params={})
199
- currency = params[:currency] || 'usd'
216
+ currency = params[:currency] || StripeMock.default_currency
200
217
  {
201
218
  id: "re_4fWhgUh5si7InF",
202
219
  amount: 1,
@@ -207,7 +224,8 @@ module StripeMock
207
224
  metadata: {},
208
225
  charge: "ch_4fWhYjzQ23UFWT",
209
226
  receipt_number: nil,
210
- status: "succeeded"
227
+ status: "succeeded",
228
+ reason: "requested_by_customer"
211
229
  }.merge(params)
212
230
  end
213
231
 
@@ -242,12 +260,13 @@ module StripeMock
242
260
  cvc_check: nil,
243
261
  address_line1_check: nil,
244
262
  address_zip_check: nil,
245
- tokenization_method: nil
263
+ tokenization_method: nil,
264
+ metadata: {}
246
265
  }, params)
247
266
  end
248
267
 
249
268
  def self.mock_bank_account(params={})
250
- currency = params[:currency] || 'usd'
269
+ currency = params[:currency] || StripeMock.default_currency
251
270
  {
252
271
  id: "test_ba_default",
253
272
  object: "bank_account",
@@ -260,7 +279,8 @@ module StripeMock
260
279
  status: 'new',
261
280
  account_holder_name: 'John Doe',
262
281
  account_holder_type: 'individual',
263
- fingerprint: "aBcFinGerPrINt123"
282
+ fingerprint: "aBcFinGerPrINt123",
283
+ metadata: {}
264
284
  }.merge(params)
265
285
  end
266
286
 
@@ -283,39 +303,59 @@ module StripeMock
283
303
  #FIXME nested overrides would be better than hardcoding plan_id
284
304
  def self.mock_subscription(params={})
285
305
  StripeMock::Util.rmerge({
286
- :created => 1478204116,
287
- :current_period_start => 1308595038,
288
- :current_period_end => 1308681468,
289
- :status => "trialing",
290
- :plan => {
291
- :interval => "month",
292
- :amount => 7500,
293
- :trial_period_days => 30,
294
- :object => "plan",
295
- :id => '__test_plan_id__'
306
+ created: 1478204116,
307
+ billing: 'charge_automatically',
308
+ current_period_start: 1308595038,
309
+ current_period_end: 1308681468,
310
+ status: 'trialing',
311
+ trial_from_plan: false,
312
+ plan: {
313
+ interval: 'month',
314
+ amount: 7500,
315
+ trial_period_days: 30,
316
+ object: 'plan',
317
+ id: '__test_plan_id__'
318
+ },
319
+ items: {
320
+ object: 'list',
321
+ data: [{
322
+ id: 'si_1AwFf62eZvKYlo2C9u6Dhf9',
323
+ created: 1504035973,
324
+ metadata: {},
325
+ object: 'subscription_item',
326
+ plan: {
327
+ amount: 999,
328
+ created: 1504035972,
329
+ currency: StripeMock.default_currency
330
+ },
331
+ quantity: 1
332
+ }]
296
333
  },
297
- :cancel_at_period_end => false,
298
- :canceled_at => nil,
299
- :ended_at => nil,
300
- :start => 1308595038,
301
- :object => "subscription",
302
- :trial_start => 1308595038,
303
- :trial_end => 1308681468,
304
- :customer => "c_test_customer",
305
- :quantity => 1,
306
- :tax_percent => nil,
307
- :discount => nil,
308
- :metadata => {}
334
+ cancel_at_period_end: false,
335
+ canceled_at: nil,
336
+ ended_at: nil,
337
+ start: 1308595038,
338
+ object: 'subscription',
339
+ trial_start: 1308595038,
340
+ trial_end: 1308681468,
341
+ customer: 'c_test_customer',
342
+ quantity: 1,
343
+ tax_percent: nil,
344
+ discount: nil,
345
+ metadata: {}
309
346
  }, params)
310
347
  end
311
348
 
312
349
  def self.mock_invoice(lines, params={})
313
350
  in_id = params[:id] || "test_in_default"
314
- currency = params[:currency] || 'usd'
351
+ currency = params[:currency] || StripeMock.default_currency
315
352
  lines << Data.mock_line_item() if lines.empty?
316
- {
353
+ invoice = {
317
354
  id: 'in_test_invoice',
318
- date: 1349738950,
355
+ status: 'open',
356
+ invoice_pdf: 'pdf_url',
357
+ hosted_invoice_url: 'hosted_invoice_url',
358
+ created: 1349738950,
319
359
  period_end: 1349738950,
320
360
  period_start: 1349738950,
321
361
  lines: {
@@ -325,7 +365,6 @@ module StripeMock
325
365
  data: lines
326
366
  },
327
367
  subtotal: lines.map {|line| line[:amount]}.reduce(0, :+),
328
- total: lines.map {|line| line[:amount]}.reduce(0, :+),
329
368
  customer: "test_customer",
330
369
  object: 'invoice',
331
370
  attempted: false,
@@ -337,12 +376,13 @@ module StripeMock
337
376
  paid: false,
338
377
  receipt_number: nil,
339
378
  statement_descriptor: nil,
340
- tax: nil,
379
+ tax: 10,
341
380
  tax_percent: nil,
342
381
  webhooks_delivered_at: 1349825350,
343
382
  livemode: false,
344
383
  attempt_count: 0,
345
- amount_due: lines.map {|line| line[:amount]}.reduce(0, :+),
384
+ amount_due: 100,
385
+ amount_paid: 0,
346
386
  currency: currency,
347
387
  starting_balance: 0,
348
388
  ending_balance: nil,
@@ -351,10 +391,19 @@ module StripeMock
351
391
  discount: nil,
352
392
  subscription: nil
353
393
  }.merge(params)
394
+ if invoice[:discount]
395
+ invoice[:total] = [0, invoice[:subtotal] - invoice[:discount][:coupon][:amount_off]].max if invoice[:discount][:coupon][:amount_off]
396
+ invoice[:total] = invoice[:subtotal] * invoice[:discount][:coupon][:percent_off] / 100 if invoice[:discount][:coupon][:percent_off]
397
+ else
398
+ invoice[:total] = invoice[:subtotal]
399
+ end
400
+ due = invoice[:total] + invoice[:starting_balance]
401
+ invoice[:amount_due] = due < 0 ? 0 : due
402
+ invoice
354
403
  end
355
404
 
356
405
  def self.mock_line_item(params = {})
357
- currency = params[:currency] || 'usd'
406
+ currency = params[:currency] || StripeMock.default_currency
358
407
  {
359
408
  id: "ii_test",
360
409
  object: "line_item",
@@ -368,6 +417,11 @@ module StripeMock
368
417
  start: 1349738920,
369
418
  end: 1349738920
370
419
  },
420
+ tax_amounts: [
421
+ {
422
+ amount: 10
423
+ }
424
+ ],
371
425
  quantity: nil,
372
426
  subscription: nil,
373
427
  plan: nil,
@@ -377,11 +431,11 @@ module StripeMock
377
431
  end
378
432
 
379
433
  def self.mock_invoice_item(params = {})
380
- currency = params[:currency] || 'usd'
434
+ currency = params[:currency] || StripeMock.default_currency
381
435
  {
382
436
  id: "test_ii",
383
437
  object: "invoiceitem",
384
- date: 1349738920,
438
+ created: 1349738920,
385
439
  amount: 1099,
386
440
  livemode: false,
387
441
  proration: false,
@@ -465,7 +519,7 @@ module StripeMock
465
519
  end
466
520
 
467
521
  def self.mock_plan(params={})
468
- currency = params[:currency] || 'usd'
522
+ currency = params[:currency] || StripeMock.default_currency
469
523
  {
470
524
  id: "2",
471
525
  object: "plan",
@@ -482,6 +536,21 @@ module StripeMock
482
536
  }.merge(params)
483
537
  end
484
538
 
539
+ def self.mock_product(params = {})
540
+ {
541
+ id: "default_test_prod",
542
+ object: "product",
543
+ active: true,
544
+ created: 1556896214,
545
+ livemode: false,
546
+ metadata: {},
547
+ name: "Default Test Product",
548
+ statement_descriptor: "PRODUCT",
549
+ type: "service",
550
+ updated: 1556918200,
551
+ }.merge(params)
552
+ end
553
+
485
554
  def self.mock_recipient(cards, params={})
486
555
  rp_id = params[:id] || "test_rp_default"
487
556
  cards.each {|card| card[:recipient] = rp_id}
@@ -566,33 +635,47 @@ module StripeMock
566
635
  end
567
636
 
568
637
  def self.mock_transfer(params={})
569
- currency = params[:currency] || 'usd'
638
+ currency = params[:currency] || StripeMock.default_currency
570
639
  id = params[:id] || 'tr_test_transfer'
571
640
  {
572
- :status => 'pending',
573
641
  :amount => 100,
574
- :account => {
575
- :object => 'bank_account',
576
- :country => 'US',
577
- :bank_name => 'STRIPE TEST BANK',
578
- :last4 => '6789'
579
- },
580
- :recipient => 'test_recipient',
581
- :fee => 0,
582
- :fee_details => [],
642
+ :amount_reversed => 0,
643
+ :balance_transaction => "txn_2dyYXXP90MN26R",
583
644
  :id => id,
584
645
  :livemode => false,
646
+ :metadata => {},
585
647
  :currency => currency,
586
648
  :object => "transfer",
587
- :date => 1304114826,
649
+ :created => 1304114826,
588
650
  :description => "Transfer description",
589
651
  :reversed => false,
590
652
  :reversals => {
591
653
  :object => "list",
654
+ :data => [],
592
655
  :total_count => 0,
593
656
  :has_more => false,
594
657
  :url => "/v1/transfers/#{id}/reversals"
595
658
  },
659
+ :destination => "acct_164wxjKbnvuxQXGu",
660
+ :destination_payment => "py_164xRvKbnvuxQXGuVFV2pZo1",
661
+ :source_transaction => "ch_164xRv2eZvKYlo2Clu1sIJWB",
662
+ :source_type => "card",
663
+ :transfer_group => "group_ch_164xRv2eZvKYlo2Clu1sIJWB",
664
+ }.merge(params)
665
+ end
666
+
667
+ def self.mock_payout(params={})
668
+ currency = params[:currency] || StripeMock.default_currency
669
+ id = params[:id] || 'po_test_payout'
670
+ {
671
+ :amount => 100,
672
+ :id => id,
673
+ :livemode => false,
674
+ :metadata => {},
675
+ :currency => currency,
676
+ :object => "payout",
677
+ :date => 1304114826,
678
+ :description => "Payout description",
596
679
  }.merge(params)
597
680
  end
598
681
 
@@ -605,7 +688,8 @@ module StripeMock
605
688
  end
606
689
 
607
690
  def self.mock_dispute(params={})
608
- currency = params[:currency] || 'usd'
691
+ @timestamp ||= Time.now.to_i
692
+ currency = params[:currency] || StripeMock.default_currency
609
693
  id = params[:id] || "dp_test_dispute"
610
694
  {
611
695
  :id => id,
@@ -613,7 +697,7 @@ module StripeMock
613
697
  :amount => 195,
614
698
  :balance_transactions => [],
615
699
  :charge => "ch_15RsQR2eZvKYlo2CA8IfzCX0",
616
- :created => 1422915137,
700
+ :created => @timestamp += 1,
617
701
  :currency => currency,
618
702
  :evidence => self.mock_dispute_evidence,
619
703
  :evidence_details => self.mock_dispute_evidence_details,
@@ -884,6 +968,38 @@ module StripeMock
884
968
  }
885
969
  end
886
970
 
971
+ def self.mock_balance(usd_balance = 10000)
972
+ {
973
+ object: "balance",
974
+ available: [
975
+ {
976
+ currency: "usd",
977
+ amount: usd_balance,
978
+ source_types: {
979
+ card: 25907032203,
980
+ bank_account: 108476658,
981
+ bitcoin_receiver: 1545182
982
+ }
983
+ }],
984
+ connect_reserved: [
985
+ {
986
+ currency: "usd",
987
+ amount: 4700
988
+ }],
989
+ livemode: false,
990
+ pending: [
991
+ {
992
+ currency: "usd",
993
+ amount: 22738833554,
994
+ source_types: {
995
+ card: 22738826610,
996
+ bank_account: 0,
997
+ bitcoin_receiver: 6944
998
+ }
999
+ }]
1000
+ }
1001
+ end
1002
+
887
1003
  def self.mock_balance_transactions(ids=[])
888
1004
  bts = {}
889
1005
  ids.each do |id|
@@ -893,7 +1009,7 @@ module StripeMock
893
1009
  end
894
1010
 
895
1011
  def self.mock_balance_transaction(params = {})
896
- currency = params[:currency] || 'usd'
1012
+ currency = params[:currency] || StripeMock.default_currency
897
1013
  bt_id = params[:id] || 'test_txn_default'
898
1014
  source = params[:source] || 'ch_test_charge'
899
1015
  {
@@ -927,5 +1043,50 @@ module StripeMock
927
1043
  type: "charge"
928
1044
  }.merge(params)
929
1045
  end
1046
+
1047
+ def self.mock_subscription_item(params = {})
1048
+ iid = params[:id] || 'test_txn_default'
1049
+ {
1050
+ id: iid,
1051
+ object: 'subscription_item',
1052
+ created: 1504716183,
1053
+ metadata: {
1054
+ },
1055
+ plan: {
1056
+ id: 'PER_USER_PLAN1',
1057
+ object: 'plan',
1058
+ amount: 1337,
1059
+ created: 1504716177,
1060
+ currency: StripeMock.default_currency,
1061
+ interval: 'month',
1062
+ interval_count: 1,
1063
+ livemode: false,
1064
+ metadata: {},
1065
+ name: 'StripeMock Default Plan ID',
1066
+ statement_descriptor: nil,
1067
+ trial_period_days: nil
1068
+ },
1069
+ quantity: 2
1070
+ }.merge(params)
1071
+ end
1072
+
1073
+ def self.mock_ephemeral_key(**params)
1074
+ created = Time.now.to_i
1075
+ expires = created + 34_000
1076
+ {
1077
+ id: "ephkey_default",
1078
+ object: "ephemeral_key",
1079
+ associated_objects: [
1080
+ {
1081
+ id: params[:customer],
1082
+ type: "customer"
1083
+ }
1084
+ ],
1085
+ created: created,
1086
+ expires: expires,
1087
+ livemode: false,
1088
+ secret: "ek_test_default"
1089
+ }
1090
+ end
930
1091
  end
931
1092
  end
@@ -20,12 +20,15 @@ module StripeMock
20
20
  @@handlers.find {|h| method_url =~ h[:route] }
21
21
  end
22
22
 
23
+ include StripeMock::RequestHandlers::ExternalAccounts
23
24
  include StripeMock::RequestHandlers::Accounts
25
+ include StripeMock::RequestHandlers::Balance
24
26
  include StripeMock::RequestHandlers::BalanceTransactions
25
27
  include StripeMock::RequestHandlers::Charges
26
28
  include StripeMock::RequestHandlers::Cards
27
29
  include StripeMock::RequestHandlers::Sources
28
30
  include StripeMock::RequestHandlers::Subscriptions # must be before Customers
31
+ include StripeMock::RequestHandlers::SubscriptionItems
29
32
  include StripeMock::RequestHandlers::Customers
30
33
  include StripeMock::RequestHandlers::Coupons
31
34
  include StripeMock::RequestHandlers::Disputes
@@ -34,21 +37,26 @@ module StripeMock
34
37
  include StripeMock::RequestHandlers::InvoiceItems
35
38
  include StripeMock::RequestHandlers::Orders
36
39
  include StripeMock::RequestHandlers::Plans
40
+ include StripeMock::RequestHandlers::Products
37
41
  include StripeMock::RequestHandlers::Refunds
38
42
  include StripeMock::RequestHandlers::Recipients
39
43
  include StripeMock::RequestHandlers::Transfers
40
44
  include StripeMock::RequestHandlers::Tokens
41
45
  include StripeMock::RequestHandlers::CountrySpec
46
+ include StripeMock::RequestHandlers::Payouts
47
+ include StripeMock::RequestHandlers::EphemeralKey
48
+ include StripeMock::RequestHandlers::TaxRates
42
49
 
43
-
44
- attr_reader :accounts, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
50
+ attr_reader :accounts, :balance, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
45
51
  :disputes, :events, :invoices, :invoice_items, :orders, :plans, :recipients,
46
- :refunds, :transfers, :subscriptions, :country_spec
52
+ :refunds, :transfers, :payouts, :subscriptions, :country_spec, :subscriptions_items,
53
+ :products, :tax_rates
47
54
 
48
- attr_accessor :error_queue, :debug
55
+ attr_accessor :error_queue, :debug, :conversion_rate, :account_balance
49
56
 
50
57
  def initialize
51
58
  @accounts = {}
59
+ @balance = Data.mock_balance
52
60
  @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'])
53
61
  @bank_tokens = {}
54
62
  @card_tokens = {}
@@ -61,22 +69,29 @@ module StripeMock
61
69
  @invoice_items = {}
62
70
  @orders = {}
63
71
  @plans = {}
72
+ @products = {}
64
73
  @recipients = {}
65
74
  @refunds = {}
66
75
  @transfers = {}
76
+ @payouts = {}
67
77
  @subscriptions = {}
78
+ @subscriptions_items = {}
68
79
  @country_spec = {}
80
+ @tax_rates = {}
69
81
 
70
82
  @debug = false
71
83
  @error_queue = ErrorQueue.new
72
84
  @id_counter = 0
73
85
  @balance_transaction_counter = 0
86
+ @dispute_counter = 0
87
+ @conversion_rate = 1.0
88
+ @account_balance = 10000
74
89
 
75
90
  # This is basically a cache for ParamValidators
76
91
  @base_strategy = TestStrategies::Base.new
77
92
  end
78
93
 
79
- def mock_request(method, url, api_key, params={}, headers={}, api_base_url=nil)
94
+ def mock_request(method, url, api_key: nil, api_base: nil, params: {}, headers: {})
80
95
  return {} if method == :xtest
81
96
 
82
97
  api_key ||= (Stripe.api_key || DUMMY_API_KEY)
@@ -99,7 +114,7 @@ module StripeMock
99
114
  else
100
115
  res = self.send(handler[:name], handler[:route], method_url, params, headers)
101
116
  puts " [res] #{res}" if @debug == true
102
- [res, api_key]
117
+ [to_faraday_hash(res), api_key]
103
118
  end
104
119
  else
105
120
  puts "[StripeMock] Warning : Unrecognized endpoint + method : [#{method} #{url}]"
@@ -113,12 +128,44 @@ module StripeMock
113
128
  @events[ event_data[:id] ] = symbolize_names(event_data)
114
129
  end
115
130
 
131
+ def upsert_stripe_object(object, attributes)
132
+ # Most Stripe entities can be created via the API. However, some entities are created when other Stripe entities are
133
+ # created - such as when BalanceTransactions are created when Charges are created. This method provides the ability
134
+ # to create these internal entities.
135
+ # It also provides the ability to modify existing Stripe entities.
136
+ id = attributes[:id]
137
+ if id.nil? || id == ""
138
+ # Insert new Stripe object
139
+ case object
140
+ when :balance_transaction
141
+ id = new_balance_transaction('txn', attributes)
142
+ when :dispute
143
+ id = new_dispute('dp', attributes)
144
+ else
145
+ raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
146
+ end
147
+ else
148
+ # Update existing Stripe object
149
+ case object
150
+ when :balance_transaction
151
+ btxn = assert_existence :balance_transaction, id, @balance_transactions[id]
152
+ btxn.merge!(attributes)
153
+ when :dispute
154
+ dispute = assert_existence :dispute, id, @disputes[id]
155
+ dispute.merge!(attributes)
156
+ else
157
+ raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
158
+ end
159
+ end
160
+ id
161
+ end
162
+
116
163
  private
117
164
 
118
165
  def assert_existence(type, id, obj, message=nil)
119
166
  if obj.nil?
120
167
  msg = message || "No such #{type}: #{id}"
121
- raise Stripe::InvalidRequestError.new(msg, type.to_s, 404)
168
+ raise Stripe::InvalidRequestError.new(msg, type.to_s, http_status: 404)
122
169
  end
123
170
  obj
124
171
  end
@@ -134,15 +181,53 @@ module StripeMock
134
181
  amount = params[:amount]
135
182
  unless amount.nil?
136
183
  # Fee calculation
137
- params[:fee] ||= (30 + (amount.abs * 0.029).ceil) * (amount > 0 ? 1 : -1)
184
+ calculate_fees(params) unless params[:fee]
185
+ params[:net] = amount - params[:fee]
186
+ params[:amount] = amount * @conversion_rate
138
187
  end
139
188
  @balance_transactions[id] = Data.mock_balance_transaction(params.merge(id: id))
140
189
  id
141
190
  end
142
191
 
192
+ def new_dispute(prefix, params = {})
193
+ id = "#{StripeMock.global_id_prefix}#{prefix}_#{@dispute_counter += 1}"
194
+ @disputes[id] = Data.mock_dispute(params.merge(id: id))
195
+ id
196
+ end
197
+
143
198
  def symbolize_names(hash)
144
199
  Stripe::Util.symbolize_names(hash)
145
200
  end
146
201
 
202
+ def to_faraday_hash(hash)
203
+ response = Struct.new(:data)
204
+ response.new(hash)
205
+ end
206
+
207
+ def calculate_fees(params)
208
+ application_fee = params[:application_fee] || 0
209
+ params[:fee] = processing_fee(params[:amount]) + application_fee
210
+ params[:fee_details] = [
211
+ {
212
+ amount: processing_fee(params[:amount]),
213
+ application: nil,
214
+ currency: params[:currency] || StripeMock.default_currency,
215
+ description: "Stripe processing fees",
216
+ type: "stripe_fee"
217
+ }
218
+ ]
219
+ if application_fee
220
+ params[:fee_details] << {
221
+ amount: application_fee,
222
+ currency: params[:currency] || StripeMock.default_currency,
223
+ description: "Application fee",
224
+ type: "application_fee"
225
+ }
226
+ end
227
+ end
228
+
229
+ def processing_fee(amount)
230
+ (30 + (amount.abs * 0.029).ceil) * (amount > 0 ? 1 : -1)
231
+ end
147
232
  end
148
233
  end