stripe-ruby-mock 2.5.0 → 2.5.1
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/README.md +1 -1
- data/lib/stripe_mock.rb +3 -0
- data/lib/stripe_mock/api/account_balance.rb +14 -0
- data/lib/stripe_mock/api/webhooks.rb +2 -0
- data/lib/stripe_mock/client.rb +4 -0
- data/lib/stripe_mock/data.rb +78 -3
- data/lib/stripe_mock/instance.rb +21 -4
- data/lib/stripe_mock/request_handlers/accounts.rb +18 -2
- data/lib/stripe_mock/request_handlers/balance.rb +17 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +27 -6
- data/lib/stripe_mock/request_handlers/invoices.rb +20 -4
- data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
- data/lib/stripe_mock/request_handlers/subscriptions.rb +65 -9
- data/lib/stripe_mock/request_handlers/tokens.rb +6 -0
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +7 -1
- data/lib/stripe_mock/server.rb +4 -0
- data/lib/stripe_mock/util.rb +8 -2
- 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/charge.updated.json +58 -0
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +40 -10
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +39 -10
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +39 -10
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +39 -10
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +92 -85
- data/spec/shared_stripe_examples/account_examples.rb +8 -0
- data/spec/shared_stripe_examples/balance_examples.rb +11 -0
- data/spec/shared_stripe_examples/bank_examples.rb +27 -0
- data/spec/shared_stripe_examples/dispute_examples.rb +10 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +68 -6
- data/spec/shared_stripe_examples/payout_examples.rb +68 -0
- data/spec/shared_stripe_examples/plan_examples.rb +7 -1
- data/spec/shared_stripe_examples/subscription_examples.rb +132 -2
- data/spec/shared_stripe_examples/webhook_event_examples.rb +69 -0
- data/spec/support/stripe_examples.rb +2 -0
- data/spec/util_spec.rb +35 -1
- metadata +10 -2
@@ -0,0 +1,32 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module Payouts
|
4
|
+
|
5
|
+
def Payouts.included(klass)
|
6
|
+
klass.add_handler 'post /v1/payouts', :new_payout
|
7
|
+
klass.add_handler 'get /v1/payouts', :list_payouts
|
8
|
+
klass.add_handler 'get /v1/payouts/(.*)', :get_payout
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_payout(route, method_url, params, headers)
|
12
|
+
id = new_id('po')
|
13
|
+
|
14
|
+
unless params[:amount].is_a?(Integer) || (params[:amount].is_a?(String) && /^\d+$/.match(params[:amount]))
|
15
|
+
raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', http_status: 400)
|
16
|
+
end
|
17
|
+
|
18
|
+
payouts[id] = Data.mock_payout(params.merge :id => id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def list_payouts(route, method_url, params, headers)
|
22
|
+
Data.mock_list_object(payouts.clone.values, params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_payout(route, method_url, params, headers)
|
26
|
+
route =~ method_url
|
27
|
+
assert_existence :payout, $1, payouts[$1]
|
28
|
+
payouts[$1] ||= Data.mock_payout(:id => $1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -32,10 +32,22 @@ module StripeMock
|
|
32
32
|
customer[:subscriptions]
|
33
33
|
end
|
34
34
|
|
35
|
+
def plan_id_from_params(params)
|
36
|
+
if params[:plan]
|
37
|
+
params[:plan].to_s
|
38
|
+
elsif params[:items]
|
39
|
+
item = params[:items].values.find { |item| item[:plan] }
|
40
|
+
if item
|
41
|
+
item[:plan].to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
35
46
|
def create_customer_subscription(route, method_url, params, headers)
|
36
47
|
route =~ method_url
|
37
48
|
|
38
|
-
plan_id = params
|
49
|
+
plan_id = plan_id_from_params(params)
|
50
|
+
|
39
51
|
plan = assert_existence :plan, plan_id, plans[plan_id]
|
40
52
|
|
41
53
|
customer = assert_existence :customer, $1, customers[$1]
|
@@ -70,26 +82,35 @@ module StripeMock
|
|
70
82
|
subscriptions[subscription[:id]] = subscription
|
71
83
|
add_subscription_to_customer(customer, subscription)
|
72
84
|
|
85
|
+
clear_top_level_plan_if_multiple_items(subscription)
|
86
|
+
|
73
87
|
subscriptions[subscription[:id]]
|
74
88
|
end
|
75
89
|
|
76
90
|
def create_subscription(route, method_url, params, headers)
|
77
91
|
route =~ method_url
|
78
92
|
|
79
|
-
plan_id = params
|
80
|
-
|
93
|
+
plan_id = plan_id_from_params(params)
|
94
|
+
|
95
|
+
plan = plan_id ? assert_existence(:plan, plan_id, plans[plan_id]) : nil
|
81
96
|
|
82
97
|
customer = params[:customer]
|
83
98
|
customer_id = customer.is_a?(Stripe::Customer) ? customer[:id] : customer.to_s
|
84
99
|
customer = assert_existence :customer, customer_id, customers[customer_id]
|
85
100
|
|
101
|
+
if plan && customer
|
102
|
+
unless customer[:currency] == plan[:currency]
|
103
|
+
raise Stripe::InvalidRequestError.new('lol', 'currency', http_status: 400)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
86
107
|
if params[:source]
|
87
108
|
new_card = get_card_by_token(params.delete(:source))
|
88
109
|
add_card_to_object(:customer, new_card, customer)
|
89
110
|
customer[:default_source] = new_card[:id]
|
90
111
|
end
|
91
112
|
|
92
|
-
allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start)
|
113
|
+
allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start created)
|
93
114
|
unknown_params = params.keys - allowed_params.map(&:to_sym)
|
94
115
|
if unknown_params.length > 0
|
95
116
|
raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
|
@@ -97,6 +118,7 @@ module StripeMock
|
|
97
118
|
|
98
119
|
subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
|
99
120
|
subscription.merge!(custom_subscription_params(plan, customer, params))
|
121
|
+
subscription[:items][:data] = mock_subscription_items(params[:items].values) if params[:items]
|
100
122
|
|
101
123
|
# Ensure customer has card to charge if plan has no trial and is not free
|
102
124
|
verify_card_present(customer, plan, subscription, params)
|
@@ -119,6 +141,8 @@ module StripeMock
|
|
119
141
|
subscriptions[subscription[:id]] = subscription
|
120
142
|
add_subscription_to_customer(customer, subscription)
|
121
143
|
|
144
|
+
clear_top_level_plan_if_multiple_items(subscription)
|
145
|
+
|
122
146
|
subscriptions[subscription[:id]]
|
123
147
|
end
|
124
148
|
|
@@ -153,10 +177,20 @@ module StripeMock
|
|
153
177
|
end
|
154
178
|
|
155
179
|
# expand the plan for addition to the customer object
|
156
|
-
|
157
|
-
|
180
|
+
plan_id = plan_id_from_params(params)
|
181
|
+
|
182
|
+
unless plan_id
|
183
|
+
plan_id = if subscription[:plan]
|
184
|
+
subscription[:plan][:id]
|
185
|
+
elsif subscription[:items]
|
186
|
+
row = subscription[:items][:data].find { |item| item[:plan] }
|
187
|
+
if row
|
188
|
+
row[:plan][:id]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
158
192
|
|
159
|
-
plan = plans[
|
193
|
+
plan = plans[plan_id]
|
160
194
|
|
161
195
|
if params[:coupon]
|
162
196
|
coupon_id = params[:coupon]
|
@@ -174,7 +208,7 @@ module StripeMock
|
|
174
208
|
end
|
175
209
|
end
|
176
210
|
|
177
|
-
assert_existence :plan,
|
211
|
+
assert_existence :plan, plan_id, plan
|
178
212
|
params[:plan] = plan if params[:plan]
|
179
213
|
verify_card_present(customer, plan, subscription)
|
180
214
|
|
@@ -190,6 +224,8 @@ module StripeMock
|
|
190
224
|
customer[:subscriptions][:data].reject! { |sub| sub[:id] == subscription[:id] }
|
191
225
|
customer[:subscriptions][:data] << subscription
|
192
226
|
|
227
|
+
clear_top_level_plan_if_multiple_items(subscription)
|
228
|
+
|
193
229
|
subscription
|
194
230
|
end
|
195
231
|
|
@@ -223,8 +259,28 @@ module StripeMock
|
|
223
259
|
|
224
260
|
private
|
225
261
|
|
262
|
+
def clear_top_level_plan_if_multiple_items(subscription)
|
263
|
+
subscription[:plan] = nil if subscription[:items][:data].size > 1
|
264
|
+
end
|
265
|
+
|
226
266
|
def verify_card_present(customer, plan, subscription, params={})
|
227
|
-
if customer[:default_source].nil? && customer[:trial_end].nil? &&
|
267
|
+
if customer[:default_source].nil? && customer[:trial_end].nil? &&
|
268
|
+
(plan.nil? ||
|
269
|
+
((plan[:trial_period_days] || 0) == 0 &&
|
270
|
+
plan[:amount] != 0 &&
|
271
|
+
plan[:trial_end].nil?)) &&
|
272
|
+
params[:trial_end].nil? &&
|
273
|
+
(subscription.nil? || subscription[:trial_end].nil? || subscription[:trial_end] == 'now')
|
274
|
+
|
275
|
+
if subscription[:items]
|
276
|
+
trial = subscription[:items][:data].none? do |item|
|
277
|
+
plan = item[:plan]
|
278
|
+
(plan[:trial_period_days].nil? || plan[:trial_period_days] == 0) &&
|
279
|
+
(plan[:trial_end].nil? || plan[:trial_end] == 'now')
|
280
|
+
end
|
281
|
+
return if trial
|
282
|
+
end
|
283
|
+
|
228
284
|
raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, http_status: 400)
|
229
285
|
end
|
230
286
|
end
|
@@ -31,6 +31,12 @@ module StripeMock
|
|
31
31
|
params[:card][:fingerprint] = StripeMock::Util.fingerprint(params[:card][:number])
|
32
32
|
params[:card][:last4] = params[:card][:number][-4,4]
|
33
33
|
customer_card = params[:card]
|
34
|
+
elsif params[:bank_account].is_a?(String)
|
35
|
+
customer = assert_existence :customer, cus_id, customers[cus_id]
|
36
|
+
|
37
|
+
# params[:bank_account] is an id; grab it from the db
|
38
|
+
bank_account = verify_bank_account(customer, params[:bank_account])
|
39
|
+
assert_existence :bank_account, params[:bank_account], bank_account
|
34
40
|
elsif params[:bank_account]
|
35
41
|
# params[:card] is a hash of cc info; "Sanitize" the card number
|
36
42
|
bank_account = params[:bank_account]
|
@@ -6,7 +6,13 @@ module StripeMock
|
|
6
6
|
params[:id] = params[:id].to_s
|
7
7
|
|
8
8
|
@base_strategy.create_plan_params.keys.each do |name|
|
9
|
-
|
9
|
+
message =
|
10
|
+
if name == :amount
|
11
|
+
"Plans require an `#{name}` parameter to be set."
|
12
|
+
else
|
13
|
+
"Missing required param: #{name}."
|
14
|
+
end
|
15
|
+
raise Stripe::InvalidRequestError.new(message, name) if params[name].nil?
|
10
16
|
end
|
11
17
|
|
12
18
|
if plans[ params[:id] ]
|
data/lib/stripe_mock/server.rb
CHANGED
data/lib/stripe_mock/util.rb
CHANGED
@@ -9,8 +9,14 @@ module StripeMock
|
|
9
9
|
if oldval.is_a?(Array) && newval.is_a?(Array)
|
10
10
|
oldval.fill(nil, oldval.length...newval.length)
|
11
11
|
oldval.zip(newval).map {|elems|
|
12
|
-
elems[1].nil?
|
13
|
-
|
12
|
+
if elems[1].nil?
|
13
|
+
elems[0]
|
14
|
+
elsif elems[1].is_a?(Hash) && elems[1].is_a?(Hash)
|
15
|
+
rmerge(elems[0], elems[1])
|
16
|
+
else
|
17
|
+
[elems[0], elems[1]].compact
|
18
|
+
end
|
19
|
+
}.flatten
|
14
20
|
elsif oldval.is_a?(Hash) && newval.is_a?(Hash)
|
15
21
|
rmerge(oldval, newval)
|
16
22
|
else
|
data/lib/stripe_mock/version.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"created": 1326853478,
|
3
|
+
"livemode": false,
|
4
|
+
"id": "evt_00000000000000",
|
5
|
+
"type": "charge.updated",
|
6
|
+
"object": "event",
|
7
|
+
"data": {
|
8
|
+
"object": {
|
9
|
+
"id": "ch_00000000000000",
|
10
|
+
"object": "charge",
|
11
|
+
"created": 1380933505,
|
12
|
+
"livemode": false,
|
13
|
+
"paid": true,
|
14
|
+
"amount": 1000,
|
15
|
+
"currency": "usd",
|
16
|
+
"refunded": false,
|
17
|
+
"source": {
|
18
|
+
"id": "cc_00000000000000",
|
19
|
+
"object": "card",
|
20
|
+
"last4": "4242",
|
21
|
+
"type": "Visa",
|
22
|
+
"brand": "Visa",
|
23
|
+
"exp_month": 12,
|
24
|
+
"exp_year": 2013,
|
25
|
+
"fingerprint": "wXWJT135mEK107G8",
|
26
|
+
"customer": "cus_00000000000000",
|
27
|
+
"country": "US",
|
28
|
+
"name": "Actual Nothing",
|
29
|
+
"address_line1": null,
|
30
|
+
"address_line2": null,
|
31
|
+
"address_city": null,
|
32
|
+
"address_state": null,
|
33
|
+
"address_zip": null,
|
34
|
+
"address_country": null,
|
35
|
+
"cvc_check": null,
|
36
|
+
"address_line1_check": null,
|
37
|
+
"address_zip_check": null
|
38
|
+
},
|
39
|
+
"captured": true,
|
40
|
+
"refunds": {
|
41
|
+
|
42
|
+
},
|
43
|
+
"balance_transaction": "txn_00000000000000",
|
44
|
+
"failure_message": null,
|
45
|
+
"failure_code": null,
|
46
|
+
"amount_refunded": 0,
|
47
|
+
"customer": "cus_00000000000000",
|
48
|
+
"invoice": "in_00000000000000",
|
49
|
+
"description": "Sample description" ,
|
50
|
+
"dispute": null,
|
51
|
+
"metadata": {
|
52
|
+
}
|
53
|
+
},
|
54
|
+
"previous_attributes": {
|
55
|
+
"description": null
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
@@ -7,16 +7,46 @@
|
|
7
7
|
"data": {
|
8
8
|
"object": {
|
9
9
|
"id": "su_00000000000000",
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
"items": {
|
11
|
+
"object": "list",
|
12
|
+
"data": [
|
13
|
+
{
|
14
|
+
"id": "si_00000000000000",
|
15
|
+
"object": "subscription_item",
|
16
|
+
"created": 1497881783,
|
17
|
+
"plan": {
|
18
|
+
"interval": "month",
|
19
|
+
"name": "Member's Club",
|
20
|
+
"amount": 100,
|
21
|
+
"currency": "usd",
|
22
|
+
"id": "fkx0AFo_00000000000000",
|
23
|
+
"object": "plan",
|
24
|
+
"livemode": false,
|
25
|
+
"interval_count": 1,
|
26
|
+
"trial_period_days": null,
|
27
|
+
"metadata": {}
|
28
|
+
},
|
29
|
+
"quantity": 1
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"id": "si_00000000000001",
|
33
|
+
"object": "subscription_item",
|
34
|
+
"created": 1497881788,
|
35
|
+
"plan": {
|
36
|
+
"interval": "month",
|
37
|
+
"name": "Vistor's Club",
|
38
|
+
"amount": 200,
|
39
|
+
"currency": "eur",
|
40
|
+
"id": "fkx0AFo_00000000000001",
|
41
|
+
"object": "plan",
|
42
|
+
"livemode": false,
|
43
|
+
"interval_count": 1,
|
44
|
+
"trial_period_days": null,
|
45
|
+
"metadata": {}
|
46
|
+
},
|
47
|
+
"quantity": 5
|
48
|
+
}
|
49
|
+
]
|
20
50
|
},
|
21
51
|
"object": "subscription",
|
22
52
|
"start": 1381080557,
|
@@ -7,16 +7,45 @@
|
|
7
7
|
"data": {
|
8
8
|
"object": {
|
9
9
|
"id": "su_00000000000000",
|
10
|
-
"
|
11
|
-
"
|
12
|
-
"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
"items": {
|
11
|
+
"object": "list",
|
12
|
+
"data": [{
|
13
|
+
"id": "si_00000000000000",
|
14
|
+
"object": "subscription_item",
|
15
|
+
"created": 1497881783,
|
16
|
+
"plan": {
|
17
|
+
"interval": "month",
|
18
|
+
"name": "Member's Club",
|
19
|
+
"amount": 100,
|
20
|
+
"currency": "usd",
|
21
|
+
"id": "fkx0AFo_00000000000000",
|
22
|
+
"object": "plan",
|
23
|
+
"livemode": false,
|
24
|
+
"interval_count": 1,
|
25
|
+
"trial_period_days": null,
|
26
|
+
"metadata": {}
|
27
|
+
},
|
28
|
+
"quantity": 1
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"id": "si_00000000000001",
|
32
|
+
"object": "subscription_item",
|
33
|
+
"created": 1497881788,
|
34
|
+
"plan": {
|
35
|
+
"interval": "month",
|
36
|
+
"name": "Vistor's Club",
|
37
|
+
"amount": 200,
|
38
|
+
"currency": "eur",
|
39
|
+
"id": "fkx0AFo_00000000000001",
|
40
|
+
"object": "plan",
|
41
|
+
"livemode": false,
|
42
|
+
"interval_count": 1,
|
43
|
+
"trial_period_days": null,
|
44
|
+
"metadata": {}
|
45
|
+
},
|
46
|
+
"quantity": 5
|
47
|
+
}
|
48
|
+
]
|
20
49
|
},
|
21
50
|
"object": "subscription",
|
22
51
|
"start": 1381080564,
|
@@ -7,16 +7,45 @@
|
|
7
7
|
"data": {
|
8
8
|
"object": {
|
9
9
|
"id": "su_00000000000000",
|
10
|
-
"
|
11
|
-
"
|
12
|
-
"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
"items": {
|
11
|
+
"object": "list",
|
12
|
+
"data": [{
|
13
|
+
"id": "si_00000000000000",
|
14
|
+
"object": "subscription_item",
|
15
|
+
"created": 1497881783,
|
16
|
+
"plan": {
|
17
|
+
"interval": "month",
|
18
|
+
"name": "Member's Club",
|
19
|
+
"amount": 100,
|
20
|
+
"currency": "usd",
|
21
|
+
"id": "fkx0AFo_00000000000000",
|
22
|
+
"object": "plan",
|
23
|
+
"livemode": false,
|
24
|
+
"interval_count": 1,
|
25
|
+
"trial_period_days": null,
|
26
|
+
"metadata": {}
|
27
|
+
},
|
28
|
+
"quantity": 1
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"id": "si_00000000000001",
|
32
|
+
"object": "subscription_item",
|
33
|
+
"created": 1497881788,
|
34
|
+
"plan": {
|
35
|
+
"interval": "month",
|
36
|
+
"name": "Vistor's Club",
|
37
|
+
"amount": 200,
|
38
|
+
"currency": "eur",
|
39
|
+
"id": "fkx0AFo_00000000000001",
|
40
|
+
"object": "plan",
|
41
|
+
"livemode": false,
|
42
|
+
"interval_count": 1,
|
43
|
+
"trial_period_days": null,
|
44
|
+
"metadata": {}
|
45
|
+
},
|
46
|
+
"quantity": 5
|
47
|
+
}
|
48
|
+
]
|
20
49
|
},
|
21
50
|
"object": "subscription",
|
22
51
|
"start": 1381080623,
|