stripe-ruby-mock 2.3.1 → 2.5.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env +2 -0
- data/.travis.yml +8 -4
- data/README.md +12 -5
- data/lib/stripe_mock/api/account_balance.rb +14 -0
- data/lib/stripe_mock/api/client.rb +4 -4
- data/lib/stripe_mock/api/conversion_rate.rb +14 -0
- data/lib/stripe_mock/api/errors.rb +25 -13
- data/lib/stripe_mock/api/instance.rb +16 -6
- data/lib/stripe_mock/api/webhooks.rb +8 -1
- data/lib/stripe_mock/client.rb +18 -2
- data/lib/stripe_mock/data/list.rb +14 -2
- data/lib/stripe_mock/data.rb +398 -58
- data/lib/stripe_mock/instance.rb +105 -9
- data/lib/stripe_mock/request_handlers/accounts.rb +41 -2
- data/lib/stripe_mock/request_handlers/balance.rb +17 -0
- data/lib/stripe_mock/request_handlers/balance_transactions.rb +18 -2
- data/lib/stripe_mock/request_handlers/charges.rb +44 -33
- data/lib/stripe_mock/request_handlers/country_spec.rb +22 -0
- data/lib/stripe_mock/request_handlers/coupons.rb +5 -4
- data/lib/stripe_mock/request_handlers/customers.rb +29 -11
- data/lib/stripe_mock/request_handlers/ephemeral_key.rb +13 -0
- data/lib/stripe_mock/request_handlers/external_accounts.rb +55 -0
- data/lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb +1 -1
- data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +9 -7
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +10 -6
- data/lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb +49 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +59 -16
- data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +3 -2
- data/lib/stripe_mock/request_handlers/invoices.rb +93 -14
- data/lib/stripe_mock/request_handlers/orders.rb +5 -5
- data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
- data/lib/stripe_mock/request_handlers/plans.rb +1 -0
- data/lib/stripe_mock/request_handlers/products.rb +43 -0
- data/lib/stripe_mock/request_handlers/recipients.rb +12 -0
- data/lib/stripe_mock/request_handlers/refunds.rb +91 -0
- data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
- data/lib/stripe_mock/request_handlers/subscriptions.rb +101 -39
- data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
- data/lib/stripe_mock/request_handlers/tokens.rb +9 -3
- data/lib/stripe_mock/request_handlers/transfers.rb +11 -5
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +15 -1
- data/lib/stripe_mock/server.rb +14 -1
- data/lib/stripe_mock/test_strategies/base.rb +10 -5
- data/lib/stripe_mock/test_strategies/live.rb +5 -0
- data/lib/stripe_mock/test_strategies/mock.rb +8 -0
- data/lib/stripe_mock/util.rb +8 -2
- data/lib/stripe_mock/version.rb +1 -1
- data/lib/stripe_mock/webhook_fixtures/account.external_account.created.json +27 -0
- data/lib/stripe_mock/webhook_fixtures/account.external_account.deleted.json +27 -0
- data/lib/stripe_mock/webhook_fixtures/account.external_account.updated.json +27 -0
- data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
- 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.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 +40 -11
- data/lib/stripe_mock/webhook_fixtures/invoice.created.json +3 -2
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +92 -85
- data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +3 -2
- data/lib/stripe_mock/webhook_fixtures/plan.created.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +1 -1
- data/lib/stripe_mock/webhook_fixtures/plan.updated.json +1 -1
- data/lib/stripe_mock.rb +15 -0
- data/spec/api/instance_spec.rb +30 -0
- data/spec/instance_spec.rb +54 -4
- data/spec/integration_examples/prepare_error_examples.rb +6 -6
- data/spec/list_spec.rb +27 -10
- data/spec/readme_spec.rb +2 -0
- data/spec/server_spec.rb +7 -3
- data/spec/shared_stripe_examples/account_examples.rb +46 -0
- data/spec/shared_stripe_examples/balance_examples.rb +11 -0
- data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
- data/spec/shared_stripe_examples/bank_examples.rb +28 -1
- data/spec/shared_stripe_examples/card_examples.rb +23 -5
- data/spec/shared_stripe_examples/card_token_examples.rb +1 -0
- data/spec/shared_stripe_examples/charge_examples.rb +131 -26
- data/spec/shared_stripe_examples/country_specs_examples.rb +18 -0
- data/spec/shared_stripe_examples/coupon_examples.rb +8 -2
- data/spec/shared_stripe_examples/customer_examples.rb +90 -0
- data/spec/shared_stripe_examples/dispute_examples.rb +19 -8
- data/spec/shared_stripe_examples/ephemeral_key_examples.rb +17 -0
- data/spec/shared_stripe_examples/error_mock_examples.rb +15 -5
- data/spec/shared_stripe_examples/external_account_examples.rb +170 -0
- data/spec/shared_stripe_examples/extra_features_examples.rb +2 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +314 -51
- data/spec/shared_stripe_examples/payout_examples.rb +68 -0
- data/spec/shared_stripe_examples/plan_examples.rb +47 -4
- data/spec/shared_stripe_examples/product_example.rb +65 -0
- data/spec/shared_stripe_examples/recipient_examples.rb +13 -7
- data/spec/shared_stripe_examples/refund_examples.rb +453 -84
- data/spec/shared_stripe_examples/subscription_examples.rb +477 -32
- data/spec/shared_stripe_examples/subscription_items_examples.rb +75 -0
- data/spec/shared_stripe_examples/tax_rate_examples.rb +42 -0
- data/spec/shared_stripe_examples/transfer_examples.rb +72 -23
- data/spec/shared_stripe_examples/webhook_event_examples.rb +74 -5
- data/spec/spec_helper.rb +7 -6
- data/spec/stripe_mock_spec.rb +16 -3
- data/spec/support/stripe_examples.rb +8 -1
- data/spec/util_spec.rb +35 -1
- data/stripe-ruby-mock.gemspec +1 -1
- metadata +44 -8
- data/ChangeLog.rdoc +0 -4
data/lib/stripe_mock/instance.rb
CHANGED
@@ -20,12 +20,15 @@ module StripeMock
|
|
20
20
|
@@handlers.find {|h| method_url =~ h[:route] }
|
21
21
|
end
|
22
22
|
|
23
|
+
include StripeMock::RequestHandlers::ExternalAccounts
|
23
24
|
include StripeMock::RequestHandlers::Accounts
|
25
|
+
include StripeMock::RequestHandlers::Balance
|
24
26
|
include StripeMock::RequestHandlers::BalanceTransactions
|
25
27
|
include StripeMock::RequestHandlers::Charges
|
26
28
|
include StripeMock::RequestHandlers::Cards
|
27
29
|
include StripeMock::RequestHandlers::Sources
|
28
30
|
include StripeMock::RequestHandlers::Subscriptions # must be before Customers
|
31
|
+
include StripeMock::RequestHandlers::SubscriptionItems
|
29
32
|
include StripeMock::RequestHandlers::Customers
|
30
33
|
include StripeMock::RequestHandlers::Coupons
|
31
34
|
include StripeMock::RequestHandlers::Disputes
|
@@ -34,19 +37,26 @@ module StripeMock
|
|
34
37
|
include StripeMock::RequestHandlers::InvoiceItems
|
35
38
|
include StripeMock::RequestHandlers::Orders
|
36
39
|
include StripeMock::RequestHandlers::Plans
|
40
|
+
include StripeMock::RequestHandlers::Products
|
41
|
+
include StripeMock::RequestHandlers::Refunds
|
37
42
|
include StripeMock::RequestHandlers::Recipients
|
38
43
|
include StripeMock::RequestHandlers::Transfers
|
39
44
|
include StripeMock::RequestHandlers::Tokens
|
45
|
+
include StripeMock::RequestHandlers::CountrySpec
|
46
|
+
include StripeMock::RequestHandlers::Payouts
|
47
|
+
include StripeMock::RequestHandlers::EphemeralKey
|
48
|
+
include StripeMock::RequestHandlers::TaxRates
|
40
49
|
|
41
|
-
|
42
|
-
attr_reader :accounts, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
|
50
|
+
attr_reader :accounts, :balance, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
|
43
51
|
:disputes, :events, :invoices, :invoice_items, :orders, :plans, :recipients,
|
44
|
-
:transfers, :subscriptions
|
52
|
+
:refunds, :transfers, :payouts, :subscriptions, :country_spec, :subscriptions_items,
|
53
|
+
:products, :tax_rates
|
45
54
|
|
46
|
-
attr_accessor :error_queue, :debug
|
55
|
+
attr_accessor :error_queue, :debug, :conversion_rate, :account_balance
|
47
56
|
|
48
57
|
def initialize
|
49
58
|
@accounts = {}
|
59
|
+
@balance = Data.mock_balance
|
50
60
|
@balance_transactions = Data.mock_balance_transactions(['txn_05RsQX2eZvKYlo2C0FRTGSSA','txn_15RsQX2eZvKYlo2C0ERTYUIA', 'txn_25RsQX2eZvKYlo2C0ZXCVBNM', 'txn_35RsQX2eZvKYlo2C0QAZXSWE', 'txn_45RsQX2eZvKYlo2C0EDCVFRT', 'txn_55RsQX2eZvKYlo2C0OIKLJUY', 'txn_65RsQX2eZvKYlo2C0ASDFGHJ', 'txn_75RsQX2eZvKYlo2C0EDCXSWQ', 'txn_85RsQX2eZvKYlo2C0UJMCDET', 'txn_95RsQX2eZvKYlo2C0EDFRYUI'])
|
51
61
|
@bank_tokens = {}
|
52
62
|
@card_tokens = {}
|
@@ -59,20 +69,29 @@ module StripeMock
|
|
59
69
|
@invoice_items = {}
|
60
70
|
@orders = {}
|
61
71
|
@plans = {}
|
72
|
+
@products = {}
|
62
73
|
@recipients = {}
|
74
|
+
@refunds = {}
|
63
75
|
@transfers = {}
|
76
|
+
@payouts = {}
|
64
77
|
@subscriptions = {}
|
78
|
+
@subscriptions_items = {}
|
79
|
+
@country_spec = {}
|
80
|
+
@tax_rates = {}
|
65
81
|
|
66
82
|
@debug = false
|
67
83
|
@error_queue = ErrorQueue.new
|
68
84
|
@id_counter = 0
|
69
85
|
@balance_transaction_counter = 0
|
86
|
+
@dispute_counter = 0
|
87
|
+
@conversion_rate = 1.0
|
88
|
+
@account_balance = 10000
|
70
89
|
|
71
90
|
# This is basically a cache for ParamValidators
|
72
91
|
@base_strategy = TestStrategies::Base.new
|
73
92
|
end
|
74
93
|
|
75
|
-
def mock_request(method, url, api_key, params
|
94
|
+
def mock_request(method, url, api_key: nil, api_base: nil, params: {}, headers: {})
|
76
95
|
return {} if method == :xtest
|
77
96
|
|
78
97
|
api_key ||= (Stripe.api_key || DUMMY_API_KEY)
|
@@ -95,7 +114,7 @@ module StripeMock
|
|
95
114
|
else
|
96
115
|
res = self.send(handler[:name], handler[:route], method_url, params, headers)
|
97
116
|
puts " [res] #{res}" if @debug == true
|
98
|
-
[res, api_key]
|
117
|
+
[to_faraday_hash(res), api_key]
|
99
118
|
end
|
100
119
|
else
|
101
120
|
puts "[StripeMock] Warning : Unrecognized endpoint + method : [#{method} #{url}]"
|
@@ -109,12 +128,44 @@ module StripeMock
|
|
109
128
|
@events[ event_data[:id] ] = symbolize_names(event_data)
|
110
129
|
end
|
111
130
|
|
131
|
+
def upsert_stripe_object(object, attributes)
|
132
|
+
# Most Stripe entities can be created via the API. However, some entities are created when other Stripe entities are
|
133
|
+
# created - such as when BalanceTransactions are created when Charges are created. This method provides the ability
|
134
|
+
# to create these internal entities.
|
135
|
+
# It also provides the ability to modify existing Stripe entities.
|
136
|
+
id = attributes[:id]
|
137
|
+
if id.nil? || id == ""
|
138
|
+
# Insert new Stripe object
|
139
|
+
case object
|
140
|
+
when :balance_transaction
|
141
|
+
id = new_balance_transaction('txn', attributes)
|
142
|
+
when :dispute
|
143
|
+
id = new_dispute('dp', attributes)
|
144
|
+
else
|
145
|
+
raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
|
146
|
+
end
|
147
|
+
else
|
148
|
+
# Update existing Stripe object
|
149
|
+
case object
|
150
|
+
when :balance_transaction
|
151
|
+
btxn = assert_existence :balance_transaction, id, @balance_transactions[id]
|
152
|
+
btxn.merge!(attributes)
|
153
|
+
when :dispute
|
154
|
+
dispute = assert_existence :dispute, id, @disputes[id]
|
155
|
+
dispute.merge!(attributes)
|
156
|
+
else
|
157
|
+
raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
id
|
161
|
+
end
|
162
|
+
|
112
163
|
private
|
113
164
|
|
114
165
|
def assert_existence(type, id, obj, message=nil)
|
115
166
|
if obj.nil?
|
116
167
|
msg = message || "No such #{type}: #{id}"
|
117
|
-
raise Stripe::InvalidRequestError.new(msg, type.to_s, 404)
|
168
|
+
raise Stripe::InvalidRequestError.new(msg, type.to_s, http_status: 404)
|
118
169
|
end
|
119
170
|
obj
|
120
171
|
end
|
@@ -124,14 +175,59 @@ module StripeMock
|
|
124
175
|
"#{StripeMock.global_id_prefix}#{prefix}_#{@id_counter += 1}"
|
125
176
|
end
|
126
177
|
|
127
|
-
def new_balance_transaction(prefix)
|
178
|
+
def new_balance_transaction(prefix, params = {})
|
128
179
|
# balance transaction ids must be strings
|
129
|
-
"#{StripeMock.global_id_prefix}#{prefix}_#{@balance_transaction_counter += 1}"
|
180
|
+
id = "#{StripeMock.global_id_prefix}#{prefix}_#{@balance_transaction_counter += 1}"
|
181
|
+
amount = params[:amount]
|
182
|
+
unless amount.nil?
|
183
|
+
# Fee calculation
|
184
|
+
calculate_fees(params) unless params[:fee]
|
185
|
+
params[:net] = amount - params[:fee]
|
186
|
+
params[:amount] = amount * @conversion_rate
|
187
|
+
end
|
188
|
+
@balance_transactions[id] = Data.mock_balance_transaction(params.merge(id: id))
|
189
|
+
id
|
190
|
+
end
|
191
|
+
|
192
|
+
def new_dispute(prefix, params = {})
|
193
|
+
id = "#{StripeMock.global_id_prefix}#{prefix}_#{@dispute_counter += 1}"
|
194
|
+
@disputes[id] = Data.mock_dispute(params.merge(id: id))
|
195
|
+
id
|
130
196
|
end
|
131
197
|
|
132
198
|
def symbolize_names(hash)
|
133
199
|
Stripe::Util.symbolize_names(hash)
|
134
200
|
end
|
135
201
|
|
202
|
+
def to_faraday_hash(hash)
|
203
|
+
response = Struct.new(:data)
|
204
|
+
response.new(hash)
|
205
|
+
end
|
206
|
+
|
207
|
+
def calculate_fees(params)
|
208
|
+
application_fee = params[:application_fee] || 0
|
209
|
+
params[:fee] = processing_fee(params[:amount]) + application_fee
|
210
|
+
params[:fee_details] = [
|
211
|
+
{
|
212
|
+
amount: processing_fee(params[:amount]),
|
213
|
+
application: nil,
|
214
|
+
currency: params[:currency] || StripeMock.default_currency,
|
215
|
+
description: "Stripe processing fees",
|
216
|
+
type: "stripe_fee"
|
217
|
+
}
|
218
|
+
]
|
219
|
+
if application_fee
|
220
|
+
params[:fee_details] << {
|
221
|
+
amount: application_fee,
|
222
|
+
currency: params[:currency] || StripeMock.default_currency,
|
223
|
+
description: "Application fee",
|
224
|
+
type: "application_fee"
|
225
|
+
}
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def processing_fee(amount)
|
230
|
+
(30 + (amount.abs * 0.029).ceil) * (amount > 0 ? 1 : -1)
|
231
|
+
end
|
136
232
|
end
|
137
233
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module StripeMock
|
2
2
|
module RequestHandlers
|
3
3
|
module Accounts
|
4
|
+
VALID_START_YEAR = 2009
|
4
5
|
|
5
6
|
def Accounts.included(klass)
|
6
7
|
klass.add_handler 'post /v1/accounts', :new_account
|
@@ -8,6 +9,7 @@ module StripeMock
|
|
8
9
|
klass.add_handler 'get /v1/accounts/(.*)', :get_account
|
9
10
|
klass.add_handler 'post /v1/accounts/(.*)', :update_account
|
10
11
|
klass.add_handler 'get /v1/accounts', :list_accounts
|
12
|
+
klass.add_handler 'post /oauth/deauthorize',:deauthorize
|
11
13
|
end
|
12
14
|
|
13
15
|
def new_account(route, method_url, params, headers)
|
@@ -25,8 +27,14 @@ module StripeMock
|
|
25
27
|
|
26
28
|
def update_account(route, method_url, params, headers)
|
27
29
|
route =~ method_url
|
28
|
-
assert_existence :account, $1, accounts[$1]
|
29
|
-
|
30
|
+
account = assert_existence :account, $1, accounts[$1]
|
31
|
+
account.merge!(params)
|
32
|
+
if blank_value?(params[:tos_acceptance], :date)
|
33
|
+
raise Stripe::InvalidRequestError.new("Invalid integer: ", "tos_acceptance[date]", http_status: 400)
|
34
|
+
elsif params[:tos_acceptance] && params[:tos_acceptance][:date]
|
35
|
+
validate_acceptance_date(params[:tos_acceptance][:date])
|
36
|
+
end
|
37
|
+
account
|
30
38
|
end
|
31
39
|
|
32
40
|
def list_accounts(route, method_url, params, headers)
|
@@ -34,6 +42,12 @@ module StripeMock
|
|
34
42
|
Data.mock_list_object(accounts.values, params)
|
35
43
|
end
|
36
44
|
|
45
|
+
def deauthorize(route, method_url, params, headers)
|
46
|
+
init_account
|
47
|
+
route =~ method_url
|
48
|
+
Stripe::StripeObject.construct_from(:stripe_user_id => params[:stripe_user_id])
|
49
|
+
end
|
50
|
+
|
37
51
|
private
|
38
52
|
|
39
53
|
def init_account
|
@@ -42,6 +56,31 @@ module StripeMock
|
|
42
56
|
accounts[acc[:id]] = acc
|
43
57
|
end
|
44
58
|
end
|
59
|
+
|
60
|
+
# Checks if setting a blank value
|
61
|
+
#
|
62
|
+
# returns true if the key is included in the hash
|
63
|
+
# and its value is empty or nil
|
64
|
+
def blank_value?(hash, key)
|
65
|
+
if hash.key?(key)
|
66
|
+
value = hash[key]
|
67
|
+
return true if value.nil? || "" == value
|
68
|
+
end
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_acceptance_date(unix_date)
|
73
|
+
unix_now = Time.now.strftime("%s").to_i
|
74
|
+
formatted_date = Time.at(unix_date)
|
75
|
+
|
76
|
+
return if formatted_date.year >= VALID_START_YEAR && unix_now >= unix_date
|
77
|
+
|
78
|
+
raise Stripe::InvalidRequestError.new(
|
79
|
+
"ToS acceptance date is not valid. Dates are expected to be integers, measured in seconds, not in the future, and after 2009",
|
80
|
+
"tos_acceptance[date]",
|
81
|
+
http_status: 400
|
82
|
+
)
|
83
|
+
end
|
45
84
|
end
|
46
85
|
end
|
47
86
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module Balance
|
4
|
+
|
5
|
+
def Balance.included(klass)
|
6
|
+
klass.add_handler 'get /v1/balance', :get_balance
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_balance(route, method_url, params, headers)
|
10
|
+
route =~ method_url
|
11
|
+
|
12
|
+
return_balance = Data.mock_balance(account_balance)
|
13
|
+
return_balance
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -9,11 +9,27 @@ module StripeMock
|
|
9
9
|
|
10
10
|
def get_balance_transaction(route, method_url, params, headers)
|
11
11
|
route =~ method_url
|
12
|
-
assert_existence :balance_transaction, $1, balance_transactions[$1]
|
12
|
+
assert_existence :balance_transaction, $1, hide_additional_attributes(balance_transactions[$1])
|
13
13
|
end
|
14
14
|
|
15
15
|
def list_balance_transactions(route, method_url, params, headers)
|
16
|
-
|
16
|
+
values = balance_transactions.values
|
17
|
+
if params.has_key?(:transfer)
|
18
|
+
# If transfer supplied as params, need to filter the btxns returned to only include those with the specified transfer id
|
19
|
+
values = values.select{|btxn| btxn[:transfer] == params[:transfer]}
|
20
|
+
end
|
21
|
+
Data.mock_list_object(values.map{|btxn| hide_additional_attributes(btxn)}, params)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def hide_additional_attributes(btxn)
|
27
|
+
# For automatic Stripe transfers, the transfer attribute on balance_transaction stores the transfer which
|
28
|
+
# included this balance_transaction. However, it is not exposed as a field returned on a balance_transaction.
|
29
|
+
# Therefore, need to not show this attribute if it exists.
|
30
|
+
if !btxn.nil?
|
31
|
+
btxn.reject{|k,v| k == :transfer }
|
32
|
+
end
|
17
33
|
end
|
18
34
|
|
19
35
|
end
|
@@ -8,14 +8,17 @@ module StripeMock
|
|
8
8
|
klass.add_handler 'get /v1/charges/(.*)', :get_charge
|
9
9
|
klass.add_handler 'post /v1/charges/(.*)/capture', :capture_charge
|
10
10
|
klass.add_handler 'post /v1/charges/(.*)/refund', :refund_charge
|
11
|
-
klass.add_handler 'post /v1/charges/(.*)/refunds', :
|
11
|
+
klass.add_handler 'post /v1/charges/(.*)/refunds', :refund_charge
|
12
12
|
klass.add_handler 'post /v1/charges/(.*)', :update_charge
|
13
13
|
end
|
14
14
|
|
15
15
|
def new_charge(route, method_url, params, headers)
|
16
|
-
if
|
17
|
-
|
18
|
-
|
16
|
+
if headers && headers[:idempotency_key]
|
17
|
+
params[:idempotency_key] = headers[:idempotency_key]
|
18
|
+
if charges.any?
|
19
|
+
original_charge = charges.values.find { |c| c[:idempotency_key] == headers[:idempotency_key]}
|
20
|
+
return charges[original_charge[:id]] if original_charge
|
21
|
+
end
|
19
22
|
end
|
20
23
|
|
21
24
|
id = new_id('ch')
|
@@ -28,10 +31,10 @@ module StripeMock
|
|
28
31
|
if params[:customer]
|
29
32
|
params[:source] = get_card(customers[params[:customer]], params[:source])
|
30
33
|
else
|
31
|
-
params[:source] =
|
34
|
+
params[:source] = get_card_or_bank_by_token(params[:source])
|
32
35
|
end
|
33
36
|
elsif params[:source][:id]
|
34
|
-
raise Stripe::InvalidRequestError.new("Invalid token id: #{params[:source]}", 'card', 400)
|
37
|
+
raise Stripe::InvalidRequestError.new("Invalid token id: #{params[:source]}", 'card', http_status: 400)
|
35
38
|
end
|
36
39
|
elsif params[:customer]
|
37
40
|
customer = customers[params[:customer]]
|
@@ -41,8 +44,21 @@ module StripeMock
|
|
41
44
|
end
|
42
45
|
|
43
46
|
ensure_required_params(params)
|
47
|
+
bal_trans_params = { amount: params[:amount], source: id, application_fee: params[:application_fee] }
|
48
|
+
|
49
|
+
balance_transaction_id = new_balance_transaction('txn', bal_trans_params)
|
50
|
+
|
51
|
+
charges[id] = Data.mock_charge(
|
52
|
+
params.merge :id => id,
|
53
|
+
:balance_transaction => balance_transaction_id)
|
54
|
+
|
55
|
+
charge = charges[id].clone
|
56
|
+
if params[:expand] == ['balance_transaction']
|
57
|
+
charge[:balance_transaction] =
|
58
|
+
balance_transactions[balance_transaction_id]
|
59
|
+
end
|
44
60
|
|
45
|
-
|
61
|
+
charge
|
46
62
|
end
|
47
63
|
|
48
64
|
def update_charge(route, method_url, params, headers)
|
@@ -53,7 +69,7 @@ module StripeMock
|
|
53
69
|
allowed = allowed_params(params)
|
54
70
|
disallowed = params.keys - allowed
|
55
71
|
if disallowed.count > 0
|
56
|
-
raise Stripe::InvalidRequestError.new("Received unknown parameters: #{disallowed.join(', ')}" , '', 400)
|
72
|
+
raise Stripe::InvalidRequestError.new("Received unknown parameters: #{disallowed.join(', ')}" , '', http_status: 400)
|
57
73
|
end
|
58
74
|
|
59
75
|
charges[id] = Util.rmerge(charge, params)
|
@@ -74,7 +90,16 @@ module StripeMock
|
|
74
90
|
|
75
91
|
def get_charge(route, method_url, params, headers)
|
76
92
|
route =~ method_url
|
77
|
-
|
93
|
+
charge_id = $1 || params[:charge]
|
94
|
+
charge = assert_existence :charge, charge_id, charges[charge_id]
|
95
|
+
|
96
|
+
charge = charge.clone
|
97
|
+
if params[:expand] == ['balance_transaction']
|
98
|
+
balance_transaction = balance_transactions[charge[:balance_transaction]]
|
99
|
+
charge[:balance_transaction] = balance_transaction
|
100
|
+
end
|
101
|
+
|
102
|
+
charge
|
78
103
|
end
|
79
104
|
|
80
105
|
def capture_charge(route, method_url, params, headers)
|
@@ -101,24 +126,12 @@ module StripeMock
|
|
101
126
|
def refund_charge(route, method_url, params, headers)
|
102
127
|
charge = get_charge(route, method_url, params, headers)
|
103
128
|
|
104
|
-
|
105
|
-
|
106
|
-
|
129
|
+
new_refund(
|
130
|
+
route,
|
131
|
+
method_url,
|
132
|
+
params.merge(:charge => charge[:id]),
|
133
|
+
headers
|
107
134
|
)
|
108
|
-
add_refund_to_charge(refund, charge)
|
109
|
-
charge
|
110
|
-
end
|
111
|
-
|
112
|
-
def create_refund(route, method_url, params, headers)
|
113
|
-
charge = get_charge(route, method_url, params, headers)
|
114
|
-
|
115
|
-
refund = Data.mock_refund params.merge(
|
116
|
-
:balance_transaction => new_balance_transaction('txn'),
|
117
|
-
:id => new_id('re'),
|
118
|
-
:charge => charge[:id]
|
119
|
-
)
|
120
|
-
add_refund_to_charge(refund, charge)
|
121
|
-
refund
|
122
135
|
end
|
123
136
|
|
124
137
|
private
|
@@ -129,9 +142,11 @@ module StripeMock
|
|
129
142
|
elsif params[:currency].nil?
|
130
143
|
require_param(:currency)
|
131
144
|
elsif non_integer_charge_amount?(params)
|
132
|
-
raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', 400)
|
145
|
+
raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', http_status: 400)
|
133
146
|
elsif non_positive_charge_amount?(params)
|
134
|
-
raise Stripe::InvalidRequestError.new('Invalid positive integer', 'amount', 400)
|
147
|
+
raise Stripe::InvalidRequestError.new('Invalid positive integer', 'amount', http_status: 400)
|
148
|
+
elsif params[:source].nil? && params[:customer].nil?
|
149
|
+
raise Stripe::InvalidRequestError.new('Must provide source or customer.', http_status: nil)
|
135
150
|
end
|
136
151
|
end
|
137
152
|
|
@@ -143,12 +158,8 @@ module StripeMock
|
|
143
158
|
params[:amount] && params[:amount] < 1
|
144
159
|
end
|
145
160
|
|
146
|
-
def require_param(param)
|
147
|
-
raise Stripe::InvalidRequestError.new("Missing required param: #{param}", param.to_s, 400)
|
148
|
-
end
|
149
|
-
|
150
161
|
def allowed_params(params)
|
151
|
-
allowed = [:description, :metadata, :receipt_email, :fraud_details, :shipping]
|
162
|
+
allowed = [:description, :metadata, :receipt_email, :fraud_details, :shipping, :destination]
|
152
163
|
|
153
164
|
# This is a workaround for the way the Stripe API sends params even when they aren't modified.
|
154
165
|
# Stipe will include those params even when they aren't modified.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module CountrySpec
|
4
|
+
|
5
|
+
def CountrySpec.included(klass)
|
6
|
+
klass.add_handler 'get /v1/country_specs/(.*)', :retrieve_country_spec
|
7
|
+
end
|
8
|
+
|
9
|
+
def retrieve_country_spec(route, method_url, params, headers)
|
10
|
+
route =~ method_url
|
11
|
+
|
12
|
+
unless ["AT", "AU", "BE", "CA", "DE", "DK", "ES", "FI", "FR", "GB", "IE", "IT", "JP", "LU", "NL", "NO", "SE", "SG", "US"].include?($1)
|
13
|
+
raise Stripe::InvalidRequestError.new("#{$1} is not currently supported by Stripe.", $1.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
country_spec[$1] ||= Data.mock_country_spec($1)
|
17
|
+
|
18
|
+
assert_existence :country_spec, $1, country_spec[$1]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -11,18 +11,19 @@ module StripeMock
|
|
11
11
|
|
12
12
|
def new_coupon(route, method_url, params, headers)
|
13
13
|
params[:id] ||= new_id('coupon')
|
14
|
-
raise Stripe::InvalidRequestError.new('Missing required param: duration', 'coupon', 400) unless params[:duration]
|
15
|
-
|
14
|
+
raise Stripe::InvalidRequestError.new('Missing required param: duration', 'coupon', http_status: 400) unless params[:duration]
|
15
|
+
raise Stripe::InvalidRequestError.new('You must pass currency when passing amount_off', 'coupon', http_status: 400) if params[:amount_off] && !params[:currency]
|
16
|
+
coupons[ params[:id] ] = Data.mock_coupon({amount_off: nil, percent_off:nil}.merge(params))
|
16
17
|
end
|
17
18
|
|
18
19
|
def get_coupon(route, method_url, params, headers)
|
19
20
|
route =~ method_url
|
20
|
-
assert_existence :
|
21
|
+
assert_existence :coupon, $1, coupons[$1]
|
21
22
|
end
|
22
23
|
|
23
24
|
def delete_coupon(route, method_url, params, headers)
|
24
25
|
route =~ method_url
|
25
|
-
assert_existence :
|
26
|
+
assert_existence :coupon, $1, coupons.delete($1)
|
26
27
|
end
|
27
28
|
|
28
29
|
def list_coupons(route, method_url, params, headers)
|
@@ -4,10 +4,11 @@ module StripeMock
|
|
4
4
|
|
5
5
|
def Customers.included(klass)
|
6
6
|
klass.add_handler 'post /v1/customers', :new_customer
|
7
|
-
klass.add_handler 'post /v1/customers/(
|
8
|
-
klass.add_handler 'get /v1/customers/(
|
9
|
-
klass.add_handler 'delete /v1/customers/(
|
7
|
+
klass.add_handler 'post /v1/customers/([^/]*)', :update_customer
|
8
|
+
klass.add_handler 'get /v1/customers/([^/]*)', :get_customer
|
9
|
+
klass.add_handler 'delete /v1/customers/([^/]*)', :delete_customer
|
10
10
|
klass.add_handler 'get /v1/customers', :list_customers
|
11
|
+
klass.add_handler 'delete /v1/customers/([^/]*)/discount', :delete_customer_discount
|
11
12
|
end
|
12
13
|
|
13
14
|
def new_customer(route, method_url, params, headers)
|
@@ -18,7 +19,7 @@ module StripeMock
|
|
18
19
|
new_card =
|
19
20
|
if params[:source].is_a?(Hash)
|
20
21
|
unless params[:source][:object] && params[:source][:number] && params[:source][:exp_month] && params[:source][:exp_year]
|
21
|
-
raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, 400)
|
22
|
+
raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, http_status: 400)
|
22
23
|
end
|
23
24
|
card_from_params(params[:source])
|
24
25
|
else
|
@@ -35,22 +36,22 @@ module StripeMock
|
|
35
36
|
plan = assert_existence :plan, plan_id, plans[plan_id]
|
36
37
|
|
37
38
|
if params[:default_source].nil? && params[:trial_end].nil? && plan[:trial_period_days].nil? && plan[:amount] != 0
|
38
|
-
raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, 400)
|
39
|
+
raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, http_status: 400)
|
39
40
|
end
|
40
41
|
|
41
42
|
subscription = Data.mock_subscription({ id: new_id('su') })
|
42
|
-
subscription
|
43
|
+
subscription = resolve_subscription_changes(subscription, [plan], customers[ params[:id] ], params)
|
43
44
|
add_subscription_to_customer(customers[ params[:id] ], subscription)
|
44
45
|
subscriptions[subscription[:id]] = subscription
|
45
46
|
elsif params[:trial_end]
|
46
|
-
raise Stripe::InvalidRequestError.new('Received unknown parameter: trial_end', nil, 400)
|
47
|
+
raise Stripe::InvalidRequestError.new('Received unknown parameter: trial_end', nil, http_status: 400)
|
47
48
|
end
|
48
49
|
|
49
50
|
if params[:coupon]
|
50
51
|
coupon = coupons[ params[:coupon] ]
|
51
52
|
assert_existence :coupon, params[:coupon], coupon
|
52
53
|
|
53
|
-
|
54
|
+
add_coupon_to_object(customers[params[:id]], coupon)
|
54
55
|
end
|
55
56
|
|
56
57
|
customers[ params[:id] ]
|
@@ -77,7 +78,7 @@ module StripeMock
|
|
77
78
|
new_card = get_card_or_bank_by_token(params.delete(:source))
|
78
79
|
elsif params[:source].is_a?(Hash)
|
79
80
|
unless params[:source][:object] && params[:source][:number] && params[:source][:exp_month] && params[:source][:exp_year]
|
80
|
-
raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, 400)
|
81
|
+
raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, http_status: 400)
|
81
82
|
end
|
82
83
|
new_card = card_from_params(params.delete(:source))
|
83
84
|
end
|
@@ -89,7 +90,7 @@ module StripeMock
|
|
89
90
|
coupon = coupons[ params[:coupon] ]
|
90
91
|
assert_existence :coupon, params[:coupon], coupon
|
91
92
|
|
92
|
-
|
93
|
+
add_coupon_to_object(cus, coupon)
|
93
94
|
end
|
94
95
|
|
95
96
|
cus
|
@@ -107,13 +108,30 @@ module StripeMock
|
|
107
108
|
|
108
109
|
def get_customer(route, method_url, params, headers)
|
109
110
|
route =~ method_url
|
110
|
-
assert_existence :customer, $1, customers[$1]
|
111
|
+
customer = assert_existence :customer, $1, customers[$1]
|
112
|
+
|
113
|
+
customer = customer.clone
|
114
|
+
if params[:expand] == ['default_source']
|
115
|
+
customer[:default_source] = customer[:sources][:data].detect do |source|
|
116
|
+
source[:id] == customer[:default_source]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
customer
|
111
121
|
end
|
112
122
|
|
113
123
|
def list_customers(route, method_url, params, headers)
|
114
124
|
Data.mock_list_object(customers.values, params)
|
115
125
|
end
|
116
126
|
|
127
|
+
def delete_customer_discount(route, method_url, params, headers)
|
128
|
+
route =~ method_url
|
129
|
+
cus = assert_existence :customer, $1, customers[$1]
|
130
|
+
|
131
|
+
cus[:discount] = nil
|
132
|
+
|
133
|
+
cus
|
134
|
+
end
|
117
135
|
end
|
118
136
|
end
|
119
137
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module EphemeralKey
|
4
|
+
def self.included(klass)
|
5
|
+
klass.add_handler 'post /v1/ephemeral_keys', :create_ephemeral_key
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_ephemeral_key(route, method_url, params, headers)
|
9
|
+
Data.mock_ephemeral_key(params)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module ExternalAccounts
|
4
|
+
|
5
|
+
def ExternalAccounts.included(klass)
|
6
|
+
klass.add_handler 'get /v1/accounts/(.*)/external_accounts', :retrieve_external_accounts
|
7
|
+
klass.add_handler 'post /v1/accounts/(.*)/external_accounts', :create_external_account
|
8
|
+
klass.add_handler 'post /v1/accounts/(.*)/external_accounts/(.*)/verify', :verify_external_account
|
9
|
+
klass.add_handler 'get /v1/accounts/(.*)/external_accounts/(.*)', :retrieve_external_account
|
10
|
+
klass.add_handler 'delete /v1/accounts/(.*)/external_accounts/(.*)', :delete_external_account
|
11
|
+
klass.add_handler 'post /v1/accounts/(.*)/external_accounts/(.*)', :update_external_account
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_external_account(route, method_url, params, headers)
|
15
|
+
route =~ method_url
|
16
|
+
add_external_account_to(:account, $1, params, accounts)
|
17
|
+
end
|
18
|
+
|
19
|
+
def retrieve_external_accounts(route, method_url, params, headers)
|
20
|
+
route =~ method_url
|
21
|
+
retrieve_object_cards(:account, $1, accounts)
|
22
|
+
end
|
23
|
+
|
24
|
+
def retrieve_external_account(route, method_url, params, headers)
|
25
|
+
route =~ method_url
|
26
|
+
account = assert_existence :account, $1, accounts[$1]
|
27
|
+
|
28
|
+
assert_existence :card, $2, get_card(account, $2)
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete_external_account(route, method_url, params, headers)
|
32
|
+
route =~ method_url
|
33
|
+
delete_card_from(:account, $1, $2, accounts)
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_external_account(route, method_url, params, headers)
|
37
|
+
route =~ method_url
|
38
|
+
account = assert_existence :account, $1, accounts[$1]
|
39
|
+
|
40
|
+
card = assert_existence :card, $2, get_card(account, $2)
|
41
|
+
card.merge!(params)
|
42
|
+
card
|
43
|
+
end
|
44
|
+
|
45
|
+
def verify_external_account(route, method_url, params, headers)
|
46
|
+
route =~ method_url
|
47
|
+
account = assert_existence :account, $1, accounts[$1]
|
48
|
+
|
49
|
+
external_account = assert_existence :bank_account, $2, verify_bank_account(account, $2)
|
50
|
+
external_account
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|