stripe-ruby-mock 2.4.0 → 2.5.8

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.
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