stripe-ruby-mock 3.0.0 → 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 +5 -5
- data/.github/workflows/rspec_tests.yml +38 -0
- data/.rspec +2 -1
- data/CHANGELOG.md +69 -0
- data/Gemfile +1 -0
- data/README.md +13 -5
- data/lib/stripe_mock/api/client.rb +1 -1
- data/lib/stripe_mock/api/errors.rb +3 -0
- data/lib/stripe_mock/api/instance.rb +1 -1
- data/lib/stripe_mock/api/webhooks.rb +66 -25
- data/lib/stripe_mock/client.rb +2 -1
- data/lib/stripe_mock/data/list.rb +42 -9
- data/lib/stripe_mock/data.rb +242 -31
- data/lib/stripe_mock/instance.rb +14 -3
- data/lib/stripe_mock/request_handlers/account_links.rb +15 -0
- data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
- data/lib/stripe_mock/request_handlers/charges.rb +11 -4
- data/lib/stripe_mock/request_handlers/checkout_session.rb +179 -0
- data/lib/stripe_mock/request_handlers/customers.rb +35 -18
- data/lib/stripe_mock/request_handlers/ephemeral_key.rb +1 -1
- data/lib/stripe_mock/request_handlers/events.rb +30 -3
- data/lib/stripe_mock/request_handlers/express_login_links.rb +15 -0
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +6 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +36 -12
- data/lib/stripe_mock/request_handlers/invoices.rb +10 -4
- data/lib/stripe_mock/request_handlers/payment_intents.rb +19 -1
- data/lib/stripe_mock/request_handlers/payment_methods.rb +10 -24
- data/lib/stripe_mock/request_handlers/plans.rb +1 -1
- data/lib/stripe_mock/request_handlers/prices.rb +62 -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/sources.rb +12 -6
- data/lib/stripe_mock/request_handlers/subscriptions.rb +120 -21
- data/lib/stripe_mock/request_handlers/tokens.rb +6 -4
- data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +33 -4
- data/lib/stripe_mock/server.rb +2 -2
- data/lib/stripe_mock/test_strategies/base.rb +62 -10
- 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 +27 -15
- 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 +225 -0
- 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 +196 -0
- 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 +7 -0
- data/spec/instance_spec.rb +7 -7
- data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
- data/spec/list_spec.rb +38 -0
- data/spec/readme_spec.rb +1 -1
- data/spec/server_spec.rb +4 -2
- data/spec/shared_stripe_examples/account_examples.rb +9 -1
- data/spec/shared_stripe_examples/account_link_examples.rb +16 -0
- data/spec/shared_stripe_examples/balance_examples.rb +6 -0
- data/spec/shared_stripe_examples/card_token_examples.rb +17 -21
- data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
- data/spec/shared_stripe_examples/customer_examples.rb +49 -23
- data/spec/shared_stripe_examples/express_login_link_examples.rb +12 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +29 -8
- data/spec/shared_stripe_examples/payment_intent_examples.rb +84 -0
- data/spec/shared_stripe_examples/payment_method_examples.rb +336 -67
- data/spec/shared_stripe_examples/price_examples.rb +223 -0
- data/spec/shared_stripe_examples/product_examples.rb +1 -9
- 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 +361 -9
- data/spec/shared_stripe_examples/transfer_examples.rb +10 -1
- data/spec/shared_stripe_examples/webhook_event_examples.rb +51 -5
- data/spec/spec_helper.rb +4 -0
- data/spec/stripe_mock_spec.rb +2 -2
- data/spec/support/stripe_examples.rb +8 -1
- data/stripe-ruby-mock.gemspec +7 -2
- metadata +73 -12
- data/.travis.yml +0 -28
@@ -0,0 +1,62 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module Prices
|
4
|
+
|
5
|
+
def Prices.included(klass)
|
6
|
+
klass.add_handler 'post /v1/prices', :new_price
|
7
|
+
klass.add_handler 'post /v1/prices/(.*)', :update_price
|
8
|
+
klass.add_handler 'get /v1/prices/(.*)', :get_price
|
9
|
+
klass.add_handler 'get /v1/prices', :list_prices
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_price(route, method_url, params, headers)
|
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
|
+
|
20
|
+
validate_create_price_params(params)
|
21
|
+
prices[ params[:id] ] = Data.mock_price(params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_price(route, method_url, params, headers)
|
25
|
+
route =~ method_url
|
26
|
+
assert_existence :price, $1, prices[$1]
|
27
|
+
prices[$1].merge!(params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_price(route, method_url, params, headers)
|
31
|
+
route =~ method_url
|
32
|
+
assert_existence :price, $1, prices[$1]
|
33
|
+
end
|
34
|
+
|
35
|
+
def list_prices(route, method_url, params, headers)
|
36
|
+
limit = params[:limit] ? params[:limit] : 10
|
37
|
+
price_data = prices.values
|
38
|
+
validate_list_prices_params(params)
|
39
|
+
|
40
|
+
if params.key?(:lookup_keys)
|
41
|
+
price_data.select! do |price|
|
42
|
+
params[:lookup_keys].include?(price[:lookup_key])
|
43
|
+
end
|
44
|
+
end
|
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
|
+
|
58
|
+
Data.mock_list_object(price_data.first(limit), params.merge!(limit: limit))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
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
|
|
@@ -12,30 +12,35 @@ module StripeMock
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def create_source(route, method_url, params, headers)
|
15
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
15
16
|
route =~ method_url
|
16
|
-
add_source_to(:customer, $1, params, customers)
|
17
|
+
add_source_to(:customer, $1, params, customers[stripe_account])
|
17
18
|
end
|
18
19
|
|
19
20
|
def retrieve_sources(route, method_url, params, headers)
|
21
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
20
22
|
route =~ method_url
|
21
|
-
retrieve_object_cards(:customer, $1, customers)
|
23
|
+
retrieve_object_cards(:customer, $1, customers[stripe_account])
|
22
24
|
end
|
23
25
|
|
24
26
|
def retrieve_source(route, method_url, params, headers)
|
27
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
25
28
|
route =~ method_url
|
26
|
-
customer = assert_existence :customer, $1, customers[$1]
|
29
|
+
customer = assert_existence :customer, $1, customers[stripe_account][$1]
|
27
30
|
|
28
31
|
assert_existence :card, $2, get_card(customer, $2)
|
29
32
|
end
|
30
33
|
|
31
34
|
def delete_source(route, method_url, params, headers)
|
35
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
32
36
|
route =~ method_url
|
33
|
-
delete_card_from(:customer, $1, $2, customers)
|
37
|
+
delete_card_from(:customer, $1, $2, customers[stripe_account])
|
34
38
|
end
|
35
39
|
|
36
40
|
def update_source(route, method_url, params, headers)
|
41
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
37
42
|
route =~ method_url
|
38
|
-
customer = assert_existence :customer, $1, customers[$1]
|
43
|
+
customer = assert_existence :customer, $1, customers[stripe_account][$1]
|
39
44
|
|
40
45
|
card = assert_existence :card, $2, get_card(customer, $2)
|
41
46
|
card.merge!(params)
|
@@ -43,8 +48,9 @@ module StripeMock
|
|
43
48
|
end
|
44
49
|
|
45
50
|
def verify_source(route, method_url, params, headers)
|
51
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
46
52
|
route =~ method_url
|
47
|
-
customer = assert_existence :customer, $1, customers[$1]
|
53
|
+
customer = assert_existence :customer, $1, customers[stripe_account][$1]
|
48
54
|
|
49
55
|
bank_account = assert_existence :bank_account, $2, verify_bank_account(customer, $2)
|
50
56
|
bank_account
|
@@ -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)
|
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
|
-
|
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)
|
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]
|
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
|
-
|
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
|
data/lib/stripe_mock/server.rb
CHANGED
@@ -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',
|