stripe-ruby-mock 2.5.0 → 2.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|