stripe-ruby-mock 2.3.1 → 2.5.8
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/.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
|