stripe-ruby-mock 2.3.1 → 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 (106) 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 -13
  9. data/lib/stripe_mock/api/instance.rb +16 -6
  10. data/lib/stripe_mock/api/webhooks.rb +8 -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 +398 -58
  14. data/lib/stripe_mock/instance.rb +105 -9
  15. data/lib/stripe_mock/request_handlers/accounts.rb +41 -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 +44 -33
  19. data/lib/stripe_mock/request_handlers/country_spec.rb +22 -0
  20. data/lib/stripe_mock/request_handlers/coupons.rb +5 -4
  21. data/lib/stripe_mock/request_handlers/customers.rb +29 -11
  22. data/lib/stripe_mock/request_handlers/ephemeral_key.rb +13 -0
  23. data/lib/stripe_mock/request_handlers/external_accounts.rb +55 -0
  24. data/lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb +1 -1
  25. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +9 -7
  26. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +10 -6
  27. data/lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb +49 -0
  28. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +59 -16
  29. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +3 -2
  30. data/lib/stripe_mock/request_handlers/invoices.rb +93 -14
  31. data/lib/stripe_mock/request_handlers/orders.rb +5 -5
  32. data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
  33. data/lib/stripe_mock/request_handlers/plans.rb +1 -0
  34. data/lib/stripe_mock/request_handlers/products.rb +43 -0
  35. data/lib/stripe_mock/request_handlers/recipients.rb +12 -0
  36. data/lib/stripe_mock/request_handlers/refunds.rb +91 -0
  37. data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
  38. data/lib/stripe_mock/request_handlers/subscriptions.rb +101 -39
  39. data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
  40. data/lib/stripe_mock/request_handlers/tokens.rb +9 -3
  41. data/lib/stripe_mock/request_handlers/transfers.rb +11 -5
  42. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +15 -1
  43. data/lib/stripe_mock/server.rb +14 -1
  44. data/lib/stripe_mock/test_strategies/base.rb +10 -5
  45. data/lib/stripe_mock/test_strategies/live.rb +5 -0
  46. data/lib/stripe_mock/test_strategies/mock.rb +8 -0
  47. data/lib/stripe_mock/util.rb +8 -2
  48. data/lib/stripe_mock/version.rb +1 -1
  49. data/lib/stripe_mock/webhook_fixtures/account.external_account.created.json +27 -0
  50. data/lib/stripe_mock/webhook_fixtures/account.external_account.deleted.json +27 -0
  51. data/lib/stripe_mock/webhook_fixtures/account.external_account.updated.json +27 -0
  52. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  53. data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_reinstated.json +88 -0
  54. data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_withdrawn.json +88 -0
  55. data/lib/stripe_mock/webhook_fixtures/charge.updated.json +58 -0
  56. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +40 -10
  57. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +39 -10
  58. data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +39 -10
  59. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +40 -11
  60. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +3 -2
  61. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +1 -1
  62. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +92 -85
  63. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +3 -2
  64. data/lib/stripe_mock/webhook_fixtures/plan.created.json +1 -1
  65. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +1 -1
  66. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +1 -1
  67. data/lib/stripe_mock.rb +15 -0
  68. data/spec/api/instance_spec.rb +30 -0
  69. data/spec/instance_spec.rb +54 -4
  70. data/spec/integration_examples/prepare_error_examples.rb +6 -6
  71. data/spec/list_spec.rb +27 -10
  72. data/spec/readme_spec.rb +2 -0
  73. data/spec/server_spec.rb +7 -3
  74. data/spec/shared_stripe_examples/account_examples.rb +46 -0
  75. data/spec/shared_stripe_examples/balance_examples.rb +11 -0
  76. data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
  77. data/spec/shared_stripe_examples/bank_examples.rb +28 -1
  78. data/spec/shared_stripe_examples/card_examples.rb +23 -5
  79. data/spec/shared_stripe_examples/card_token_examples.rb +1 -0
  80. data/spec/shared_stripe_examples/charge_examples.rb +131 -26
  81. data/spec/shared_stripe_examples/country_specs_examples.rb +18 -0
  82. data/spec/shared_stripe_examples/coupon_examples.rb +8 -2
  83. data/spec/shared_stripe_examples/customer_examples.rb +90 -0
  84. data/spec/shared_stripe_examples/dispute_examples.rb +19 -8
  85. data/spec/shared_stripe_examples/ephemeral_key_examples.rb +17 -0
  86. data/spec/shared_stripe_examples/error_mock_examples.rb +15 -5
  87. data/spec/shared_stripe_examples/external_account_examples.rb +170 -0
  88. data/spec/shared_stripe_examples/extra_features_examples.rb +2 -0
  89. data/spec/shared_stripe_examples/invoice_examples.rb +314 -51
  90. data/spec/shared_stripe_examples/payout_examples.rb +68 -0
  91. data/spec/shared_stripe_examples/plan_examples.rb +47 -4
  92. data/spec/shared_stripe_examples/product_example.rb +65 -0
  93. data/spec/shared_stripe_examples/recipient_examples.rb +13 -7
  94. data/spec/shared_stripe_examples/refund_examples.rb +453 -84
  95. data/spec/shared_stripe_examples/subscription_examples.rb +477 -32
  96. data/spec/shared_stripe_examples/subscription_items_examples.rb +75 -0
  97. data/spec/shared_stripe_examples/tax_rate_examples.rb +42 -0
  98. data/spec/shared_stripe_examples/transfer_examples.rb +72 -23
  99. data/spec/shared_stripe_examples/webhook_event_examples.rb +74 -5
  100. data/spec/spec_helper.rb +7 -6
  101. data/spec/stripe_mock_spec.rb +16 -3
  102. data/spec/support/stripe_examples.rb +8 -1
  103. data/spec/util_spec.rb +35 -1
  104. data/stripe-ruby-mock.gemspec +1 -1
  105. metadata +44 -8
  106. data/ChangeLog.rdoc +0 -4
@@ -0,0 +1,36 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module SubscriptionItems
4
+
5
+ def SubscriptionItems.included(klass)
6
+ klass.add_handler 'get /v1/subscription_items', :retrieve_subscription_items
7
+ klass.add_handler 'post /v1/subscription_items/([^/]*)', :update_subscription_item
8
+ klass.add_handler 'post /v1/subscription_items', :create_subscription_items
9
+ end
10
+
11
+ def retrieve_subscription_items(route, method_url, params, headers)
12
+ route =~ method_url
13
+
14
+ require_param(:subscription) unless params[:subscription]
15
+
16
+ Data.mock_list_object(subscriptions_items, params)
17
+ end
18
+
19
+ def create_subscription_items(route, method_url, params, headers)
20
+ params[:id] ||= new_id('si')
21
+
22
+ require_param(:subscription) unless params[:subscription]
23
+ require_param(:plan) unless params[:plan]
24
+
25
+ subscriptions_items[params[:id]] = Data.mock_subscription_item(params.merge(plan: plans[params[:plan]]))
26
+ end
27
+
28
+ def update_subscription_item(route, method_url, params, headers)
29
+ route =~ method_url
30
+
31
+ subscription_item = assert_existence :subscription_item, $1, subscriptions_items[$1]
32
+ subscription_item.merge!(params.merge(plan: plans[params[:plan]]))
33
+ end
34
+ end
35
+ end
36
+ end
@@ -9,11 +9,11 @@ module StripeMock
9
9
  klass.add_handler 'post /v1/subscriptions/(.*)', :update_subscription
10
10
  klass.add_handler 'delete /v1/subscriptions/(.*)', :cancel_subscription
11
11
 
12
- klass.add_handler 'post /v1/customers/(.*)/subscriptions', :create_customer_subscription
13
- klass.add_handler 'get /v1/customers/(.*)/subscriptions/(.*)', :retrieve_customer_subscription
14
- klass.add_handler 'get /v1/customers/(.*)/subscriptions', :retrieve_customer_subscriptions
15
- klass.add_handler 'post /v1/customers/(.*)subscriptions/(.*)', :update_subscription
16
- klass.add_handler 'delete /v1/customers/(.*)/subscriptions/(.*)', :cancel_subscription
12
+ klass.add_handler 'post /v1/customers/(.*)/subscription(?:s)?', :create_customer_subscription
13
+ klass.add_handler 'get /v1/customers/(.*)/subscription(?:s)?/(.*)', :retrieve_customer_subscription
14
+ klass.add_handler 'get /v1/customers/(.*)/subscription(?:s)?', :retrieve_customer_subscriptions
15
+ klass.add_handler 'post /v1/customers/(.*)subscription(?:s)?/(.*)', :update_subscription
16
+ klass.add_handler 'delete /v1/customers/(.*)/subscription(?:s)?/(.*)', :cancel_subscription
17
17
  end
18
18
 
19
19
  def retrieve_customer_subscription(route, method_url, params, headers)
@@ -35,9 +35,7 @@ module StripeMock
35
35
  def create_customer_subscription(route, method_url, params, headers)
36
36
  route =~ method_url
37
37
 
38
- plan_id = params[:plan].to_s
39
- plan = assert_existence :plan, plan_id, plans[plan_id]
40
-
38
+ subscription_plans = get_subscription_plans_from_params(params)
41
39
  customer = assert_existence :customer, $1, customers[$1]
42
40
 
43
41
  if params[:source]
@@ -46,11 +44,12 @@ module StripeMock
46
44
  customer[:default_source] = new_card[:id]
47
45
  end
48
46
 
49
- # Ensure customer has card to charge if plan has no trial and is not free
50
- verify_card_present(customer, plan, params)
51
-
52
47
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
53
- subscription.merge!(custom_subscription_params(plan, customer, params))
48
+ subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
49
+
50
+ # Ensure customer has card to charge if plan has no trial and is not free
51
+ # Note: needs updating for subscriptions with multiple plans
52
+ verify_card_present(customer, subscription_plans.first, subscription, params)
54
53
 
55
54
  if params[:coupon]
56
55
  coupon_id = params[:coupon]
@@ -61,9 +60,9 @@ module StripeMock
61
60
  coupon = coupons[coupon_id]
62
61
 
63
62
  if coupon
64
- subscription[:discount] = Stripe::Util.convert_to_stripe_object({ coupon: coupon }, {})
63
+ add_coupon_to_object(subscription, coupon)
65
64
  else
66
- raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', 400)
65
+ raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
67
66
  end
68
67
  end
69
68
 
@@ -74,25 +73,50 @@ module StripeMock
74
73
  end
75
74
 
76
75
  def create_subscription(route, method_url, params, headers)
76
+ if headers && headers[:idempotency_key]
77
+ if subscriptions.any?
78
+ original_subscription = subscriptions.values.find { |c| c[:idempotency_key] == headers[:idempotency_key]}
79
+ puts original_subscription
80
+ return subscriptions[original_subscription[:id]] if original_subscription
81
+ end
82
+ end
77
83
  route =~ method_url
78
84
 
79
- plan_id = params[:plan].to_s
80
- plan = assert_existence :plan, plan_id, plans[plan_id]
85
+ subscription_plans = get_subscription_plans_from_params(params)
81
86
 
82
- customer_id = params[:customer].to_s
87
+ customer = params[:customer]
88
+ customer_id = customer.is_a?(Stripe::Customer) ? customer[:id] : customer.to_s
83
89
  customer = assert_existence :customer, customer_id, customers[customer_id]
84
90
 
91
+ if subscription_plans && customer
92
+ subscription_plans.each do |plan|
93
+ unless customer[:currency].to_s == plan[:currency].to_s
94
+ raise Stripe::InvalidRequestError.new("Customer's currency of #{customer[:currency]} does not match plan's currency of #{plan[:currency]}", 'currency', http_status: 400)
95
+ end
96
+ end
97
+ end
98
+
85
99
  if params[:source]
86
100
  new_card = get_card_by_token(params.delete(:source))
87
101
  add_card_to_object(:customer, new_card, customer)
88
102
  customer[:default_source] = new_card[:id]
89
103
  end
90
104
 
91
- # Ensure customer has card to charge if plan has no trial and is not free
92
- verify_card_present(customer, plan, params)
105
+ allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start created prorate billing_cycle_anchor billing days_until_due idempotency_key)
106
+ unknown_params = params.keys - allowed_params.map(&:to_sym)
107
+ if unknown_params.length > 0
108
+ raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
109
+ end
93
110
 
94
111
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
95
- subscription.merge!(custom_subscription_params(plan, customer, params))
112
+ subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
113
+ if headers[:idempotency_key]
114
+ subscription[:idempotency_key] = headers[:idempotency_key]
115
+ end
116
+
117
+ # Ensure customer has card to charge if plan has no trial and is not free
118
+ # Note: needs updating for subscriptions with multiple plans
119
+ verify_card_present(customer, subscription_plans.first, subscription, params)
96
120
 
97
121
  if params[:coupon]
98
122
  coupon_id = params[:coupon]
@@ -103,9 +127,9 @@ module StripeMock
103
127
  coupon = coupons[coupon_id]
104
128
 
105
129
  if coupon
106
- subscription[:discount] = Stripe::Util.convert_to_stripe_object({ coupon: coupon }, {})
130
+ add_coupon_to_object(subscription, coupon)
107
131
  else
108
- raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', 400)
132
+ raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
109
133
  end
110
134
  end
111
135
 
@@ -145,11 +169,12 @@ module StripeMock
145
169
  customer[:default_source] = new_card[:id]
146
170
  end
147
171
 
148
- # expand the plan for addition to the customer object
149
- plan_name =
150
- params[:plan].is_a?(String) ? params[:plan] : subscription[:plan][:id]
172
+ subscription_plans = get_subscription_plans_from_params(params)
151
173
 
152
- plan = plans[plan_name]
174
+ # subscription plans are not being updated but load them for the response
175
+ if subscription_plans.empty?
176
+ subscription_plans = subscription[:items][:data].map { |item| item[:plan] }
177
+ end
153
178
 
154
179
  if params[:coupon]
155
180
  coupon_id = params[:coupon]
@@ -158,17 +183,15 @@ module StripeMock
158
183
  # coupon = assert_existence :coupon, coupon_id, coupons[coupon_id]
159
184
 
160
185
  coupon = coupons[coupon_id]
161
-
162
186
  if coupon
163
- subscription[:discount] = Stripe::Util.convert_to_stripe_object({ coupon: coupon }, {})
187
+ add_coupon_to_object(subscription, coupon)
188
+ elsif coupon_id == ""
189
+ subscription[:discount] = nil
164
190
  else
165
- raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', 400)
191
+ raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
166
192
  end
167
193
  end
168
-
169
- assert_existence :plan, plan_name, plan
170
- params[:plan] = plan if params[:plan]
171
- verify_card_present(customer, plan)
194
+ verify_card_present(customer, subscription_plans.first, subscription)
172
195
 
173
196
  if subscription[:cancel_at_period_end]
174
197
  subscription[:cancel_at_period_end] = false
@@ -176,7 +199,8 @@ module StripeMock
176
199
  end
177
200
 
178
201
  params[:current_period_start] = subscription[:current_period_start]
179
- subscription.merge!(custom_subscription_params(plan, customer, params))
202
+ params[:trial_end] = params[:trial_end] || subscription[:trial_end]
203
+ subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
180
204
 
181
205
  # delete the old subscription, replace with the new subscription
182
206
  customer[:subscriptions][:data].reject! { |sub| sub[:id] == subscription[:id] }
@@ -215,11 +239,49 @@ module StripeMock
215
239
 
216
240
  private
217
241
 
218
- def verify_card_present(customer, plan, params={})
219
- if customer[:default_source].nil? && customer[:trial_end].nil? && plan[:trial_period_days].nil? &&
220
- plan[:amount] != 0 && plan[:trial_end].nil? && params[:trial_end].nil?
221
- raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, 400)
242
+ def get_subscription_plans_from_params(params)
243
+ plan_ids = if params[:plan]
244
+ [params[:plan].to_s]
245
+ elsif params[:items]
246
+ items = params[:items]
247
+ items = items.values if items.respond_to?(:values)
248
+ items.map { |item| item[:plan].to_s if item[:plan] }
249
+ else
250
+ []
251
+ end
252
+ plan_ids.each do |plan_id|
253
+ assert_existence :plan, plan_id, plans[plan_id]
222
254
  end
255
+ plan_ids.map { |plan_id| plans[plan_id] }
256
+ end
257
+
258
+ # Ensure customer has card to charge unless one of the following criterias is met:
259
+ # 1) is in trial
260
+ # 2) is free
261
+ # 3) has billing set to send invoice
262
+ def verify_card_present(customer, plan, subscription, params={})
263
+ return if customer[:default_source]
264
+ return if customer[:trial_end]
265
+ return if params[:trial_end]
266
+
267
+ plan_trial_period_days = plan[:trial_period_days] || 0
268
+ plan_has_trial = plan_trial_period_days != 0 || plan[:amount] == 0 || plan[:trial_end]
269
+ return if plan && plan_has_trial
270
+
271
+ return if subscription && subscription[:trial_end] && subscription[:trial_end] != 'now'
272
+
273
+ if subscription[:items]
274
+ trial = subscription[:items][:data].none? do |item|
275
+ plan = item[:plan]
276
+ (plan[:trial_period_days].nil? || plan[:trial_period_days] == 0) &&
277
+ (plan[:trial_end].nil? || plan[:trial_end] == 'now')
278
+ end
279
+ return if trial
280
+ end
281
+
282
+ return if params[:billing] == 'send_invoice'
283
+
284
+ raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, http_status: 400)
223
285
  end
224
286
 
225
287
  def verify_active_status(subscription)
@@ -227,7 +289,7 @@ module StripeMock
227
289
 
228
290
  if status == 'canceled'
229
291
  message = "No such subscription: #{id}"
230
- raise Stripe::InvalidRequestError.new(message, 'subscription', 404)
292
+ raise Stripe::InvalidRequestError.new(message, 'subscription', http_status: 404)
231
293
  end
232
294
  end
233
295
  end
@@ -0,0 +1,36 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module TaxRates
4
+ def TaxRates.included(klass)
5
+ klass.add_handler 'post /v1/tax_rates', :new_tax_rate
6
+ klass.add_handler 'post /v1/tax_rates/([^/]*)', :update_tax_rate
7
+ klass.add_handler 'get /v1/tax_rates/([^/]*)', :get_tax_rate
8
+ klass.add_handler 'get /v1/tax_rates', :list_tax_rates
9
+ end
10
+
11
+ def update_tax_rate(route, method_url, params, headers)
12
+ route =~ method_url
13
+ rate = assert_existence :tax_rate, $1, tax_rates[$1]
14
+ rate.merge!(params)
15
+ rate
16
+ end
17
+
18
+ def new_tax_rate(route, method_url, params, headers)
19
+ params[:id] ||= new_id('txr')
20
+ tax_rates[ params[:id] ] = Data.mock_tax_rate(params)
21
+ tax_rates[ params[:id] ]
22
+ end
23
+
24
+ def list_tax_rates(route, method_url, params, headers)
25
+ Data.mock_list_object(tax_rates.values, params)
26
+ end
27
+
28
+ def get_tax_rate(route, method_url, params, headers)
29
+ route =~ method_url
30
+ tax_rate = assert_existence :tax_rate, $1, tax_rates[$1]
31
+ tax_rate.clone
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -9,7 +9,7 @@ module StripeMock
9
9
 
10
10
  def create_token(route, method_url, params, headers)
11
11
  if params[:customer].nil? && params[:card].nil? && params[:bank_account].nil?
12
- raise Stripe::InvalidRequestError.new('You must supply either a card, customer, or bank account to create a token.', nil, 400)
12
+ raise Stripe::InvalidRequestError.new('You must supply either a card, customer, or bank account to create a token.', nil, http_status: 400)
13
13
  end
14
14
 
15
15
  cus_id = params[:customer]
@@ -31,6 +31,12 @@ module StripeMock
31
31
  params[:card][:fingerprint] = StripeMock::Util.fingerprint(params[:card][:number])
32
32
  params[:card][:last4] = params[:card][:number][-4,4]
33
33
  customer_card = params[:card]
34
+ elsif params[:bank_account].is_a?(String)
35
+ customer = assert_existence :customer, cus_id, customers[cus_id]
36
+
37
+ # params[:bank_account] is an id; grab it from the db
38
+ bank_account = verify_bank_account(customer, params[:bank_account])
39
+ assert_existence :bank_account, params[:bank_account], bank_account
34
40
  elsif params[:bank_account]
35
41
  # params[:card] is a hash of cc info; "Sanitize" the card number
36
42
  bank_account = params[:bank_account]
@@ -40,12 +46,12 @@ module StripeMock
40
46
  end
41
47
 
42
48
  if bank_account
43
- token_id = generate_bank_token(bank_account)
49
+ token_id = generate_bank_token(bank_account.dup)
44
50
  bank_account = @bank_tokens[token_id]
45
51
 
46
52
  Data.mock_bank_account_token(params.merge :id => token_id, :bank_account => bank_account)
47
53
  else
48
- token_id = generate_card_token(customer_card)
54
+ token_id = generate_card_token(customer_card.dup)
49
55
  card = @card_tokens[token_id]
50
56
 
51
57
  Data.mock_card_token(params.merge :id => token_id, :card => card)
@@ -10,13 +10,19 @@ module StripeMock
10
10
  end
11
11
 
12
12
  def get_all_transfers(route, method_url, params, headers)
13
- if recipient = params[:recipient]
14
- assert_existence :recipient, recipient, recipients[recipient]
13
+ extra_params = params.keys - [:created, :destination, :ending_before,
14
+ :limit, :starting_after, :transfer_group]
15
+ unless extra_params.empty?
16
+ raise Stripe::InvalidRequestError.new("Received unknown parameter: #{extra_params[0]}", extra_params[0].to_s, http_status: 400)
17
+ end
18
+
19
+ if destination = params[:destination]
20
+ assert_existence :destination, destination, accounts[destination]
15
21
  end
16
22
 
17
23
  _transfers = transfers.each_with_object([]) do |(_, transfer), array|
18
- if recipient
19
- array << transfer if transfer[:recipient] == recipient
24
+ if destination
25
+ array << transfer if transfer[:destination] == destination
20
26
  else
21
27
  array << transfer
22
28
  end
@@ -36,7 +42,7 @@ module StripeMock
36
42
  end
37
43
 
38
44
  unless params[:amount].is_a?(Integer) || (params[:amount].is_a?(String) && /^\d+$/.match(params[:amount]))
39
- raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', 400)
45
+ raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', http_status: 400)
40
46
  end
41
47
 
42
48
  transfers[id] = Data.mock_transfer(params.merge :id => id)
@@ -6,13 +6,27 @@ module StripeMock
6
6
  params[:id] = params[:id].to_s
7
7
 
8
8
  @base_strategy.create_plan_params.keys.each do |name|
9
- raise Stripe::InvalidRequestError.new("Missing required param: #{name}.", name) if params[name].nil?
9
+ message =
10
+ if name == :amount
11
+ "Plans require an `#{name}` parameter to be set."
12
+ else
13
+ "Missing required param: #{name}."
14
+ end
15
+ raise Stripe::InvalidRequestError.new(message, name) if params[name].nil?
10
16
  end
17
+
11
18
  if plans[ params[:id] ]
12
19
  raise Stripe::InvalidRequestError.new("Plan already exists.", :id)
13
20
  end
21
+
22
+ unless params[:amount].integer?
23
+ raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", :amount)
24
+ end
14
25
  end
15
26
 
27
+ def require_param(param_name)
28
+ raise Stripe::InvalidRequestError.new("Missing required param: #{param_name}.", param_name.to_s, http_status: 400)
29
+ end
16
30
  end
17
31
  end
18
32
  end
@@ -23,7 +23,7 @@ module StripeMock
23
23
  {
24
24
  :error_raised => 'invalid_request',
25
25
  :error_params => [
26
- e.message, e.param, e.http_status, e.http_body, e.json_body
26
+ e.message, e.param, { http_status: e.http_status, http_body: e.http_body, json_body: e.json_body}
27
27
  ]
28
28
  }
29
29
  end
@@ -65,6 +65,14 @@ module StripeMock
65
65
  @instance.generate_webhook_event(event_data)
66
66
  end
67
67
 
68
+ def set_conversion_rate(value)
69
+ @instance.conversion_rate = value
70
+ end
71
+
72
+ def set_account_balance(value)
73
+ @instance.account_balance = value
74
+ end
75
+
68
76
  def error_queue
69
77
  @instance.error_queue
70
78
  end
@@ -76,5 +84,10 @@ module StripeMock
76
84
  def ping
77
85
  true
78
86
  end
87
+
88
+ def upsert_stripe_object(object, attributes)
89
+ @instance.upsert_stripe_object(object, attributes)
90
+ end
91
+
79
92
  end
80
93
  end
@@ -3,17 +3,20 @@ module StripeMock
3
3
  class Base
4
4
 
5
5
  def create_plan_params(params={})
6
+ currency = params[:currency] || StripeMock.default_currency
6
7
  {
7
8
  :id => 'stripe_mock_default_plan_id',
8
- :name => 'StripeMock Default Plan ID',
9
+ :product => {
10
+ :name => 'StripeMock Default Plan ID'
11
+ },
9
12
  :amount => 1337,
10
- :currency => 'usd',
13
+ :currency => currency,
11
14
  :interval => 'month'
12
15
  }.merge(params)
13
16
  end
14
17
 
15
18
  def generate_card_token(card_params={})
16
- card_data = { :number => "4242424242424242", :exp_month => 9, :exp_year => 2018, :cvc => "999" }
19
+ card_data = { :number => "4242424242424242", :exp_month => 9, :exp_year => (Time.now.year + 5), :cvc => "999", :tokenization_method => nil }
17
20
  card = StripeMock::Util.card_merge(card_data, card_params)
18
21
  card[:fingerprint] = StripeMock::Util.fingerprint(card[:number]) if StripeMock.state == 'local'
19
22
 
@@ -22,9 +25,10 @@ module StripeMock
22
25
  end
23
26
 
24
27
  def generate_bank_token(bank_account_params={})
28
+ currency = bank_account_params[:currency] || StripeMock.default_currency
25
29
  bank_account = {
26
30
  :country => "US",
27
- :currency => "usd",
31
+ :currency => currency,
28
32
  :account_holder_name => "Jane Austen",
29
33
  :account_holder_type => "individual",
30
34
  :routing_number => "110000000",
@@ -37,10 +41,11 @@ module StripeMock
37
41
  end
38
42
 
39
43
  def create_coupon_params(params = {})
44
+ currency = params[:currency] || StripeMock.default_currency
40
45
  {
41
46
  id: '10BUCKS',
42
47
  amount_off: 1000,
43
- currency: 'usd',
48
+ currency: currency,
44
49
  max_redemptions: 100,
45
50
  metadata: {
46
51
  created_by: 'admin_acct_1'
@@ -30,6 +30,11 @@ module StripeMock
30
30
  # do nothing
31
31
  end
32
32
  end
33
+
34
+ def upsert_stripe_object(object, attributes)
35
+ raise UnsupportedRequestError.new "Updating or inserting Stripe objects in Live mode not supported"
36
+ end
37
+
33
38
  end
34
39
  end
35
40
  end
@@ -14,6 +14,14 @@ module StripeMock
14
14
  end
15
15
  end
16
16
 
17
+ def upsert_stripe_object(object, attributes = {})
18
+ if StripeMock.state == 'remote'
19
+ StripeMock.client.upsert_stripe_object(object, attributes)
20
+ elsif StripeMock.state == 'local'
21
+ StripeMock.instance.upsert_stripe_object(object, attributes)
22
+ end
23
+ end
24
+
17
25
  end
18
26
  end
19
27
  end
@@ -9,8 +9,14 @@ module StripeMock
9
9
  if oldval.is_a?(Array) && newval.is_a?(Array)
10
10
  oldval.fill(nil, oldval.length...newval.length)
11
11
  oldval.zip(newval).map {|elems|
12
- elems[1].nil? ? elems[0] : rmerge(elems[0], elems[1])
13
- }
12
+ if elems[1].nil?
13
+ elems[0]
14
+ elsif elems[1].is_a?(Hash) && elems[1].is_a?(Hash)
15
+ rmerge(elems[0], elems[1])
16
+ else
17
+ [elems[0], elems[1]].compact
18
+ end
19
+ }.flatten
14
20
  elsif oldval.is_a?(Hash) && newval.is_a?(Hash)
15
21
  rmerge(oldval, newval)
16
22
  else
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "2.3.1"
3
+ VERSION = "2.5.8"
4
4
  end
@@ -0,0 +1,27 @@
1
+ {
2
+ "created":1326853478,
3
+ "livemode":false,
4
+ "id":"evt_00000000000000",
5
+ "type":"account.external_account.created",
6
+ "object":"event",
7
+ "data":{
8
+ "object":{
9
+ "id":"ba_00000000000000",
10
+ "object":"bank_account",
11
+ "account":"acct_00000000000000",
12
+ "account_holder_name":"Jane Austen",
13
+ "account_holder_type":"individual",
14
+ "bank_name":"STRIPE TEST BANK",
15
+ "country":"US",
16
+ "currency":"eur",
17
+ "default_for_currency":false,
18
+ "fingerprint":"efGCBmiwp56O1lsN",
19
+ "last4":"6789",
20
+ "metadata":{
21
+
22
+ },
23
+ "routing_number":"110000000",
24
+ "status":"new"
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "created":1326853478,
3
+ "livemode":false,
4
+ "id":"evt_00000000000000",
5
+ "type":"account.external_account.deleted",
6
+ "object":"event",
7
+ "data":{
8
+ "object":{
9
+ "id":"ba_00000000000000",
10
+ "object":"bank_account",
11
+ "account":"acct_00000000000000",
12
+ "account_holder_name":"Jane Austen",
13
+ "account_holder_type":"individual",
14
+ "bank_name":"STRIPE TEST BANK",
15
+ "country":"US",
16
+ "currency":"eur",
17
+ "default_for_currency":false,
18
+ "fingerprint":"efGCBmiwp56O1lsN",
19
+ "last4":"6789",
20
+ "metadata":{
21
+
22
+ },
23
+ "routing_number":"110000000",
24
+ "status":"new"
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "created":1326853478,
3
+ "livemode":false,
4
+ "id":"evt_00000000000000",
5
+ "type":"account.external_account.updated",
6
+ "object":"event",
7
+ "data":{
8
+ "object":{
9
+ "id":"ba_00000000000000",
10
+ "object":"bank_account",
11
+ "account":"acct_00000000000000",
12
+ "account_holder_name":"Jane Austen",
13
+ "account_holder_type":"individual",
14
+ "bank_name":"STRIPE TEST BANK",
15
+ "country":"US",
16
+ "currency":"eur",
17
+ "default_for_currency":false,
18
+ "fingerprint":"efGCBmiwp56O1lsN",
19
+ "last4":"6789",
20
+ "metadata":{
21
+
22
+ },
23
+ "routing_number":"110000000",
24
+ "status":"new"
25
+ }
26
+ }
27
+ }
@@ -11,7 +11,7 @@
11
11
  "statement_descriptor": "TEST",
12
12
  "details_submitted": true,
13
13
  "charge_enabled": false,
14
- "transfer_enabled": false,
14
+ "payouts_enabled": false,
15
15
  "currencies_supported": [
16
16
  "USD"
17
17
  ],