stripe-ruby-mock 2.5.6 → 3.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -1
- data/.travis.yml +6 -9
- data/CHANGELOG.md +35 -0
- data/Gemfile +1 -0
- data/README.md +17 -11
- data/lib/stripe_mock.rb +11 -0
- data/lib/stripe_mock/api/client.rb +1 -1
- data/lib/stripe_mock/api/errors.rb +34 -28
- data/lib/stripe_mock/api/instance.rb +1 -1
- data/lib/stripe_mock/api/webhooks.rb +7 -0
- data/lib/stripe_mock/client.rb +2 -1
- data/lib/stripe_mock/data.rb +323 -13
- data/lib/stripe_mock/data/list.rb +42 -9
- data/lib/stripe_mock/instance.rb +52 -5
- data/lib/stripe_mock/request_handlers/account_links.rb +15 -0
- data/lib/stripe_mock/request_handlers/balance_transactions.rb +2 -2
- data/lib/stripe_mock/request_handlers/charges.rb +13 -12
- data/lib/stripe_mock/request_handlers/checkout.rb +15 -0
- data/lib/stripe_mock/request_handlers/checkout_session.rb +16 -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/express_login_links.rb +15 -0
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +14 -10
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +22 -7
- data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +1 -1
- data/lib/stripe_mock/request_handlers/invoices.rb +11 -5
- data/lib/stripe_mock/request_handlers/payment_intents.rb +182 -0
- data/lib/stripe_mock/request_handlers/payment_methods.rb +120 -0
- data/lib/stripe_mock/request_handlers/plans.rb +1 -1
- data/lib/stripe_mock/request_handlers/prices.rb +44 -0
- data/lib/stripe_mock/request_handlers/products.rb +44 -0
- data/lib/stripe_mock/request_handlers/refunds.rb +6 -3
- data/lib/stripe_mock/request_handlers/setup_intents.rb +93 -0
- data/lib/stripe_mock/request_handlers/sources.rb +12 -6
- data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
- data/lib/stripe_mock/request_handlers/subscriptions.rb +82 -41
- data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
- data/lib/stripe_mock/request_handlers/tokens.rb +8 -6
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +130 -9
- data/lib/stripe_mock/test_strategies/base.rb +68 -8
- data/lib/stripe_mock/test_strategies/live.rb +23 -12
- data/lib/stripe_mock/test_strategies/mock.rb +6 -2
- data/lib/stripe_mock/version.rb +1 -1
- data/lib/stripe_mock/webhook_fixtures/balance.available.json +6 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_reinstated.json +88 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_withdrawn.json +88 -0
- data/lib/stripe_mock/webhook_fixtures/charge.failed.json +166 -38
- data/lib/stripe_mock/webhook_fixtures/customer.created.json +1 -0
- data/lib/stripe_mock/webhook_fixtures/customer.updated.json +1 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.created.json +2 -1
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +2 -1
- data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +186 -0
- data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +164 -0
- data/lib/stripe_mock/webhook_fixtures/product.created.json +34 -0
- data/lib/stripe_mock/webhook_fixtures/product.deleted.json +34 -0
- data/lib/stripe_mock/webhook_fixtures/product.updated.json +38 -0
- data/spec/instance_spec.rb +10 -12
- data/spec/list_spec.rb +38 -0
- data/spec/server_spec.rb +6 -3
- data/spec/shared_stripe_examples/account_examples.rb +1 -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/balance_transaction_examples.rb +3 -3
- data/spec/shared_stripe_examples/bank_examples.rb +3 -3
- data/spec/shared_stripe_examples/card_examples.rb +4 -4
- data/spec/shared_stripe_examples/card_token_examples.rb +17 -21
- data/spec/shared_stripe_examples/charge_examples.rb +32 -36
- data/spec/shared_stripe_examples/checkout_examples.rb +38 -0
- data/spec/shared_stripe_examples/coupon_examples.rb +1 -1
- data/spec/shared_stripe_examples/customer_examples.rb +103 -53
- data/spec/shared_stripe_examples/dispute_examples.rb +2 -2
- data/spec/shared_stripe_examples/error_mock_examples.rb +8 -7
- data/spec/shared_stripe_examples/express_login_link_examples.rb +12 -0
- data/spec/shared_stripe_examples/external_account_examples.rb +3 -3
- data/spec/shared_stripe_examples/invoice_examples.rb +43 -41
- data/spec/shared_stripe_examples/invoice_item_examples.rb +1 -1
- data/spec/shared_stripe_examples/payment_intent_examples.rb +147 -0
- data/spec/shared_stripe_examples/payment_method_examples.rb +449 -0
- data/spec/shared_stripe_examples/payout_examples.rb +2 -2
- data/spec/shared_stripe_examples/plan_examples.rb +135 -77
- data/spec/shared_stripe_examples/price_examples.rb +183 -0
- data/spec/shared_stripe_examples/product_examples.rb +155 -0
- data/spec/shared_stripe_examples/refund_examples.rb +41 -31
- data/spec/shared_stripe_examples/setup_intent_examples.rb +68 -0
- data/spec/shared_stripe_examples/subscription_examples.rb +546 -295
- data/spec/shared_stripe_examples/subscription_items_examples.rb +76 -0
- data/spec/shared_stripe_examples/tax_rate_examples.rb +42 -0
- data/spec/shared_stripe_examples/transfer_examples.rb +9 -9
- data/spec/shared_stripe_examples/webhook_event_examples.rb +11 -11
- data/spec/spec_helper.rb +7 -4
- data/spec/stripe_mock_spec.rb +4 -4
- data/spec/support/shared_contexts/stripe_validator_spec.rb +8 -0
- data/spec/support/stripe_examples.rb +12 -2
- data/stripe-ruby-mock.gemspec +8 -3
- metadata +81 -32
@@ -34,7 +34,7 @@ module StripeMock
|
|
34
34
|
|
35
35
|
def list_plans(route, method_url, params, headers)
|
36
36
|
limit = params[:limit] ? params[:limit] : 10
|
37
|
-
Data.mock_list_object(plans.values.first(limit), limit: limit)
|
37
|
+
Data.mock_list_object(plans.values.first(limit), params.merge!(limit: limit))
|
38
38
|
end
|
39
39
|
|
40
40
|
end
|
@@ -0,0 +1,44 @@
|
|
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
|
+
validate_create_price_params(params)
|
15
|
+
prices[ params[:id] ] = Data.mock_price(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_price(route, method_url, params, headers)
|
19
|
+
route =~ method_url
|
20
|
+
assert_existence :price, $1, prices[$1]
|
21
|
+
prices[$1].merge!(params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_price(route, method_url, params, headers)
|
25
|
+
route =~ method_url
|
26
|
+
assert_existence :price, $1, prices[$1]
|
27
|
+
end
|
28
|
+
|
29
|
+
def list_prices(route, method_url, params, headers)
|
30
|
+
limit = params[:limit] ? params[:limit] : 10
|
31
|
+
price_data = prices.values
|
32
|
+
validate_list_prices_params(params)
|
33
|
+
|
34
|
+
if params.key?(:lookup_keys)
|
35
|
+
price_data.select! do |price|
|
36
|
+
params[:lookup_keys].include?(price[:lookup_key])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Data.mock_list_object(price_data.first(limit), params.merge!(limit: limit))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module Products
|
4
|
+
def self.included(base)
|
5
|
+
base.add_handler 'post /v1/products', :create_product
|
6
|
+
base.add_handler 'get /v1/products/(.*)', :retrieve_product
|
7
|
+
base.add_handler 'post /v1/products/(.*)', :update_product
|
8
|
+
base.add_handler 'get /v1/products', :list_products
|
9
|
+
base.add_handler 'delete /v1/products/(.*)', :destroy_product
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_product(_route, _method_url, params, _headers)
|
13
|
+
params[:id] ||= new_id('prod')
|
14
|
+
validate_create_product_params(params)
|
15
|
+
products[params[:id]] = Data.mock_product(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def retrieve_product(route, method_url, _params, _headers)
|
19
|
+
id = method_url.match(route).captures.first
|
20
|
+
assert_existence :product, id, products[id]
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_product(route, method_url, params, _headers)
|
24
|
+
id = method_url.match(route).captures.first
|
25
|
+
product = assert_existence :product, id, products[id]
|
26
|
+
|
27
|
+
product.merge!(params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_products(_route, _method_url, params, _headers)
|
31
|
+
limit = params[:limit] || 10
|
32
|
+
Data.mock_list_object(products.values.take(limit), params)
|
33
|
+
end
|
34
|
+
|
35
|
+
def destroy_product(route, method_url, _params, _headers)
|
36
|
+
id = method_url.match(route).captures.first
|
37
|
+
assert_existence :product, id, products[id]
|
38
|
+
|
39
|
+
products.delete(id)
|
40
|
+
{ id: id, object: 'product', deleted: true }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -10,9 +10,12 @@ module StripeMock
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def new_refund(route, method_url, params, headers)
|
13
|
-
if
|
14
|
-
|
15
|
-
|
13
|
+
if headers && headers[:idempotency_key]
|
14
|
+
params[:idempotency_key] = headers[:idempotency_key]
|
15
|
+
if refunds.any?
|
16
|
+
original_refund = refunds.values.find { |c| c[:idempotency_key] == headers[:idempotency_key]}
|
17
|
+
return refunds[original_refund[:id]] if original_refund
|
18
|
+
end
|
16
19
|
end
|
17
20
|
|
18
21
|
charge = assert_existence :charge, params[:charge], charges[params[:charge]]
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module SetupIntents
|
4
|
+
ALLOWED_PARAMS = [
|
5
|
+
:confirm,
|
6
|
+
:customer,
|
7
|
+
:description,
|
8
|
+
:metadata,
|
9
|
+
:on_behalf_of,
|
10
|
+
:payment_method,
|
11
|
+
:payment_method_options,
|
12
|
+
:payment_method_types,
|
13
|
+
:return_url,
|
14
|
+
:usage
|
15
|
+
]
|
16
|
+
|
17
|
+
def SetupIntents.included(klass)
|
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
|
+
end
|
25
|
+
|
26
|
+
def new_setup_intent(route, method_url, params, headers)
|
27
|
+
id = new_id('si')
|
28
|
+
|
29
|
+
setup_intents[id] = Data.mock_setup_intent(
|
30
|
+
params.merge(
|
31
|
+
id: id
|
32
|
+
)
|
33
|
+
)
|
34
|
+
|
35
|
+
setup_intents[id].clone
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_setup_intent(route, method_url, params, headers)
|
39
|
+
route =~ method_url
|
40
|
+
id = $1
|
41
|
+
|
42
|
+
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)})
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_setup_intents(route, method_url, params, headers)
|
47
|
+
params[:offset] ||= 0
|
48
|
+
params[:limit] ||= 10
|
49
|
+
|
50
|
+
clone = setup_intents.clone
|
51
|
+
|
52
|
+
if params[:customer]
|
53
|
+
clone.delete_if { |k,v| v[:customer] != params[:customer] }
|
54
|
+
end
|
55
|
+
|
56
|
+
Data.mock_list_object(clone.values, params)
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_setup_intent(route, method_url, params, headers)
|
60
|
+
route =~ method_url
|
61
|
+
setup_intent_id = $1 || params[:setup_intent]
|
62
|
+
setup_intent = assert_existence :setup_intent, setup_intent_id, setup_intents[setup_intent_id]
|
63
|
+
|
64
|
+
setup_intent = setup_intent.clone
|
65
|
+
setup_intent
|
66
|
+
end
|
67
|
+
|
68
|
+
def capture_setup_intent(route, method_url, params, headers)
|
69
|
+
route =~ method_url
|
70
|
+
setup_intent = assert_existence :setup_intent, $1, setup_intents[$1]
|
71
|
+
|
72
|
+
setup_intent[:status] = 'succeeded'
|
73
|
+
setup_intent
|
74
|
+
end
|
75
|
+
|
76
|
+
def confirm_setup_intent(route, method_url, params, headers)
|
77
|
+
route =~ method_url
|
78
|
+
setup_intent = assert_existence :setup_intent, $1, setup_intents[$1]
|
79
|
+
|
80
|
+
setup_intent[:status] = 'succeeded'
|
81
|
+
setup_intent
|
82
|
+
end
|
83
|
+
|
84
|
+
def cancel_setup_intent(route, method_url, params, headers)
|
85
|
+
route =~ method_url
|
86
|
+
setup_intent = assert_existence :setup_intent, $1, setup_intents[$1]
|
87
|
+
|
88
|
+
setup_intent[:status] = 'canceled'
|
89
|
+
setup_intent
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -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
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module SubscriptionItems
|
4
|
+
|
5
|
+
def SubscriptionItems.included(klass)
|
6
|
+
klass.add_handler 'get /v1/subscription_items', :retrieve_subscription_items
|
7
|
+
klass.add_handler 'post /v1/subscription_items/([^/]*)', :update_subscription_item
|
8
|
+
klass.add_handler 'post /v1/subscription_items', :create_subscription_items
|
9
|
+
end
|
10
|
+
|
11
|
+
def retrieve_subscription_items(route, method_url, params, headers)
|
12
|
+
route =~ method_url
|
13
|
+
|
14
|
+
require_param(:subscription) unless params[:subscription]
|
15
|
+
|
16
|
+
Data.mock_list_object(subscriptions_items, params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_subscription_items(route, method_url, params, headers)
|
20
|
+
params[:id] ||= new_id('si')
|
21
|
+
|
22
|
+
require_param(:subscription) unless params[:subscription]
|
23
|
+
require_param(:plan) unless params[:plan]
|
24
|
+
|
25
|
+
subscriptions_items[params[:id]] = Data.mock_subscription_item(params.merge(plan: plans[params[:plan]]))
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_subscription_item(route, method_url, params, headers)
|
29
|
+
route =~ method_url
|
30
|
+
|
31
|
+
subscription_item = assert_existence :subscription_item, $1, subscriptions_items[$1]
|
32
|
+
subscription_item.merge!(params.merge(plan: plans[params[:plan]]))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -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))
|
@@ -60,7 +63,7 @@ module StripeMock
|
|
60
63
|
coupon = coupons[coupon_id]
|
61
64
|
|
62
65
|
if coupon
|
63
|
-
subscription
|
66
|
+
add_coupon_to_object(subscription, coupon)
|
64
67
|
else
|
65
68
|
raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
|
66
69
|
end
|
@@ -73,21 +76,20 @@ module StripeMock
|
|
73
76
|
end
|
74
77
|
|
75
78
|
def create_subscription(route, method_url, params, headers)
|
79
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
80
|
+
if headers && headers[:idempotency_key]
|
81
|
+
if subscriptions.any?
|
82
|
+
original_subscription = subscriptions.values.find { |c| c[:idempotency_key] == headers[:idempotency_key]}
|
83
|
+
return subscriptions[original_subscription[:id]] if original_subscription
|
84
|
+
end
|
85
|
+
end
|
76
86
|
route =~ method_url
|
77
87
|
|
78
88
|
subscription_plans = get_subscription_plans_from_params(params)
|
79
89
|
|
80
90
|
customer = params[:customer]
|
81
91
|
customer_id = customer.is_a?(Stripe::Customer) ? customer[:id] : customer.to_s
|
82
|
-
customer = assert_existence :customer, customer_id, customers[customer_id]
|
83
|
-
|
84
|
-
if subscription_plans && customer
|
85
|
-
subscription_plans.each do |plan|
|
86
|
-
unless customer[:currency].to_s == plan[:currency].to_s
|
87
|
-
raise Stripe::InvalidRequestError.new("Customer's currency of #{customer[:currency]} does not match plan's currency of #{plan[:currency]}", 'currency', http_status: 400)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
92
|
+
customer = assert_existence :customer, customer_id, customers[stripe_account][customer_id]
|
91
93
|
|
92
94
|
if params[:source]
|
93
95
|
new_card = get_card_by_token(params.delete(:source))
|
@@ -95,7 +97,7 @@ module StripeMock
|
|
95
97
|
customer[:default_source] = new_card[:id]
|
96
98
|
end
|
97
99
|
|
98
|
-
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)
|
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)
|
99
101
|
unknown_params = params.keys - allowed_params.map(&:to_sym)
|
100
102
|
if unknown_params.length > 0
|
101
103
|
raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
|
@@ -103,6 +105,9 @@ module StripeMock
|
|
103
105
|
|
104
106
|
subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
|
105
107
|
subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
|
108
|
+
if headers[:idempotency_key]
|
109
|
+
subscription[:idempotency_key] = headers[:idempotency_key]
|
110
|
+
end
|
106
111
|
|
107
112
|
# Ensure customer has card to charge if plan has no trial and is not free
|
108
113
|
# Note: needs updating for subscriptions with multiple plans
|
@@ -117,12 +122,21 @@ module StripeMock
|
|
117
122
|
coupon = coupons[coupon_id]
|
118
123
|
|
119
124
|
if coupon
|
120
|
-
subscription
|
125
|
+
add_coupon_to_object(subscription, coupon)
|
121
126
|
else
|
122
127
|
raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
|
123
128
|
end
|
124
129
|
end
|
125
130
|
|
131
|
+
if params[:trial_period_days]
|
132
|
+
subscription[:status] = 'trialing'
|
133
|
+
end
|
134
|
+
|
135
|
+
if params[:cancel_at_period_end]
|
136
|
+
subscription[:cancel_at_period_end] = true
|
137
|
+
subscription[:canceled_at] = Time.now.utc.to_i
|
138
|
+
end
|
139
|
+
|
126
140
|
subscriptions[subscription[:id]] = subscription
|
127
141
|
add_subscription_to_customer(customer, subscription)
|
128
142
|
|
@@ -136,14 +150,16 @@ module StripeMock
|
|
136
150
|
end
|
137
151
|
|
138
152
|
def retrieve_subscriptions(route, method_url, params, headers)
|
153
|
+
# stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
139
154
|
route =~ method_url
|
140
155
|
|
141
156
|
Data.mock_list_object(subscriptions.values, params)
|
142
|
-
#customer = assert_existence :customer, $1, customers[$1]
|
157
|
+
#customer = assert_existence :customer, $1, customers[stripe_account][$1]
|
143
158
|
#customer[:subscriptions]
|
144
159
|
end
|
145
160
|
|
146
161
|
def update_subscription(route, method_url, params, headers)
|
162
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
147
163
|
route =~ method_url
|
148
164
|
|
149
165
|
subscription_id = $2 ? $2 : $1
|
@@ -151,7 +167,7 @@ module StripeMock
|
|
151
167
|
verify_active_status(subscription)
|
152
168
|
|
153
169
|
customer_id = subscription[:customer]
|
154
|
-
customer = assert_existence :customer, customer_id, customers[customer_id]
|
170
|
+
customer = assert_existence :customer, customer_id, customers[stripe_account][customer_id]
|
155
171
|
|
156
172
|
if params[:source]
|
157
173
|
new_card = get_card_by_token(params.delete(:source))
|
@@ -174,23 +190,35 @@ module StripeMock
|
|
174
190
|
|
175
191
|
coupon = coupons[coupon_id]
|
176
192
|
if coupon
|
177
|
-
subscription
|
193
|
+
add_coupon_to_object(subscription, coupon)
|
178
194
|
elsif coupon_id == ""
|
179
|
-
subscription[:discount] =
|
195
|
+
subscription[:discount] = nil
|
180
196
|
else
|
181
197
|
raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
|
182
198
|
end
|
183
199
|
end
|
184
|
-
verify_card_present(customer, subscription_plans.first, subscription)
|
185
200
|
|
186
|
-
if
|
201
|
+
if params[:trial_period_days]
|
202
|
+
subscription[:status] = 'trialing'
|
203
|
+
end
|
204
|
+
|
205
|
+
if params[:cancel_at_period_end]
|
206
|
+
subscription[:cancel_at_period_end] = true
|
207
|
+
subscription[:canceled_at] = Time.now.utc.to_i
|
208
|
+
elsif params.has_key?(:cancel_at_period_end)
|
187
209
|
subscription[:cancel_at_period_end] = false
|
188
210
|
subscription[:canceled_at] = nil
|
189
211
|
end
|
190
212
|
|
191
213
|
params[:current_period_start] = subscription[:current_period_start]
|
214
|
+
params[:trial_end] = params[:trial_end] || subscription[:trial_end]
|
215
|
+
|
216
|
+
plan_amount_was = subscription.dig(:plan, :amount)
|
217
|
+
|
192
218
|
subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)
|
193
219
|
|
220
|
+
verify_card_present(customer, subscription_plans.first, subscription, params) if plan_amount_was == 0 && subscription.dig(:plan, :amount) && subscription.dig(:plan, :amount) > 0
|
221
|
+
|
194
222
|
# delete the old subscription, replace with the new subscription
|
195
223
|
customer[:subscriptions][:data].reject! { |sub| sub[:id] == subscription[:id] }
|
196
224
|
customer[:subscriptions][:data] << subscription
|
@@ -199,13 +227,14 @@ module StripeMock
|
|
199
227
|
end
|
200
228
|
|
201
229
|
def cancel_subscription(route, method_url, params, headers)
|
230
|
+
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
|
202
231
|
route =~ method_url
|
203
232
|
|
204
233
|
subscription_id = $2 ? $2 : $1
|
205
234
|
subscription = assert_existence :subscription, subscription_id, subscriptions[subscription_id]
|
206
235
|
|
207
236
|
customer_id = subscription[:customer]
|
208
|
-
customer = assert_existence :customer, customer_id, customers[customer_id]
|
237
|
+
customer = assert_existence :customer, customer_id, customers[stripe_account][customer_id]
|
209
238
|
|
210
239
|
cancel_params = { canceled_at: Time.now.utc.to_i }
|
211
240
|
cancelled_at_period_end = (params[:at_period_end] == true)
|
@@ -234,36 +263,48 @@ module StripeMock
|
|
234
263
|
elsif params[:items]
|
235
264
|
items = params[:items]
|
236
265
|
items = items.values if items.respond_to?(:values)
|
237
|
-
items.map { |item| item[:plan]
|
266
|
+
items.map { |item| item[:plan] ? item[:plan] : item[:price] }
|
238
267
|
else
|
239
268
|
[]
|
240
269
|
end
|
270
|
+
plan_ids.compact!
|
241
271
|
plan_ids.each do |plan_id|
|
242
272
|
assert_existence :plan, plan_id, plans[plan_id]
|
273
|
+
rescue Stripe::InvalidRequestError
|
274
|
+
assert_existence :price, plan_id, prices[plan_id]
|
243
275
|
end
|
244
|
-
plan_ids.map { |plan_id| plans[plan_id] }
|
276
|
+
plan_ids.map { |plan_id| plans[plan_id] || prices[plan_id]}
|
245
277
|
end
|
246
278
|
|
279
|
+
# Ensure customer has card to charge unless one of the following criterias is met:
|
280
|
+
# 1) is in trial
|
281
|
+
# 2) is free
|
282
|
+
# 3) has billing set to send invoice
|
247
283
|
def verify_card_present(customer, plan, subscription, params={})
|
248
|
-
if customer[:default_source]
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
284
|
+
return if customer[:default_source]
|
285
|
+
return if customer[:invoice_settings][:default_payment_method]
|
286
|
+
return if customer[:trial_end]
|
287
|
+
return if params[:trial_end]
|
288
|
+
return if subscription[:default_payment_method]
|
289
|
+
|
290
|
+
plan_trial_period_days = plan[:trial_period_days] || 0
|
291
|
+
plan_has_trial = plan_trial_period_days != 0 || plan[:amount] == 0 || plan[:trial_end]
|
292
|
+
return if plan && plan_has_trial
|
293
|
+
|
294
|
+
return if subscription && subscription[:trial_end] && subscription[:trial_end] != 'now'
|
295
|
+
|
296
|
+
if subscription[:items]
|
297
|
+
trial = subscription[:items][:data].none? do |item|
|
298
|
+
plan = item[:plan]
|
299
|
+
(plan[:trial_period_days].nil? || plan[:trial_period_days] == 0) &&
|
300
|
+
(plan[:trial_end].nil? || plan[:trial_end] == 'now')
|
263
301
|
end
|
264
|
-
|
265
|
-
raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, http_status: 400)
|
302
|
+
return if trial
|
266
303
|
end
|
304
|
+
|
305
|
+
return if params[:billing] == 'send_invoice'
|
306
|
+
|
307
|
+
raise Stripe::InvalidRequestError.new('This customer has no attached payment source', nil, http_status: 400)
|
267
308
|
end
|
268
309
|
|
269
310
|
def verify_active_status(subscription)
|