stripe-ruby-mock 3.1.0.rc3 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rspec_tests.yml +38 -0
- data/.rspec +2 -1
- data/CHANGELOG.md +28 -0
- data/README.md +5 -3
- data/lib/stripe_mock/api/webhooks.rb +65 -26
- data/lib/stripe_mock/data.rb +80 -11
- data/lib/stripe_mock/instance.rb +6 -2
- data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
- data/lib/stripe_mock/request_handlers/charges.rb +5 -0
- data/lib/stripe_mock/request_handlers/checkout_session.rb +158 -1
- data/lib/stripe_mock/request_handlers/events.rb +30 -3
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +1 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +28 -9
- data/lib/stripe_mock/request_handlers/invoices.rb +6 -1
- data/lib/stripe_mock/request_handlers/payment_intents.rb +13 -2
- data/lib/stripe_mock/request_handlers/payment_methods.rb +5 -1
- data/lib/stripe_mock/request_handlers/prices.rb +18 -0
- data/lib/stripe_mock/request_handlers/promotion_codes.rb +43 -0
- data/lib/stripe_mock/request_handlers/refunds.rb +13 -2
- data/lib/stripe_mock/request_handlers/setup_intents.rb +16 -9
- data/lib/stripe_mock/request_handlers/subscriptions.rb +93 -4
- data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +5 -4
- data/lib/stripe_mock/test_strategies/base.rb +51 -24
- data/lib/stripe_mock/version.rb +1 -1
- data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/balance.available.json +26 -20
- data/lib/stripe_mock/webhook_fixtures/charge.captured.json +143 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +63 -16
- data/lib/stripe_mock/webhook_fixtures/charge.failed.json +49 -120
- data/lib/stripe_mock/webhook_fixtures/charge.refund.updated.json +35 -0
- data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +145 -50
- data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +114 -43
- data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.json +79 -0
- data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.payment_mode.json +53 -0
- data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.setup_mode.json +45 -0
- data/lib/stripe_mock/webhook_fixtures/customer.created.json +37 -46
- data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +36 -32
- data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +31 -22
- data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -25
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +135 -47
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +134 -45
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +135 -56
- data/lib/stripe_mock/webhook_fixtures/customer.updated.json +38 -47
- data/lib/stripe_mock/webhook_fixtures/invoice.created.json +176 -49
- data/lib/stripe_mock/webhook_fixtures/invoice.finalized.json +171 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.paid.json +171 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_action_required.json +171 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +149 -83
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +149 -90
- data/lib/stripe_mock/webhook_fixtures/invoice.upcoming.json +70 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +178 -50
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +87 -13
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +88 -14
- data/lib/stripe_mock/webhook_fixtures/mandate.updated.json +34 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.amount_capturable_updated.json +170 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.canceled.json +73 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.created.json +86 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +118 -79
- data/lib/stripe_mock/webhook_fixtures/payment_intent.processing.json +162 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.requires_action.json +191 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +85 -53
- data/lib/stripe_mock/webhook_fixtures/payment_link.created.json +47 -0
- data/lib/stripe_mock/webhook_fixtures/payment_link.updated.json +50 -0
- data/lib/stripe_mock/webhook_fixtures/payment_method.attached.json +63 -0
- data/lib/stripe_mock/webhook_fixtures/payment_method.detached.json +62 -0
- data/lib/stripe_mock/webhook_fixtures/payout.created.json +40 -0
- data/lib/stripe_mock/webhook_fixtures/payout.paid.json +40 -0
- data/lib/stripe_mock/webhook_fixtures/payout.updated.json +46 -0
- data/lib/stripe_mock/webhook_fixtures/plan.created.json +30 -13
- data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +30 -13
- data/lib/stripe_mock/webhook_fixtures/plan.updated.json +34 -14
- data/lib/stripe_mock/webhook_fixtures/price.created.json +42 -0
- data/lib/stripe_mock/webhook_fixtures/price.deleted.json +42 -0
- data/lib/stripe_mock/webhook_fixtures/price.updated.json +48 -0
- data/lib/stripe_mock/webhook_fixtures/product.created.json +19 -13
- data/lib/stripe_mock/webhook_fixtures/product.deleted.json +20 -14
- data/lib/stripe_mock/webhook_fixtures/product.updated.json +24 -15
- data/lib/stripe_mock/webhook_fixtures/quote.accepted.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/quote.canceled.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/quote.created.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/quote.finalized.json +92 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.canceled.json +46 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.created.json +51 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.setup_failed.json +100 -0
- data/lib/stripe_mock/webhook_fixtures/setup_intent.succeeded.json +46 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.canceled.json +119 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.created.json +114 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.released.json +111 -0
- data/lib/stripe_mock/webhook_fixtures/subscription_schedule.updated.json +125 -0
- data/lib/stripe_mock/webhook_fixtures/tax_rate.created.json +32 -0
- data/lib/stripe_mock/webhook_fixtures/tax_rate.updated.json +37 -0
- data/lib/stripe_mock.rb +3 -1
- data/spec/instance_spec.rb +3 -1
- data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
- data/spec/readme_spec.rb +1 -1
- data/spec/shared_stripe_examples/account_examples.rb +9 -1
- data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +21 -0
- data/spec/shared_stripe_examples/payment_intent_examples.rb +74 -0
- data/spec/shared_stripe_examples/payment_method_examples.rb +32 -27
- data/spec/shared_stripe_examples/price_examples.rb +42 -2
- data/spec/shared_stripe_examples/promotion_code_examples.rb +68 -0
- data/spec/shared_stripe_examples/refund_examples.rb +13 -0
- data/spec/shared_stripe_examples/setup_intent_examples.rb +17 -0
- data/spec/shared_stripe_examples/subscription_examples.rb +213 -2
- data/spec/shared_stripe_examples/transfer_examples.rb +10 -1
- data/spec/shared_stripe_examples/webhook_event_examples.rb +51 -5
- data/spec/support/stripe_examples.rb +3 -1
- data/stripe-ruby-mock.gemspec +1 -1
- metadata +54 -11
- data/.travis.yml +0 -25
- data/lib/stripe_mock/request_handlers/checkout.rb +0 -15
- data/spec/shared_stripe_examples/checkout_examples.rb +0 -47
|
@@ -4,7 +4,7 @@ module StripeMock
|
|
|
4
4
|
|
|
5
5
|
def Events.included(klass)
|
|
6
6
|
klass.add_handler 'get /v1/events/(.*)', :retrieve_event
|
|
7
|
-
klass.add_handler 'get /v1/events', :list_events
|
|
7
|
+
klass.add_handler 'get /v1/events', :list_events
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def retrieve_event(route, method_url, params, headers)
|
|
@@ -13,9 +13,36 @@ module StripeMock
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def list_events(route, method_url, params, headers)
|
|
16
|
-
|
|
16
|
+
values = filter_by_created(events.values, params: params)
|
|
17
|
+
Data.mock_list_object(values, params)
|
|
17
18
|
end
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def filter_by_created(event_list, params:)
|
|
23
|
+
if params[:created].nil?
|
|
24
|
+
return event_list
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if params[:created].is_a?(Hash)
|
|
28
|
+
if params[:created][:gt]
|
|
29
|
+
event_list = event_list.select { |event| event[:created] > params[:created][:gt].to_i }
|
|
30
|
+
end
|
|
31
|
+
if params[:created][:gte]
|
|
32
|
+
event_list = event_list.select { |event| event[:created] >= params[:created][:gte].to_i }
|
|
33
|
+
end
|
|
34
|
+
if params[:created][:lt]
|
|
35
|
+
event_list = event_list.select { |event| event[:created] < params[:created][:lt].to_i }
|
|
36
|
+
end
|
|
37
|
+
if params[:created][:lte]
|
|
38
|
+
event_list = event_list.select { |event| event[:created] <= params[:created][:lte].to_i }
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
event_list = event_list.select { |event| event[:created] == params[:created].to_i }
|
|
42
|
+
end
|
|
43
|
+
event_list
|
|
44
|
+
end
|
|
45
|
+
|
|
19
46
|
end
|
|
20
47
|
end
|
|
21
48
|
end
|
|
@@ -7,6 +7,7 @@ module StripeMock
|
|
|
7
7
|
attrs[:coupon] = coupon
|
|
8
8
|
attrs[:start] = Time.now.to_i
|
|
9
9
|
attrs[:end] = (DateTime.now >> coupon[:duration_in_months].to_i).to_time.to_i if coupon[:duration] == 'repeating'
|
|
10
|
+
attrs[:id] = new_id("di")
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
object[:discount] = Stripe::Discount.construct_from(discount_attrs)
|
|
@@ -13,11 +13,15 @@ module StripeMock
|
|
|
13
13
|
subscription[:items][:data] = plans.map do |plan|
|
|
14
14
|
matching_item = items && items.detect { |item| [item[:price], item[:plan]].include? plan[:id] }
|
|
15
15
|
if matching_item
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
matching_item[:quantity] ||= 1
|
|
17
|
+
matching_item[:id] ||= new_id('si')
|
|
18
|
+
params = matching_item.merge(plan: plan)
|
|
19
|
+
params[:price] = plan if plan[:object] == "price"
|
|
20
|
+
Data.mock_subscription_item(params)
|
|
19
21
|
else
|
|
20
|
-
|
|
22
|
+
params = { plan: plan, id: new_id('si') }
|
|
23
|
+
params[:price] = plan if plan[:object] == "price"
|
|
24
|
+
Data.mock_subscription_item(params)
|
|
21
25
|
end
|
|
22
26
|
end
|
|
23
27
|
subscription
|
|
@@ -46,10 +50,10 @@ module StripeMock
|
|
|
46
50
|
|
|
47
51
|
if (((plan && plan[:trial_period_days]) || 0) == 0 && options[:trial_end].nil?) || options[:trial_end] == "now"
|
|
48
52
|
end_time = options[:billing_cycle_anchor] || get_ending_time(start_time, plan)
|
|
49
|
-
params.merge!({status: 'active', current_period_end: end_time, trial_start: nil, trial_end: nil, billing_cycle_anchor: options[:billing_cycle_anchor]})
|
|
53
|
+
params.merge!({status: 'active', current_period_end: end_time, trial_start: nil, trial_end: nil, billing_cycle_anchor: options[:billing_cycle_anchor] || created_time})
|
|
50
54
|
else
|
|
51
55
|
end_time = options[:trial_end] || (Time.now.utc.to_i + plan[:trial_period_days]*86400)
|
|
52
|
-
params.merge!({status: 'trialing', current_period_end: end_time, trial_start: start_time, trial_end: end_time, billing_cycle_anchor:
|
|
56
|
+
params.merge!({status: 'trialing', current_period_end: end_time, trial_start: start_time, trial_end: end_time, billing_cycle_anchor: options[:billing_cycle_anchor] || created_time})
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
params
|
|
@@ -86,11 +90,13 @@ module StripeMock
|
|
|
86
90
|
def get_ending_time(start_time, plan, intervals = 1)
|
|
87
91
|
return start_time unless plan
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
interval = plan[:interval] || plan.dig(:recurring, :interval)
|
|
94
|
+
interval_count = plan[:interval_count] || plan.dig(:recurring, :interval_count) || 1
|
|
95
|
+
case interval
|
|
90
96
|
when "week"
|
|
91
|
-
start_time + (604800 * (
|
|
97
|
+
start_time + (604800 * (interval_count) * intervals)
|
|
92
98
|
when "month"
|
|
93
|
-
(Time.at(start_time).to_datetime >> ((
|
|
99
|
+
(Time.at(start_time).to_datetime >> ((interval_count) * intervals)).to_time.to_i
|
|
94
100
|
when "year"
|
|
95
101
|
(Time.at(start_time).to_datetime >> (12 * intervals)).to_time.to_i # max period is 1 year
|
|
96
102
|
else
|
|
@@ -119,6 +125,19 @@ module StripeMock
|
|
|
119
125
|
end
|
|
120
126
|
total
|
|
121
127
|
end
|
|
128
|
+
|
|
129
|
+
def filter_by_timestamp(subscriptions, field:, value:)
|
|
130
|
+
if value.is_a?(Hash)
|
|
131
|
+
operator_mapping = { gt: :>, gte: :>=, lt: :<, lte: :<= }
|
|
132
|
+
subscriptions.filter do |sub|
|
|
133
|
+
sub[field].public_send(operator_mapping[value.keys[0]], value.values[0])
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
subscriptions.filter do |sub|
|
|
137
|
+
sub[field] == value
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
122
141
|
end
|
|
123
142
|
end
|
|
124
143
|
end
|
|
@@ -53,7 +53,12 @@ module StripeMock
|
|
|
53
53
|
route =~ method_url
|
|
54
54
|
assert_existence :invoice, $1, invoices[$1]
|
|
55
55
|
charge = invoice_charge(invoices[$1])
|
|
56
|
-
invoices[$1].merge!(
|
|
56
|
+
invoices[$1].merge!(
|
|
57
|
+
:paid => true,
|
|
58
|
+
:status => "paid",
|
|
59
|
+
:attempted => true,
|
|
60
|
+
:charge => charge[:id],
|
|
61
|
+
)
|
|
57
62
|
end
|
|
58
63
|
|
|
59
64
|
def upcoming_invoice(route, method_url, params, headers = {})
|
|
@@ -81,6 +81,10 @@ module StripeMock
|
|
|
81
81
|
route =~ method_url
|
|
82
82
|
payment_intent = assert_existence :payment_intent, $1, payment_intents[$1]
|
|
83
83
|
|
|
84
|
+
if params[:payment_method]
|
|
85
|
+
payment_intent[:payment_method] = params[:payment_method]
|
|
86
|
+
end
|
|
87
|
+
|
|
84
88
|
succeeded_payment_intent(payment_intent)
|
|
85
89
|
end
|
|
86
90
|
|
|
@@ -169,12 +173,19 @@ module StripeMock
|
|
|
169
173
|
payment_intent[:status] = 'succeeded'
|
|
170
174
|
btxn = new_balance_transaction('txn', { source: payment_intent[:id] })
|
|
171
175
|
|
|
172
|
-
|
|
176
|
+
charge_id = new_id('ch')
|
|
177
|
+
|
|
178
|
+
charges[charge_id] = Data.mock_charge(
|
|
179
|
+
id: charge_id,
|
|
173
180
|
balance_transaction: btxn,
|
|
181
|
+
payment_intent: payment_intent[:id],
|
|
174
182
|
amount: payment_intent[:amount],
|
|
175
|
-
currency: payment_intent[:currency]
|
|
183
|
+
currency: payment_intent[:currency],
|
|
184
|
+
payment_method: payment_intent[:payment_method]
|
|
176
185
|
)
|
|
177
186
|
|
|
187
|
+
payment_intent[:charges][:data] << charges[charge_id].clone
|
|
188
|
+
|
|
178
189
|
payment_intent
|
|
179
190
|
end
|
|
180
191
|
end
|
|
@@ -78,7 +78,11 @@ module StripeMock
|
|
|
78
78
|
|
|
79
79
|
# post /v1/payment_methods/:id
|
|
80
80
|
def update_payment_method(route, method_url, params, headers)
|
|
81
|
-
allowed_params = [:billing_details, :card, :
|
|
81
|
+
allowed_params = [:billing_details, :card, :metadata]
|
|
82
|
+
disallowed_params = params.keys - allowed_params
|
|
83
|
+
unless disallowed_params.empty?
|
|
84
|
+
raise Stripe::InvalidRequestError.new("Received unknown parameter: #{disallowed_params.first}", disallowed_params.first)
|
|
85
|
+
end
|
|
82
86
|
|
|
83
87
|
id = method_url.match(route)[1]
|
|
84
88
|
|
|
@@ -11,6 +11,12 @@ module StripeMock
|
|
|
11
11
|
|
|
12
12
|
def new_price(route, method_url, params, headers)
|
|
13
13
|
params[:id] ||= new_id('price')
|
|
14
|
+
|
|
15
|
+
if params[:product_data]
|
|
16
|
+
params[:product] = create_product(nil, nil, params[:product_data], nil)[:id] unless params[:product]
|
|
17
|
+
params.delete(:product_data)
|
|
18
|
+
end
|
|
19
|
+
|
|
14
20
|
validate_create_price_params(params)
|
|
15
21
|
prices[ params[:id] ] = Data.mock_price(params)
|
|
16
22
|
end
|
|
@@ -37,6 +43,18 @@ module StripeMock
|
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
|
|
46
|
+
if params.key?(:currency)
|
|
47
|
+
price_data.select! do |price|
|
|
48
|
+
params[:currency] == price[:currency]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if params.key?(:product)
|
|
53
|
+
price_data.select! do |price|
|
|
54
|
+
params[:product] == price[:product]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
40
58
|
Data.mock_list_object(price_data.first(limit), params.merge!(limit: limit))
|
|
41
59
|
end
|
|
42
60
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module StripeMock
|
|
2
|
+
module RequestHandlers
|
|
3
|
+
module PromotionCodes
|
|
4
|
+
|
|
5
|
+
def PromotionCodes.included(klass)
|
|
6
|
+
klass.add_handler 'post /v1/promotion_codes', :new_promotion_code
|
|
7
|
+
klass.add_handler 'post /v1/promotion_codes/([^/]*)', :update_promotion_code
|
|
8
|
+
klass.add_handler 'get /v1/promotion_codes/([^/]*)', :get_promotion_code
|
|
9
|
+
klass.add_handler 'get /v1/promotion_codes', :list_promotion_code
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def new_promotion_code(route, method_url, params, headers)
|
|
13
|
+
params[:id] ||= new_id("promo")
|
|
14
|
+
raise Stripe::InvalidRequestError.new("Missing required param: coupon", "promotion_code", http_status: 400) unless params[:coupon]
|
|
15
|
+
|
|
16
|
+
if params[:restrictions]
|
|
17
|
+
if params[:restrictions][:minimum_amount] && !params[:restrictions][:minimum_amount_currency]
|
|
18
|
+
raise Stripe::InvalidRequestError.new(
|
|
19
|
+
"You must pass minimum_amount_currency when passing minimum_amount", "minimum_amount_currency", http_status: 400
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
promotion_codes[ params[:id] ] = Data.mock_promotion_code(params)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def update_promotion_code(route, method_url, params, headers)
|
|
28
|
+
route =~ method_url
|
|
29
|
+
assert_existence :promotion_code, $1, promotion_codes[$1]
|
|
30
|
+
promotion_codes[$1].merge!(params)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def get_promotion_code(route, method_url, params, headers)
|
|
34
|
+
route =~ method_url
|
|
35
|
+
assert_existence :promotion_code, $1, promotion_codes[$1]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def list_promotion_code(route, method_url, params, headers)
|
|
39
|
+
Data.mock_list_object(promotion_codes.values, params)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -18,7 +18,18 @@ module StripeMock
|
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
if params[:payment_intent]
|
|
22
|
+
payment_intent = assert_existence(
|
|
23
|
+
:payment_intent,
|
|
24
|
+
params[:payment_intent],
|
|
25
|
+
payment_intents[params[:payment_intent]]
|
|
26
|
+
)
|
|
27
|
+
charge = {}
|
|
28
|
+
else
|
|
29
|
+
charge = assert_existence :charge, params[:charge], charges[params[:charge]]
|
|
30
|
+
payment_intent = {}
|
|
31
|
+
end
|
|
32
|
+
params[:amount] ||= payment_intent[:amount]
|
|
22
33
|
params[:amount] ||= charge[:amount]
|
|
23
34
|
id = new_id('re')
|
|
24
35
|
bal_trans_params = {
|
|
@@ -32,7 +43,7 @@ module StripeMock
|
|
|
32
43
|
:id => id,
|
|
33
44
|
:charge => charge[:id],
|
|
34
45
|
)
|
|
35
|
-
add_refund_to_charge(refund, charge)
|
|
46
|
+
add_refund_to_charge(refund, charge) unless charge.empty?
|
|
36
47
|
refunds[id] = refund
|
|
37
48
|
|
|
38
49
|
if params[:expand] == ['balance_transaction']
|
|
@@ -15,20 +15,22 @@ module StripeMock
|
|
|
15
15
|
]
|
|
16
16
|
|
|
17
17
|
def SetupIntents.included(klass)
|
|
18
|
-
klass.add_handler 'post /v1/setup_intents',
|
|
19
|
-
klass.add_handler 'get /v1/setup_intents',
|
|
20
|
-
klass.add_handler 'get /v1/setup_intents/(.*)',
|
|
21
|
-
klass.add_handler 'post /v1/setup_intents/(.*)/confirm',
|
|
22
|
-
klass.add_handler 'post /v1/setup_intents/(.*)/cancel',
|
|
23
|
-
klass.add_handler 'post /v1/setup_intents/(.*)',
|
|
18
|
+
klass.add_handler 'post /v1/setup_intents', :new_setup_intent
|
|
19
|
+
klass.add_handler 'get /v1/setup_intents', :get_setup_intents
|
|
20
|
+
klass.add_handler 'get /v1/setup_intents/(.*)', :get_setup_intent
|
|
21
|
+
klass.add_handler 'post /v1/setup_intents/(.*)/confirm', :confirm_setup_intent
|
|
22
|
+
klass.add_handler 'post /v1/setup_intents/(.*)/cancel', :cancel_setup_intent
|
|
23
|
+
klass.add_handler 'post /v1/setup_intents/(.*)', :update_setup_intent
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def new_setup_intent(route, method_url, params, headers)
|
|
27
27
|
id = new_id('si')
|
|
28
|
+
status = params[:payment_method] ? 'requires_action' : 'requires_payment_method'
|
|
28
29
|
|
|
29
30
|
setup_intents[id] = Data.mock_setup_intent(
|
|
30
31
|
params.merge(
|
|
31
|
-
id: id
|
|
32
|
+
id: id,
|
|
33
|
+
status: status
|
|
32
34
|
)
|
|
33
35
|
)
|
|
34
36
|
|
|
@@ -40,7 +42,7 @@ module StripeMock
|
|
|
40
42
|
id = $1
|
|
41
43
|
|
|
42
44
|
setup_intent = assert_existence :setup_intent, id, setup_intents[id]
|
|
43
|
-
setup_intents[id] = Util.rmerge(setup_intent, params.select{ |k,v| ALLOWED_PARAMS.include?(k)})
|
|
45
|
+
setup_intents[id] = Util.rmerge(setup_intent, params.select { |k, v| ALLOWED_PARAMS.include?(k) })
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def get_setup_intents(route, method_url, params, headers)
|
|
@@ -50,7 +52,7 @@ module StripeMock
|
|
|
50
52
|
clone = setup_intents.clone
|
|
51
53
|
|
|
52
54
|
if params[:customer]
|
|
53
|
-
clone.delete_if { |k,v| v[:customer] != params[:customer] }
|
|
55
|
+
clone.delete_if { |k, v| v[:customer] != params[:customer] }
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
Data.mock_list_object(clone.values, params)
|
|
@@ -62,6 +64,11 @@ module StripeMock
|
|
|
62
64
|
setup_intent = assert_existence :setup_intent, setup_intent_id, setup_intents[setup_intent_id]
|
|
63
65
|
|
|
64
66
|
setup_intent = setup_intent.clone
|
|
67
|
+
|
|
68
|
+
if params[:expand]&.include?("payment_method")
|
|
69
|
+
setup_intent[:payment_method] = assert_existence :payment_method, setup_intent[:payment_method], payment_methods[setup_intent[:payment_method]]
|
|
70
|
+
end
|
|
71
|
+
|
|
65
72
|
setup_intent
|
|
66
73
|
end
|
|
67
74
|
|
|
@@ -69,6 +69,16 @@ module StripeMock
|
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
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
|
+
|
|
72
82
|
subscriptions[subscription[:id]] = subscription
|
|
73
83
|
add_subscription_to_customer(customer, subscription)
|
|
74
84
|
|
|
@@ -97,7 +107,7 @@ module StripeMock
|
|
|
97
107
|
customer[:default_source] = new_card[:id]
|
|
98
108
|
end
|
|
99
109
|
|
|
100
|
-
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 default_payment_method collection_method off_session trial_from_plan expand)
|
|
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)
|
|
101
111
|
unknown_params = params.keys - allowed_params.map(&:to_sym)
|
|
102
112
|
if unknown_params.length > 0
|
|
103
113
|
raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
|
|
@@ -113,6 +123,10 @@ module StripeMock
|
|
|
113
123
|
# Note: needs updating for subscriptions with multiple plans
|
|
114
124
|
verify_card_present(customer, subscription_plans.first, subscription, params)
|
|
115
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
|
+
|
|
116
130
|
if params[:coupon]
|
|
117
131
|
coupon_id = params[:coupon]
|
|
118
132
|
|
|
@@ -128,15 +142,50 @@ module StripeMock
|
|
|
128
142
|
end
|
|
129
143
|
end
|
|
130
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
|
+
|
|
131
155
|
if params[:trial_period_days]
|
|
132
156
|
subscription[:status] = 'trialing'
|
|
133
157
|
end
|
|
134
158
|
|
|
159
|
+
if params[:payment_behavior] == 'default_incomplete'
|
|
160
|
+
subscription[:status] = 'incomplete'
|
|
161
|
+
end
|
|
162
|
+
|
|
135
163
|
if params[:cancel_at_period_end]
|
|
136
164
|
subscription[:cancel_at_period_end] = true
|
|
137
165
|
subscription[:canceled_at] = Time.now.utc.to_i
|
|
138
166
|
end
|
|
139
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
|
+
|
|
140
189
|
subscriptions[subscription[:id]] = subscription
|
|
141
190
|
add_subscription_to_customer(customer, subscription)
|
|
142
191
|
|
|
@@ -153,15 +202,34 @@ module StripeMock
|
|
|
153
202
|
# stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
|
154
203
|
route =~ method_url
|
|
155
204
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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)
|
|
162
226
|
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
|
163
227
|
route =~ method_url
|
|
164
228
|
|
|
229
|
+
if params[:billing_cycle_anchor] == 'now'
|
|
230
|
+
params[:billing_cycle_anchor] = Time.now.utc.to_i
|
|
231
|
+
end
|
|
232
|
+
|
|
165
233
|
subscription_id = $2 ? $2 : $1
|
|
166
234
|
subscription = assert_existence :subscription, subscription_id, subscriptions[subscription_id]
|
|
167
235
|
verify_active_status(subscription)
|
|
@@ -198,6 +266,26 @@ module StripeMock
|
|
|
198
266
|
end
|
|
199
267
|
end
|
|
200
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
|
+
|
|
201
289
|
if params[:trial_period_days]
|
|
202
290
|
subscription[:status] = 'trialing'
|
|
203
291
|
end
|
|
@@ -285,6 +373,7 @@ module StripeMock
|
|
|
285
373
|
return if customer[:invoice_settings][:default_payment_method]
|
|
286
374
|
return if customer[:trial_end]
|
|
287
375
|
return if params[:trial_end]
|
|
376
|
+
return if params[:payment_behavior] == 'default_incomplete'
|
|
288
377
|
return if subscription[:default_payment_method]
|
|
289
378
|
|
|
290
379
|
plan_trial_period_days = plan[:trial_period_days] || 0
|
|
@@ -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
|
-
|
|
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)
|
|
@@ -108,13 +108,14 @@ module StripeMock
|
|
|
108
108
|
|
|
109
109
|
def validate_create_price_params(params)
|
|
110
110
|
price_id = params[:id].to_s
|
|
111
|
-
product_id = params[:product]
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
raise Stripe::InvalidRequestError
|
|
112
|
+
require_param(:currency) unless params[:currency]
|
|
113
|
+
unless params[:product] || params[:product_data]
|
|
114
|
+
raise Stripe::InvalidRequestError("Requires product or product_data")
|
|
116
115
|
end
|
|
117
116
|
|
|
117
|
+
product_id = params[:product] || create_product(nil, nil, params[:product_data], nil).id
|
|
118
|
+
|
|
118
119
|
if prices[price_id]
|
|
119
120
|
message = already_exists_message(Stripe::Price)
|
|
120
121
|
raise Stripe::InvalidRequestError.new(message, :id)
|