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.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rspec_tests.yml +38 -0
  3. data/.rspec +2 -1
  4. data/CHANGELOG.md +62 -15
  5. data/Gemfile +1 -0
  6. data/README.md +5 -3
  7. data/lib/stripe_mock/api/client.rb +1 -1
  8. data/lib/stripe_mock/api/instance.rb +1 -1
  9. data/lib/stripe_mock/api/webhooks.rb +66 -25
  10. data/lib/stripe_mock/client.rb +2 -1
  11. data/lib/stripe_mock/data/list.rb +31 -6
  12. data/lib/stripe_mock/data.rb +201 -30
  13. data/lib/stripe_mock/instance.rb +12 -3
  14. data/lib/stripe_mock/request_handlers/account_links.rb +15 -0
  15. data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
  16. data/lib/stripe_mock/request_handlers/charges.rb +11 -4
  17. data/lib/stripe_mock/request_handlers/checkout_session.rb +179 -0
  18. data/lib/stripe_mock/request_handlers/customers.rb +22 -13
  19. data/lib/stripe_mock/request_handlers/ephemeral_key.rb +1 -1
  20. data/lib/stripe_mock/request_handlers/events.rb +30 -3
  21. data/lib/stripe_mock/request_handlers/express_login_links.rb +15 -0
  22. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +1 -0
  23. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +36 -12
  24. data/lib/stripe_mock/request_handlers/invoices.rb +10 -4
  25. data/lib/stripe_mock/request_handlers/payment_intents.rb +13 -2
  26. data/lib/stripe_mock/request_handlers/payment_methods.rb +11 -4
  27. data/lib/stripe_mock/request_handlers/prices.rb +62 -0
  28. data/lib/stripe_mock/request_handlers/promotion_codes.rb +43 -0
  29. data/lib/stripe_mock/request_handlers/refunds.rb +13 -2
  30. data/lib/stripe_mock/request_handlers/setup_intents.rb +16 -9
  31. data/lib/stripe_mock/request_handlers/sources.rb +12 -6
  32. data/lib/stripe_mock/request_handlers/subscriptions.rb +120 -21
  33. data/lib/stripe_mock/request_handlers/tokens.rb +6 -4
  34. data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
  35. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +33 -4
  36. data/lib/stripe_mock/server.rb +2 -2
  37. data/lib/stripe_mock/test_strategies/base.rb +62 -10
  38. data/lib/stripe_mock/version.rb +1 -1
  39. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  40. data/lib/stripe_mock/webhook_fixtures/balance.available.json +27 -15
  41. data/lib/stripe_mock/webhook_fixtures/charge.captured.json +143 -0
  42. data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +63 -16
  43. data/lib/stripe_mock/webhook_fixtures/charge.failed.json +49 -120
  44. data/lib/stripe_mock/webhook_fixtures/charge.refund.updated.json +35 -0
  45. data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +145 -50
  46. data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +114 -43
  47. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.json +79 -0
  48. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.payment_mode.json +53 -0
  49. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.setup_mode.json +45 -0
  50. data/lib/stripe_mock/webhook_fixtures/customer.created.json +37 -46
  51. data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +36 -32
  52. data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +31 -22
  53. data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -25
  54. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +135 -47
  55. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +134 -45
  56. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +135 -56
  57. data/lib/stripe_mock/webhook_fixtures/customer.updated.json +38 -47
  58. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +176 -49
  59. data/lib/stripe_mock/webhook_fixtures/invoice.finalized.json +171 -0
  60. data/lib/stripe_mock/webhook_fixtures/invoice.paid.json +171 -0
  61. data/lib/stripe_mock/webhook_fixtures/invoice.payment_action_required.json +171 -0
  62. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +149 -83
  63. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +149 -90
  64. data/lib/stripe_mock/webhook_fixtures/invoice.upcoming.json +70 -0
  65. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +178 -50
  66. data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +87 -13
  67. data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +88 -14
  68. data/lib/stripe_mock/webhook_fixtures/mandate.updated.json +34 -0
  69. data/lib/stripe_mock/webhook_fixtures/payment_intent.amount_capturable_updated.json +170 -0
  70. data/lib/stripe_mock/webhook_fixtures/payment_intent.canceled.json +73 -0
  71. data/lib/stripe_mock/webhook_fixtures/payment_intent.created.json +86 -0
  72. data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +225 -0
  73. data/lib/stripe_mock/webhook_fixtures/payment_intent.processing.json +162 -0
  74. data/lib/stripe_mock/webhook_fixtures/payment_intent.requires_action.json +191 -0
  75. data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +196 -0
  76. data/lib/stripe_mock/webhook_fixtures/payment_link.created.json +47 -0
  77. data/lib/stripe_mock/webhook_fixtures/payment_link.updated.json +50 -0
  78. data/lib/stripe_mock/webhook_fixtures/payment_method.attached.json +63 -0
  79. data/lib/stripe_mock/webhook_fixtures/payment_method.detached.json +62 -0
  80. data/lib/stripe_mock/webhook_fixtures/payout.created.json +40 -0
  81. data/lib/stripe_mock/webhook_fixtures/payout.paid.json +40 -0
  82. data/lib/stripe_mock/webhook_fixtures/payout.updated.json +46 -0
  83. data/lib/stripe_mock/webhook_fixtures/plan.created.json +30 -13
  84. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +30 -13
  85. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +34 -14
  86. data/lib/stripe_mock/webhook_fixtures/price.created.json +42 -0
  87. data/lib/stripe_mock/webhook_fixtures/price.deleted.json +42 -0
  88. data/lib/stripe_mock/webhook_fixtures/price.updated.json +48 -0
  89. data/lib/stripe_mock/webhook_fixtures/product.created.json +19 -13
  90. data/lib/stripe_mock/webhook_fixtures/product.deleted.json +20 -14
  91. data/lib/stripe_mock/webhook_fixtures/product.updated.json +24 -15
  92. data/lib/stripe_mock/webhook_fixtures/quote.accepted.json +92 -0
  93. data/lib/stripe_mock/webhook_fixtures/quote.canceled.json +92 -0
  94. data/lib/stripe_mock/webhook_fixtures/quote.created.json +92 -0
  95. data/lib/stripe_mock/webhook_fixtures/quote.finalized.json +92 -0
  96. data/lib/stripe_mock/webhook_fixtures/setup_intent.canceled.json +46 -0
  97. data/lib/stripe_mock/webhook_fixtures/setup_intent.created.json +51 -0
  98. data/lib/stripe_mock/webhook_fixtures/setup_intent.setup_failed.json +100 -0
  99. data/lib/stripe_mock/webhook_fixtures/setup_intent.succeeded.json +46 -0
  100. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.canceled.json +119 -0
  101. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.created.json +114 -0
  102. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.released.json +111 -0
  103. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.updated.json +125 -0
  104. data/lib/stripe_mock/webhook_fixtures/tax_rate.created.json +32 -0
  105. data/lib/stripe_mock/webhook_fixtures/tax_rate.updated.json +37 -0
  106. data/lib/stripe_mock.rb +7 -1
  107. data/spec/instance_spec.rb +7 -7
  108. data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
  109. data/spec/list_spec.rb +23 -0
  110. data/spec/readme_spec.rb +1 -1
  111. data/spec/server_spec.rb +4 -2
  112. data/spec/shared_stripe_examples/account_examples.rb +9 -1
  113. data/spec/shared_stripe_examples/account_link_examples.rb +16 -0
  114. data/spec/shared_stripe_examples/balance_examples.rb +6 -0
  115. data/spec/shared_stripe_examples/card_token_examples.rb +17 -21
  116. data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
  117. data/spec/shared_stripe_examples/customer_examples.rb +11 -13
  118. data/spec/shared_stripe_examples/express_login_link_examples.rb +12 -0
  119. data/spec/shared_stripe_examples/invoice_examples.rb +29 -8
  120. data/spec/shared_stripe_examples/payment_intent_examples.rb +74 -0
  121. data/spec/shared_stripe_examples/payment_method_examples.rb +336 -67
  122. data/spec/shared_stripe_examples/price_examples.rb +223 -0
  123. data/spec/shared_stripe_examples/product_examples.rb +1 -9
  124. data/spec/shared_stripe_examples/promotion_code_examples.rb +68 -0
  125. data/spec/shared_stripe_examples/refund_examples.rb +13 -0
  126. data/spec/shared_stripe_examples/setup_intent_examples.rb +17 -0
  127. data/spec/shared_stripe_examples/subscription_examples.rb +327 -9
  128. data/spec/shared_stripe_examples/transfer_examples.rb +10 -1
  129. data/spec/shared_stripe_examples/webhook_event_examples.rb +51 -5
  130. data/spec/spec_helper.rb +4 -0
  131. data/spec/stripe_mock_spec.rb +2 -2
  132. data/spec/support/stripe_examples.rb +8 -2
  133. data/stripe-ruby-mock.gemspec +7 -2
  134. metadata +72 -15
  135. data/.travis.yml +0 -28
  136. data/lib/stripe_mock/request_handlers/checkout.rb +0 -15
  137. data/spec/shared_stripe_examples/checkout_examples.rb +0 -19
@@ -17,26 +17,29 @@ module StripeMock
17
17
  end
18
18
 
19
19
  def retrieve_customer_subscription(route, method_url, params, headers)
20
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
20
21
  route =~ method_url
21
22
 
22
- customer = assert_existence :customer, $1, customers[$1]
23
+ customer = assert_existence :customer, $1, customers[stripe_account][$1]
23
24
  subscription = get_customer_subscription(customer, $2)
24
25
 
25
26
  assert_existence :subscription, $2, subscription
26
27
  end
27
28
 
28
29
  def retrieve_customer_subscriptions(route, method_url, params, headers)
30
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
29
31
  route =~ method_url
30
32
 
31
- customer = assert_existence :customer, $1, customers[$1]
33
+ customer = assert_existence :customer, $1, customers[stripe_account][$1]
32
34
  customer[:subscriptions]
33
35
  end
34
36
 
35
37
  def create_customer_subscription(route, method_url, params, headers)
38
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
36
39
  route =~ method_url
37
40
 
38
41
  subscription_plans = get_subscription_plans_from_params(params)
39
- customer = assert_existence :customer, $1, customers[$1]
42
+ customer = assert_existence :customer, $1, customers[stripe_account][$1]
40
43
 
41
44
  if params[:source]
42
45
  new_card = get_card_by_token(params.delete(:source))
@@ -66,6 +69,16 @@ module StripeMock
66
69
  end
67
70
  end
68
71
 
72
+ if params[:promotion_code]
73
+ promotion_code_id = params[:promotion_code]
74
+
75
+ promotion_code = promotion_codes[promotion_code_id]
76
+
77
+ unless promotion_code
78
+ raise Stripe::InvalidRequestError.new("No such promotion code: #{promotion_code_id}", 'promotion_code', http_status: 400)
79
+ end
80
+ end
81
+
69
82
  subscriptions[subscription[:id]] = subscription
70
83
  add_subscription_to_customer(customer, subscription)
71
84
 
@@ -73,10 +86,10 @@ module StripeMock
73
86
  end
74
87
 
75
88
  def create_subscription(route, method_url, params, headers)
89
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
76
90
  if headers && headers[:idempotency_key]
77
91
  if subscriptions.any?
78
92
  original_subscription = subscriptions.values.find { |c| c[:idempotency_key] == headers[:idempotency_key]}
79
- puts original_subscription
80
93
  return subscriptions[original_subscription[:id]] if original_subscription
81
94
  end
82
95
  end
@@ -86,15 +99,7 @@ module StripeMock
86
99
 
87
100
  customer = params[:customer]
88
101
  customer_id = customer.is_a?(Stripe::Customer) ? customer[:id] : customer.to_s
89
- customer = assert_existence :customer, customer_id, customers[customer_id]
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
102
+ customer = assert_existence :customer, customer_id, customers[stripe_account][customer_id]
98
103
 
99
104
  if params[:source]
100
105
  new_card = get_card_by_token(params.delete(:source))
@@ -102,7 +107,7 @@ module StripeMock
102
107
  customer[:default_source] = new_card[:id]
103
108
  end
104
109
 
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 enable_incomplete_payments cancel_at_period_end default_tax_rates payment_behavior pending_invoice_item_interval)
110
+ allowed_params = %w(id 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 enable_incomplete_payments cancel_at_period_end default_tax_rates payment_behavior pending_invoice_item_interval default_payment_method collection_method off_session trial_from_plan proration_behavior backdate_start_date transfer_data expand automatic_tax payment_settings trial_settings promotion_code)
106
111
  unknown_params = params.keys - allowed_params.map(&:to_sym)
107
112
  if unknown_params.length > 0
108
113
  raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
@@ -118,6 +123,10 @@ module StripeMock
118
123
  # Note: needs updating for subscriptions with multiple plans
119
124
  verify_card_present(customer, subscription_plans.first, subscription, params)
120
125
 
126
+ if params[:coupon] && params[:promotion_code]
127
+ raise Stripe::InvalidRequestError.new("You may only specify one of these parameters: coupon, promotion_code", "coupon", http_status: 400)
128
+ end
129
+
121
130
  if params[:coupon]
122
131
  coupon_id = params[:coupon]
123
132
 
@@ -133,11 +142,50 @@ module StripeMock
133
142
  end
134
143
  end
135
144
 
145
+ if params[:promotion_code]
146
+ promotion_code_id = params[:promotion_code]
147
+
148
+ promotion_code = promotion_codes[promotion_code_id]
149
+
150
+ unless promotion_code
151
+ raise Stripe::InvalidRequestError.new("No such promotion code: #{promotion_code_id}", 'promotion_code', http_status: 400)
152
+ end
153
+ end
154
+
155
+ if params[:trial_period_days]
156
+ subscription[:status] = 'trialing'
157
+ end
158
+
159
+ if params[:payment_behavior] == 'default_incomplete'
160
+ subscription[:status] = 'incomplete'
161
+ end
162
+
136
163
  if params[:cancel_at_period_end]
137
164
  subscription[:cancel_at_period_end] = true
138
165
  subscription[:canceled_at] = Time.now.utc.to_i
139
166
  end
140
167
 
168
+ if params[:transfer_data] && !params[:transfer_data].empty?
169
+ throw Stripe::InvalidRequestError.new(missing_param_message("transfer_data[destination]")) unless params[:transfer_data][:destination]
170
+ subscription[:transfer_data] = params[:transfer_data].dup
171
+ subscription[:transfer_data][:amount_percent] ||= 100
172
+ end
173
+
174
+ if (s = params[:expand]&.find { |s| s.start_with? 'latest_invoice' })
175
+ payment_intent = nil
176
+ unless subscription[:status] == 'trialing'
177
+ intent_status = subscription[:status] == 'incomplete' ? 'requires_payment_method' : 'succeeded'
178
+ intent = Data.mock_payment_intent({
179
+ status: intent_status,
180
+ amount: subscription[:plan][:amount],
181
+ currency: subscription[:plan][:currency]
182
+ })
183
+ payment_intent = s.include?('latest_invoice.payment_intent') ? intent : intent.id
184
+ end
185
+ invoice = Data.mock_invoice([], { payment_intent: payment_intent })
186
+ subscription[:latest_invoice] = invoice
187
+ end
188
+
141
189
  subscriptions[subscription[:id]] = subscription
142
190
  add_subscription_to_customer(customer, subscription)
143
191
 
@@ -151,22 +199,43 @@ module StripeMock
151
199
  end
152
200
 
153
201
  def retrieve_subscriptions(route, method_url, params, headers)
202
+ # stripe_account = headers && headers[:stripe_account] || Stripe.api_key
154
203
  route =~ method_url
155
204
 
156
- Data.mock_list_object(subscriptions.values, params)
157
- #customer = assert_existence :customer, $1, customers[$1]
158
- #customer[:subscriptions]
205
+ subs = subscriptions.values
206
+
207
+ case params[:status]
208
+ when nil
209
+ subs = subs.filter {|subscription| subscription[:status] != "canceled"}
210
+ when "all"
211
+ # Include all subscriptions
212
+ else
213
+ subs = subs.filter {|subscription| subscription[:status] == params[:status]}
214
+ end
215
+ if params[:current_period_end]
216
+ subs = filter_by_timestamp(subs, field: :current_period_end, value: params[:current_period_end])
217
+ end
218
+ if params[:current_period_start]
219
+ subs = filter_by_timestamp(subs, field: :current_period_start, value: params[:current_period_start])
220
+ end
221
+
222
+ Data.mock_list_object(subs, params)
159
223
  end
160
224
 
161
225
  def update_subscription(route, method_url, params, headers)
226
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
162
227
  route =~ method_url
163
228
 
229
+ if params[:billing_cycle_anchor] == 'now'
230
+ params[:billing_cycle_anchor] = Time.now.utc.to_i
231
+ end
232
+
164
233
  subscription_id = $2 ? $2 : $1
165
234
  subscription = assert_existence :subscription, subscription_id, subscriptions[subscription_id]
166
235
  verify_active_status(subscription)
167
236
 
168
237
  customer_id = subscription[:customer]
169
- customer = assert_existence :customer, customer_id, customers[customer_id]
238
+ customer = assert_existence :customer, customer_id, customers[stripe_account][customer_id]
170
239
 
171
240
  if params[:source]
172
241
  new_card = get_card_by_token(params.delete(:source))
@@ -197,6 +266,30 @@ module StripeMock
197
266
  end
198
267
  end
199
268
 
269
+ if params[:promotion_code]
270
+ promotion_code_id = params[:promotion_code]
271
+
272
+ promotion_code = promotion_codes[promotion_code_id]
273
+
274
+ if promotion_code
275
+ # You can't apply a promotion code with amount restrictions on the Customer object or on a subscription
276
+ # update API call
277
+ if promotion_code[:restrictions][:minimum_amount]
278
+ raise Stripe::InvalidRequestError.new(
279
+ "This promotion code cannot be redeemed on a subcription update because it uses the `minimum_amount` restriction.",
280
+ "promotion_code",
281
+ http_status: 400
282
+ )
283
+ end
284
+ else
285
+ raise Stripe::InvalidRequestError.new("No such promotion code: #{promotion_code_id}", 'promotion_code', http_status: 400)
286
+ end
287
+ end
288
+
289
+ if params[:trial_period_days]
290
+ subscription[:status] = 'trialing'
291
+ end
292
+
200
293
  if params[:cancel_at_period_end]
201
294
  subscription[:cancel_at_period_end] = true
202
295
  subscription[:canceled_at] = Time.now.utc.to_i
@@ -222,13 +315,14 @@ module StripeMock
222
315
  end
223
316
 
224
317
  def cancel_subscription(route, method_url, params, headers)
318
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
225
319
  route =~ method_url
226
320
 
227
321
  subscription_id = $2 ? $2 : $1
228
322
  subscription = assert_existence :subscription, subscription_id, subscriptions[subscription_id]
229
323
 
230
324
  customer_id = subscription[:customer]
231
- customer = assert_existence :customer, customer_id, customers[customer_id]
325
+ customer = assert_existence :customer, customer_id, customers[stripe_account][customer_id]
232
326
 
233
327
  cancel_params = { canceled_at: Time.now.utc.to_i }
234
328
  cancelled_at_period_end = (params[:at_period_end] == true)
@@ -257,14 +351,17 @@ module StripeMock
257
351
  elsif params[:items]
258
352
  items = params[:items]
259
353
  items = items.values if items.respond_to?(:values)
260
- items.map { |item| item[:plan].to_s if item[:plan] }
354
+ items.map { |item| item[:plan] ? item[:plan] : item[:price] }
261
355
  else
262
356
  []
263
357
  end
358
+ plan_ids.compact!
264
359
  plan_ids.each do |plan_id|
265
360
  assert_existence :plan, plan_id, plans[plan_id]
361
+ rescue Stripe::InvalidRequestError
362
+ assert_existence :price, plan_id, prices[plan_id]
266
363
  end
267
- plan_ids.map { |plan_id| plans[plan_id] }
364
+ plan_ids.map { |plan_id| plans[plan_id] || prices[plan_id]}
268
365
  end
269
366
 
270
367
  # Ensure customer has card to charge unless one of the following criterias is met:
@@ -276,6 +373,8 @@ module StripeMock
276
373
  return if customer[:invoice_settings][:default_payment_method]
277
374
  return if customer[:trial_end]
278
375
  return if params[:trial_end]
376
+ return if params[:payment_behavior] == 'default_incomplete'
377
+ return if subscription[:default_payment_method]
279
378
 
280
379
  plan_trial_period_days = plan[:trial_period_days] || 0
281
380
  plan_has_trial = plan_trial_period_days != 0 || plan[:amount] == 0 || plan[:trial_end]
@@ -8,6 +8,8 @@ module StripeMock
8
8
  end
9
9
 
10
10
  def create_token(route, method_url, params, headers)
11
+ stripe_account = headers && headers[:stripe_account] || Stripe.api_key
12
+
11
13
  if params[:customer].nil? && params[:card].nil? && params[:bank_account].nil?
12
14
  raise Stripe::InvalidRequestError.new('You must supply either a card, customer, or bank account to create a token.', nil, http_status: 400)
13
15
  end
@@ -15,13 +17,13 @@ module StripeMock
15
17
  cus_id = params[:customer]
16
18
 
17
19
  if cus_id && params[:source]
18
- customer = assert_existence :customer, cus_id, customers[cus_id]
20
+ customer = assert_existence :customer, cus_id, customers[stripe_account][cus_id]
19
21
 
20
22
  # params[:card] is an id; grab it from the db
21
23
  customer_card = get_card(customer, params[:source])
22
24
  assert_existence :card, params[:source], customer_card
23
25
  elsif params[:card].is_a?(String)
24
- customer = assert_existence :customer, cus_id, customers[cus_id]
26
+ customer = assert_existence :customer, cus_id, customers[stripe_account][cus_id]
25
27
 
26
28
  # params[:card] is an id; grab it from the db
27
29
  customer_card = get_card(customer, params[:card])
@@ -32,7 +34,7 @@ module StripeMock
32
34
  params[:card][:last4] = params[:card][:number][-4,4]
33
35
  customer_card = params[:card]
34
36
  elsif params[:bank_account].is_a?(String)
35
- customer = assert_existence :customer, cus_id, customers[cus_id]
37
+ customer = assert_existence :customer, cus_id, customers[stripe_account][cus_id]
36
38
 
37
39
  # params[:bank_account] is an id; grab it from the db
38
40
  bank_account = verify_bank_account(customer, params[:bank_account])
@@ -41,7 +43,7 @@ module StripeMock
41
43
  # params[:card] is a hash of cc info; "Sanitize" the card number
42
44
  bank_account = params[:bank_account]
43
45
  else
44
- customer = assert_existence :customer, cus_id, customers[cus_id]
46
+ customer = assert_existence :customer, cus_id, customers[stripe_account][cus_id] || customers[Stripe.api_key][cus_id]
45
47
  customer_card = get_card(customer, customer[:default_source])
46
48
  end
47
49
 
@@ -45,7 +45,18 @@ module StripeMock
45
45
  raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', http_status: 400)
46
46
  end
47
47
 
48
- transfers[id] = Data.mock_transfer(params.merge :id => id)
48
+ bal_trans_params = { amount: params[:amount].to_i, source: id }
49
+
50
+ balance_transaction_id = new_balance_transaction('txn', bal_trans_params)
51
+
52
+ transfers[id] = Data.mock_transfer(params.merge(id: id, balance_transaction: balance_transaction_id))
53
+
54
+ transfer = transfers[id].clone
55
+ if params[:expand] == ['balance_transaction']
56
+ transfer[:balance_transaction] = balance_transactions[balance_transaction_id]
57
+ end
58
+
59
+ transfer
49
60
  end
50
61
 
51
62
  def get_transfer(route, method_url, params, headers)
@@ -29,10 +29,6 @@ module StripeMock
29
29
  raise Stripe::InvalidRequestError.new(missing_param_message(k), k) if params[k].nil?
30
30
  end
31
31
 
32
- if !%w[good service].include?(params[:type])
33
- raise Stripe::InvalidRequestError.new("Invalid type: must be one of good or service", :type)
34
- end
35
-
36
32
  if products[ params[:id] ]
37
33
  raise Stripe::InvalidRequestError.new(already_exists_message(Stripe::Product), :id)
38
34
  end
@@ -110,9 +106,42 @@ module StripeMock
110
106
 
111
107
  end
112
108
 
109
+ def validate_create_price_params(params)
110
+ price_id = params[:id].to_s
111
+
112
+ require_param(:currency) unless params[:currency]
113
+ unless params[:product] || params[:product_data]
114
+ raise Stripe::InvalidRequestError("Requires product or product_data")
115
+ end
116
+
117
+ product_id = params[:product] || create_product(nil, nil, params[:product_data], nil).id
118
+
119
+ if prices[price_id]
120
+ message = already_exists_message(Stripe::Price)
121
+ raise Stripe::InvalidRequestError.new(message, :id)
122
+ end
123
+
124
+ unless products[product_id]
125
+ message = not_found_message(Stripe::Product, product_id)
126
+ raise Stripe::InvalidRequestError.new(message, :product)
127
+ end
128
+
129
+ unless SUPPORTED_CURRENCIES.include?(params[:currency])
130
+ message = invalid_currency_message(params[:currency])
131
+ raise Stripe::InvalidRequestError.new(message, :currency)
132
+ end
133
+ end
134
+
135
+ def validate_list_prices_params(params)
136
+ if params[:lookup_keys] && !params[:lookup_keys].is_a?(Array)
137
+ raise Stripe::InvalidRequestError.new('Invalid array', :lookup_keys)
138
+ end
139
+ end
140
+
113
141
  def require_param(param_name)
114
142
  raise Stripe::InvalidRequestError.new("Missing required param: #{param_name}.", param_name.to_s, http_status: 400)
115
143
  end
144
+
116
145
  end
117
146
  end
118
147
  end
@@ -16,9 +16,9 @@ module StripeMock
16
16
  self.clear_data
17
17
  end
18
18
 
19
- def mock_request(*args)
19
+ def mock_request(*args, **kwargs)
20
20
  begin
21
- @instance.mock_request(*args)
21
+ @instance.mock_request(*args, **kwargs)
22
22
  rescue Stripe::InvalidRequestError => e
23
23
  {
24
24
  :error_raised => 'invalid_request',
@@ -10,11 +10,10 @@ module StripeMock
10
10
  Stripe::Product.create create_product_params(params)
11
11
  end
12
12
 
13
- def create_product_params(params={})
13
+ def create_product_params(params = {})
14
14
  {
15
15
  :id => 'stripe_mock_default_product_id',
16
16
  :name => 'Default Product',
17
- :type => 'service'
18
17
  }.merge(params)
19
18
  end
20
19
 
@@ -22,16 +21,15 @@ module StripeMock
22
21
  Stripe::Product.retrieve(product_id)
23
22
  end
24
23
 
25
-
26
24
  def list_plans(limit)
27
25
  Stripe::Plan.list(limit: limit)
28
26
  end
29
27
 
30
- def create_plan(params={})
28
+ def create_plan(params = {})
31
29
  Stripe::Plan.create create_plan_params(params)
32
30
  end
33
31
 
34
- def create_plan_params(params={})
32
+ def create_plan_params(params = {})
35
33
  {
36
34
  :id => 'stripe_mock_default_plan_id',
37
35
  :interval => 'month',
@@ -41,14 +39,28 @@ module StripeMock
41
39
  }.merge(params)
42
40
  end
43
41
 
42
+ def create_price(params = {})
43
+ Stripe::Price.create create_price_params(params)
44
+ end
45
+
46
+ def create_price_params(params = {})
47
+ price_params = {
48
+ currency: StripeMock.default_currency,
49
+ }.merge(params)
50
+ unless price_params.key?(:product) || price_params.key?(:product_data)
51
+ price_params[:product_data] = {
52
+ name: 'Product created for price'
53
+ }
54
+ end
55
+ price_params
56
+ end
44
57
 
45
58
  def list_subscriptions(limit)
46
59
  Stripe::Subscription.list(limit: limit)
47
60
  end
48
61
 
49
-
50
- def generate_card_token(card_params={})
51
- card_data = { :number => "4242424242424242", :exp_month => 9, :exp_year => (Time.now.year + 5), :cvc => "999", :tokenization_method => nil }
62
+ def generate_card_token(card_params = {})
63
+ card_data = {:number => "4242424242424242", :exp_month => 9, :exp_year => (Time.now.year + 5), :cvc => "999", :tokenization_method => nil}
52
64
  card = StripeMock::Util.card_merge(card_data, card_params)
53
65
  card[:fingerprint] = StripeMock::Util.fingerprint(card[:number]) if StripeMock.state == 'local'
54
66
 
@@ -56,7 +68,7 @@ module StripeMock
56
68
  stripe_token.id
57
69
  end
58
70
 
59
- def generate_bank_token(bank_account_params={})
71
+ def generate_bank_token(bank_account_params = {})
60
72
  currency = bank_account_params[:currency] || StripeMock.default_currency
61
73
  bank_account = {
62
74
  :country => "US",
@@ -72,7 +84,6 @@ module StripeMock
72
84
  stripe_token.id
73
85
  end
74
86
 
75
-
76
87
  def create_coupon_params(params = {})
77
88
  currency = params[:currency] || StripeMock.default_currency
78
89
  {
@@ -97,6 +108,47 @@ module StripeMock
97
108
  }.merge(params)
98
109
  end
99
110
 
111
+ def create_checkout_session(params = {})
112
+ Stripe::Checkout::Session.create create_checkout_session_params(params)
113
+ end
114
+
115
+ def create_checkout_session_params(params = {})
116
+ {
117
+ payment_method_types: ['card'],
118
+ line_items: params[:mode] == "setup" ? nil : [{
119
+ name: 'T-shirt',
120
+ quantity: 1,
121
+ amount: 500,
122
+ currency: 'usd',
123
+ }],
124
+ cancel_url: "https://example.com/cancel",
125
+ success_url: "https://example.com/success",
126
+ }.merge(params)
127
+ end
128
+
129
+ def complete_checkout_session(session, payment_method)
130
+ session = session.is_a?(Stripe::Checkout::Session) ? session : Stripe::Checkout::Session.retrieve(session)
131
+ payment_method = payment_method.is_a?(Stripe::PaymentMethod) ? payment_method : Stripe::PaymentMethod.retrieve(payment_method)
132
+ case session.mode
133
+ when "payment"
134
+ Stripe::PaymentIntent.retrieve(session.payment_intent).confirm(payment_method: payment_method.id)
135
+ when "setup"
136
+ Stripe::SetupIntent.update(session.setup_intent, {payment_method: payment_method.id})
137
+ when "subscription"
138
+ line_items = Stripe::Checkout::Session.list_line_items(session.id)
139
+ Stripe::Subscription.create({
140
+ customer: session.customer,
141
+ items: line_items.map do |line_item|
142
+ {
143
+ price: line_item.price.id,
144
+ quantity: line_item.quantity
145
+ }
146
+ end,
147
+ default_payment_method: payment_method.id
148
+ })
149
+ end
150
+ end
151
+
100
152
  def create_coupon(params = {})
101
153
  Stripe::Coupon.create create_coupon_params(params)
102
154
  end
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "3.0.1"
3
+ VERSION = "3.1.0"
4
4
  end
@@ -10,7 +10,7 @@
10
10
  "email": "test@stripe.com",
11
11
  "statement_descriptor": "TEST",
12
12
  "details_submitted": true,
13
- "charge_enabled": false,
13
+ "charges_enabled": false,
14
14
  "payouts_enabled": false,
15
15
  "currencies_supported": [
16
16
  "USD"
@@ -1,25 +1,37 @@
1
1
  {
2
- "created": 1326853478,
3
- "livemode": false,
4
- "id": "evt_00000000000000",
5
- "type": "balance.available",
2
+ "id": "evt_000000000000000000000000",
6
3
  "object": "event",
4
+ "api_version": "2020-08-27",
5
+ "created": 1648319937,
7
6
  "data": {
8
7
  "object": {
9
- "pending": [
10
- {
11
- "amount": 2217,
12
- "currency": "usd"
13
- }
14
- ],
8
+ "object": "balance",
15
9
  "available": [
16
10
  {
17
- "amount": 0,
18
- "currency": "usd"
11
+ "amount": 7648,
12
+ "currency": "usd",
13
+ "source_types": {
14
+ "card": 7648
15
+ }
19
16
  }
20
17
  ],
21
18
  "livemode": false,
22
- "object": "balance"
19
+ "pending": [
20
+ {
21
+ "amount": 37734,
22
+ "currency": "usd",
23
+ "source_types": {
24
+ "card": 37734
25
+ }
26
+ }
27
+ ]
23
28
  }
24
- }
25
- }
29
+ },
30
+ "livemode": false,
31
+ "pending_webhooks": 2,
32
+ "request": {
33
+ "id": null,
34
+ "idempotency_key": null
35
+ },
36
+ "type": "balance.available"
37
+ }