epopia-stripe-ruby-mock 2.5.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.env +2 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.travis.yml +28 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +413 -0
- data/Rakefile +14 -0
- data/bin/stripe-mock-server +19 -0
- data/lib/stripe_mock.rb +95 -0
- data/lib/stripe_mock/api/account_balance.rb +14 -0
- data/lib/stripe_mock/api/bank_tokens.rb +13 -0
- data/lib/stripe_mock/api/card_tokens.rb +13 -0
- data/lib/stripe_mock/api/client.rb +41 -0
- data/lib/stripe_mock/api/conversion_rate.rb +14 -0
- data/lib/stripe_mock/api/debug.rb +11 -0
- data/lib/stripe_mock/api/errors.rb +65 -0
- data/lib/stripe_mock/api/global_id_prefix.rb +22 -0
- data/lib/stripe_mock/api/instance.rb +38 -0
- data/lib/stripe_mock/api/live.rb +15 -0
- data/lib/stripe_mock/api/server.rb +39 -0
- data/lib/stripe_mock/api/test_helpers.rb +24 -0
- data/lib/stripe_mock/api/webhooks.rb +88 -0
- data/lib/stripe_mock/client.rb +127 -0
- data/lib/stripe_mock/data.rb +1193 -0
- data/lib/stripe_mock/data/list.rb +73 -0
- data/lib/stripe_mock/error_queue.rb +27 -0
- data/lib/stripe_mock/errors/closed_client_connection_error.rb +9 -0
- data/lib/stripe_mock/errors/server_timeout_error.rb +12 -0
- data/lib/stripe_mock/errors/stripe_mock_error.rb +15 -0
- data/lib/stripe_mock/errors/uninitialized_instance_error.rb +9 -0
- data/lib/stripe_mock/errors/unstarted_state_error.rb +9 -0
- data/lib/stripe_mock/errors/unsupported_request_error.rb +4 -0
- data/lib/stripe_mock/instance.rb +237 -0
- data/lib/stripe_mock/request_handlers/accounts.rb +86 -0
- data/lib/stripe_mock/request_handlers/balance.rb +17 -0
- data/lib/stripe_mock/request_handlers/balance_transactions.rb +37 -0
- data/lib/stripe_mock/request_handlers/cards.rb +35 -0
- data/lib/stripe_mock/request_handlers/charges.rb +177 -0
- data/lib/stripe_mock/request_handlers/country_spec.rb +22 -0
- data/lib/stripe_mock/request_handlers/coupons.rb +35 -0
- data/lib/stripe_mock/request_handlers/customers.rb +137 -0
- data/lib/stripe_mock/request_handlers/disputes.rb +35 -0
- data/lib/stripe_mock/request_handlers/ephemeral_key.rb +13 -0
- data/lib/stripe_mock/request_handlers/events.rb +21 -0
- data/lib/stripe_mock/request_handlers/external_accounts.rb +55 -0
- data/lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb +14 -0
- data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +127 -0
- data/lib/stripe_mock/request_handlers/helpers/charge_helpers.rb +16 -0
- data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +17 -0
- data/lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb +49 -0
- data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +119 -0
- data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +44 -0
- data/lib/stripe_mock/request_handlers/invoice_items.rb +45 -0
- data/lib/stripe_mock/request_handlers/invoices.rb +177 -0
- data/lib/stripe_mock/request_handlers/orders.rb +80 -0
- data/lib/stripe_mock/request_handlers/payment_intents.rb +203 -0
- data/lib/stripe_mock/request_handlers/payment_methods.rb +112 -0
- data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
- data/lib/stripe_mock/request_handlers/plans.rb +42 -0
- data/lib/stripe_mock/request_handlers/products.rb +43 -0
- data/lib/stripe_mock/request_handlers/recipients.rb +60 -0
- data/lib/stripe_mock/request_handlers/refunds.rb +91 -0
- data/lib/stripe_mock/request_handlers/sources.rb +55 -0
- data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
- data/lib/stripe_mock/request_handlers/subscriptions.rb +296 -0
- data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
- data/lib/stripe_mock/request_handlers/tokens.rb +75 -0
- data/lib/stripe_mock/request_handlers/transfers.rb +65 -0
- data/lib/stripe_mock/request_handlers/validators/param_validators.rb +32 -0
- data/lib/stripe_mock/server.rb +93 -0
- data/lib/stripe_mock/test_strategies/base.rb +81 -0
- data/lib/stripe_mock/test_strategies/live.rb +40 -0
- data/lib/stripe_mock/test_strategies/mock.rb +27 -0
- data/lib/stripe_mock/util.rb +44 -0
- data/lib/stripe_mock/version.rb +4 -0
- data/lib/stripe_mock/webhook_fixtures/account.application.deauthorized.json +12 -0
- 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 +26 -0
- data/lib/stripe_mock/webhook_fixtures/balance.available.json +25 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.closed.json +22 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +22 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_reinstated.json +88 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_withdrawn.json +88 -0
- data/lib/stripe_mock/webhook_fixtures/charge.dispute.updated.json +25 -0
- data/lib/stripe_mock/webhook_fixtures/charge.failed.json +56 -0
- data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +69 -0
- data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +55 -0
- data/lib/stripe_mock/webhook_fixtures/charge.updated.json +58 -0
- data/lib/stripe_mock/webhook_fixtures/coupon.created.json +23 -0
- data/lib/stripe_mock/webhook_fixtures/coupon.deleted.json +23 -0
- data/lib/stripe_mock/webhook_fixtures/customer.created.json +54 -0
- data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +42 -0
- data/lib/stripe_mock/webhook_fixtures/customer.discount.created.json +28 -0
- data/lib/stripe_mock/webhook_fixtures/customer.discount.deleted.json +28 -0
- data/lib/stripe_mock/webhook_fixtures/customer.discount.updated.json +43 -0
- data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +32 -0
- data/lib/stripe_mock/webhook_fixtures/customer.source.deleted.json +32 -0
- data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -0
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +66 -0
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +65 -0
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +65 -0
- data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +78 -0
- data/lib/stripe_mock/webhook_fixtures/customer.updated.json +57 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.created.json +71 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +105 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +112 -0
- data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +74 -0
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +21 -0
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.deleted.json +21 -0
- data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +24 -0
- data/lib/stripe_mock/webhook_fixtures/plan.created.json +20 -0
- data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +20 -0
- data/lib/stripe_mock/webhook_fixtures/plan.updated.json +23 -0
- data/lib/stripe_mock/webhook_fixtures/transfer.created.json +89 -0
- data/lib/stripe_mock/webhook_fixtures/transfer.failed.json +89 -0
- data/lib/stripe_mock/webhook_fixtures/transfer.paid.json +89 -0
- data/lib/stripe_mock/webhook_fixtures/transfer.updated.json +92 -0
- data/lib/trollop.rb +782 -0
- data/spec/_dummy/webhooks/dummy.event.json +6 -0
- data/spec/api/instance_spec.rb +30 -0
- data/spec/fixtures/create_refund.yml +126 -0
- data/spec/fixtures/stripe_webhooks/account.updated.json +7 -0
- data/spec/fixtures/stripe_webhooks/custom.account.updated.json +5 -0
- data/spec/instance_spec.rb +100 -0
- data/spec/integration_examples/charge_token_examples.rb +51 -0
- data/spec/integration_examples/customer_card_examples.rb +42 -0
- data/spec/integration_examples/prepare_error_examples.rb +38 -0
- data/spec/list_spec.rb +140 -0
- data/spec/readme_spec.rb +75 -0
- data/spec/server_spec.rb +139 -0
- data/spec/shared_stripe_examples/account_examples.rb +96 -0
- data/spec/shared_stripe_examples/balance_examples.rb +11 -0
- data/spec/shared_stripe_examples/balance_transaction_examples.rb +63 -0
- data/spec/shared_stripe_examples/bank_examples.rb +229 -0
- data/spec/shared_stripe_examples/bank_token_examples.rb +59 -0
- data/spec/shared_stripe_examples/card_examples.rb +307 -0
- data/spec/shared_stripe_examples/card_token_examples.rb +185 -0
- data/spec/shared_stripe_examples/charge_examples.rb +510 -0
- data/spec/shared_stripe_examples/country_specs_examples.rb +18 -0
- data/spec/shared_stripe_examples/coupon_examples.rb +85 -0
- data/spec/shared_stripe_examples/customer_examples.rb +453 -0
- data/spec/shared_stripe_examples/dispute_examples.rb +98 -0
- data/spec/shared_stripe_examples/ephemeral_key_examples.rb +17 -0
- data/spec/shared_stripe_examples/error_mock_examples.rb +162 -0
- data/spec/shared_stripe_examples/external_account_examples.rb +170 -0
- data/spec/shared_stripe_examples/extra_features_examples.rb +36 -0
- data/spec/shared_stripe_examples/invoice_examples.rb +524 -0
- data/spec/shared_stripe_examples/invoice_item_examples.rb +69 -0
- data/spec/shared_stripe_examples/payment_intent_examples.rb +131 -0
- data/spec/shared_stripe_examples/payment_method_examples.rb +175 -0
- data/spec/shared_stripe_examples/payout_examples.rb +68 -0
- data/spec/shared_stripe_examples/plan_examples.rb +194 -0
- data/spec/shared_stripe_examples/product_example.rb +65 -0
- data/spec/shared_stripe_examples/recipient_examples.rb +118 -0
- data/spec/shared_stripe_examples/refund_examples.rb +472 -0
- data/spec/shared_stripe_examples/subscription_examples.rb +1148 -0
- 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 +130 -0
- data/spec/shared_stripe_examples/validation_examples.rb +19 -0
- data/spec/shared_stripe_examples/webhook_event_examples.rb +261 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/stripe_mock_spec.rb +123 -0
- data/spec/support/stripe_examples.rb +42 -0
- data/spec/util_spec.rb +121 -0
- data/stripe-ruby-mock.gemspec +27 -0
- metadata +344 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module Data
|
3
|
+
class List
|
4
|
+
attr_reader :data, :limit, :offset, :starting_after, :ending_before
|
5
|
+
|
6
|
+
def initialize(data, options = {})
|
7
|
+
@data = Array(data.clone)
|
8
|
+
@limit = [[options[:limit] || 10, 100].min, 1].max # restrict @limit to 1..100
|
9
|
+
@starting_after = options[:starting_after]
|
10
|
+
@ending_before = options[:ending_before]
|
11
|
+
if @data.first.is_a?(Hash) && @data.first[:created]
|
12
|
+
@data.sort_by! { |x| x[:created] }
|
13
|
+
@data.reverse!
|
14
|
+
elsif @data.first.respond_to?(:created)
|
15
|
+
@data.sort_by { |x| x.created }
|
16
|
+
@data.reverse!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def url
|
21
|
+
"/v1/#{object_types}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_hash
|
25
|
+
{ object: "list", data: data_page, url: url, has_more: has_more? }
|
26
|
+
end
|
27
|
+
alias_method :to_h, :to_hash
|
28
|
+
|
29
|
+
def has_more?
|
30
|
+
(offset + limit) < data.size
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method_name, *args, &block)
|
34
|
+
hash = to_hash
|
35
|
+
|
36
|
+
if hash.keys.include?(method_name)
|
37
|
+
hash[method_name]
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def respond_to?(method_name, priv = false)
|
44
|
+
to_hash.keys.include?(method_name) || super
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def offset
|
50
|
+
case
|
51
|
+
when starting_after
|
52
|
+
index = data.index { |datum| datum[:id] == starting_after }
|
53
|
+
(index || raise("No such object id: #{starting_after}")) + 1
|
54
|
+
when ending_before
|
55
|
+
index = data.index { |datum| datum[:id] == ending_before }
|
56
|
+
(index || raise("No such object id: #{ending_before}")) - 1
|
57
|
+
else
|
58
|
+
0
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def data_page
|
63
|
+
data[offset, limit]
|
64
|
+
end
|
65
|
+
|
66
|
+
def object_types
|
67
|
+
if first_object = data[0]
|
68
|
+
"#{first_object.class.to_s.split('::')[-1].downcase}s"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'drb/drb'
|
2
|
+
|
3
|
+
module StripeMock
|
4
|
+
class ErrorQueue
|
5
|
+
include DRb::DRbUndumped
|
6
|
+
extend DRb::DRbUndumped
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@queue = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def queue(error, handler_names)
|
13
|
+
@queue << handler_names.map {|n| [n, error]}
|
14
|
+
end
|
15
|
+
|
16
|
+
def error_for_handler_name(handler_name)
|
17
|
+
return nil if @queue.count == 0
|
18
|
+
triggers = @queue.first
|
19
|
+
(triggers.assoc(:all) || triggers.assoc(handler_name) || [])[1]
|
20
|
+
end
|
21
|
+
|
22
|
+
def dequeue
|
23
|
+
@queue.shift
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module StripeMock
|
2
|
+
class ServerTimeoutError < StripeMockError
|
3
|
+
|
4
|
+
attr_reader :associated_error
|
5
|
+
|
6
|
+
def initialize(associated_error)
|
7
|
+
@associated_error = associated_error
|
8
|
+
super("Unable to connect to stripe mock server (did you forget to run `$ stripe-mock-server`?)")
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
module StripeMock
|
2
|
+
class Instance
|
3
|
+
|
4
|
+
include StripeMock::RequestHandlers::Helpers
|
5
|
+
include StripeMock::RequestHandlers::ParamValidators
|
6
|
+
|
7
|
+
DUMMY_API_KEY = (0...32).map { (65 + rand(26)).chr }.join.downcase
|
8
|
+
|
9
|
+
# Handlers are ordered by priority
|
10
|
+
@@handlers = []
|
11
|
+
|
12
|
+
def self.add_handler(route, name)
|
13
|
+
@@handlers << {
|
14
|
+
:route => %r{^#{route}$},
|
15
|
+
:name => name
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.handler_for_method_url(method_url)
|
20
|
+
@@handlers.find {|h| method_url =~ h[:route] }
|
21
|
+
end
|
22
|
+
|
23
|
+
include StripeMock::RequestHandlers::PaymentIntents
|
24
|
+
include StripeMock::RequestHandlers::PaymentMethods
|
25
|
+
include StripeMock::RequestHandlers::ExternalAccounts
|
26
|
+
include StripeMock::RequestHandlers::Accounts
|
27
|
+
include StripeMock::RequestHandlers::Balance
|
28
|
+
include StripeMock::RequestHandlers::BalanceTransactions
|
29
|
+
include StripeMock::RequestHandlers::Charges
|
30
|
+
include StripeMock::RequestHandlers::Cards
|
31
|
+
include StripeMock::RequestHandlers::Sources
|
32
|
+
include StripeMock::RequestHandlers::Subscriptions # must be before Customers
|
33
|
+
include StripeMock::RequestHandlers::SubscriptionItems
|
34
|
+
include StripeMock::RequestHandlers::Customers
|
35
|
+
include StripeMock::RequestHandlers::Coupons
|
36
|
+
include StripeMock::RequestHandlers::Disputes
|
37
|
+
include StripeMock::RequestHandlers::Events
|
38
|
+
include StripeMock::RequestHandlers::Invoices
|
39
|
+
include StripeMock::RequestHandlers::InvoiceItems
|
40
|
+
include StripeMock::RequestHandlers::Orders
|
41
|
+
include StripeMock::RequestHandlers::Plans
|
42
|
+
include StripeMock::RequestHandlers::Products
|
43
|
+
include StripeMock::RequestHandlers::Refunds
|
44
|
+
include StripeMock::RequestHandlers::Recipients
|
45
|
+
include StripeMock::RequestHandlers::Transfers
|
46
|
+
include StripeMock::RequestHandlers::Tokens
|
47
|
+
include StripeMock::RequestHandlers::CountrySpec
|
48
|
+
include StripeMock::RequestHandlers::Payouts
|
49
|
+
include StripeMock::RequestHandlers::EphemeralKey
|
50
|
+
include StripeMock::RequestHandlers::TaxRates
|
51
|
+
|
52
|
+
attr_reader :accounts, :balance, :balance_transactions, :bank_tokens, :charges, :coupons, :customers,
|
53
|
+
:disputes, :events, :invoices, :invoice_items, :orders, :payment_intents, :payment_methods,
|
54
|
+
:plans, :recipients, :refunds, :transfers, :payouts, :subscriptions, :country_spec,
|
55
|
+
:subscriptions_items, :products, :tax_rates
|
56
|
+
|
57
|
+
attr_accessor :error_queue, :debug, :conversion_rate, :account_balance
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
@accounts = {}
|
61
|
+
@balance = Data.mock_balance
|
62
|
+
@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'])
|
63
|
+
@bank_tokens = {}
|
64
|
+
@card_tokens = {}
|
65
|
+
@customers = {}
|
66
|
+
@charges = {}
|
67
|
+
@payment_intents = {}
|
68
|
+
@coupons = {}
|
69
|
+
@disputes = Data.mock_disputes(['dp_05RsQX2eZvKYlo2C0FRTGSSA','dp_15RsQX2eZvKYlo2C0ERTYUIA', 'dp_25RsQX2eZvKYlo2C0ZXCVBNM', 'dp_35RsQX2eZvKYlo2C0QAZXSWE', 'dp_45RsQX2eZvKYlo2C0EDCVFRT', 'dp_55RsQX2eZvKYlo2C0OIKLJUY', 'dp_65RsQX2eZvKYlo2C0ASDFGHJ', 'dp_75RsQX2eZvKYlo2C0EDCXSWQ', 'dp_85RsQX2eZvKYlo2C0UJMCDET', 'dp_95RsQX2eZvKYlo2C0EDFRYUI'])
|
70
|
+
@events = {}
|
71
|
+
@invoices = {}
|
72
|
+
@invoice_items = {}
|
73
|
+
@orders = {}
|
74
|
+
@payment_methods = {}
|
75
|
+
@plans = {}
|
76
|
+
@products = {}
|
77
|
+
@recipients = {}
|
78
|
+
@refunds = {}
|
79
|
+
@transfers = {}
|
80
|
+
@payouts = {}
|
81
|
+
@subscriptions = {}
|
82
|
+
@subscriptions_items = {}
|
83
|
+
@country_spec = {}
|
84
|
+
@tax_rates = {}
|
85
|
+
|
86
|
+
@debug = false
|
87
|
+
@error_queue = ErrorQueue.new
|
88
|
+
@id_counter = 0
|
89
|
+
@balance_transaction_counter = 0
|
90
|
+
@dispute_counter = 0
|
91
|
+
@conversion_rate = 1.0
|
92
|
+
@account_balance = 10000
|
93
|
+
|
94
|
+
# This is basically a cache for ParamValidators
|
95
|
+
@base_strategy = TestStrategies::Base.new
|
96
|
+
end
|
97
|
+
|
98
|
+
def mock_request(method, url, api_key: nil, api_base: nil, params: {}, headers: {})
|
99
|
+
return {} if method == :xtest
|
100
|
+
|
101
|
+
api_key ||= (Stripe.api_key || DUMMY_API_KEY)
|
102
|
+
|
103
|
+
# Ensure params hash has symbols as keys
|
104
|
+
params = Stripe::Util.symbolize_names(params)
|
105
|
+
|
106
|
+
method_url = "#{method} #{url}"
|
107
|
+
|
108
|
+
if handler = Instance.handler_for_method_url(method_url)
|
109
|
+
if @debug == true
|
110
|
+
puts "- - - - " * 8
|
111
|
+
puts "[StripeMock req]::#{handler[:name]} #{method} #{url}"
|
112
|
+
puts " #{params}"
|
113
|
+
end
|
114
|
+
|
115
|
+
if mock_error = @error_queue.error_for_handler_name(handler[:name])
|
116
|
+
@error_queue.dequeue
|
117
|
+
raise mock_error
|
118
|
+
else
|
119
|
+
res = self.send(handler[:name], handler[:route], method_url, params, headers)
|
120
|
+
puts " [res] #{res}" if @debug == true
|
121
|
+
[to_faraday_hash(res), api_key]
|
122
|
+
end
|
123
|
+
else
|
124
|
+
puts "[StripeMock] Warning : Unrecognized endpoint + method : [#{method} #{url}]"
|
125
|
+
puts "[StripeMock] params: #{params}" unless params.empty?
|
126
|
+
[{}, api_key]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def generate_webhook_event(event_data)
|
131
|
+
event_data[:id] ||= new_id 'evt'
|
132
|
+
@events[ event_data[:id] ] = symbolize_names(event_data)
|
133
|
+
end
|
134
|
+
|
135
|
+
def upsert_stripe_object(object, attributes)
|
136
|
+
# Most Stripe entities can be created via the API. However, some entities are created when other Stripe entities are
|
137
|
+
# created - such as when BalanceTransactions are created when Charges are created. This method provides the ability
|
138
|
+
# to create these internal entities.
|
139
|
+
# It also provides the ability to modify existing Stripe entities.
|
140
|
+
id = attributes[:id]
|
141
|
+
if id.nil? || id == ""
|
142
|
+
# Insert new Stripe object
|
143
|
+
case object
|
144
|
+
when :balance_transaction
|
145
|
+
id = new_balance_transaction('txn', attributes)
|
146
|
+
when :dispute
|
147
|
+
id = new_dispute('dp', attributes)
|
148
|
+
else
|
149
|
+
raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
|
150
|
+
end
|
151
|
+
else
|
152
|
+
# Update existing Stripe object
|
153
|
+
case object
|
154
|
+
when :balance_transaction
|
155
|
+
btxn = assert_existence :balance_transaction, id, @balance_transactions[id]
|
156
|
+
btxn.merge!(attributes)
|
157
|
+
when :dispute
|
158
|
+
dispute = assert_existence :dispute, id, @disputes[id]
|
159
|
+
dispute.merge!(attributes)
|
160
|
+
else
|
161
|
+
raise UnsupportedRequestError.new "Unsupported stripe object `#{object}`"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
id
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def assert_existence(type, id, obj, message=nil)
|
170
|
+
if obj.nil?
|
171
|
+
msg = message || "No such #{type}: #{id}"
|
172
|
+
raise Stripe::InvalidRequestError.new(msg, type.to_s, http_status: 404)
|
173
|
+
end
|
174
|
+
obj
|
175
|
+
end
|
176
|
+
|
177
|
+
def new_id(prefix)
|
178
|
+
# Stripe ids must be strings
|
179
|
+
"#{StripeMock.global_id_prefix}#{prefix}_#{@id_counter += 1}"
|
180
|
+
end
|
181
|
+
|
182
|
+
def new_balance_transaction(prefix, params = {})
|
183
|
+
# balance transaction ids must be strings
|
184
|
+
id = "#{StripeMock.global_id_prefix}#{prefix}_#{@balance_transaction_counter += 1}"
|
185
|
+
amount = params[:amount]
|
186
|
+
unless amount.nil?
|
187
|
+
# Fee calculation
|
188
|
+
calculate_fees(params) unless params[:fee]
|
189
|
+
params[:net] = amount - params[:fee]
|
190
|
+
params[:amount] = amount * @conversion_rate
|
191
|
+
end
|
192
|
+
@balance_transactions[id] = Data.mock_balance_transaction(params.merge(id: id))
|
193
|
+
id
|
194
|
+
end
|
195
|
+
|
196
|
+
def new_dispute(prefix, params = {})
|
197
|
+
id = "#{StripeMock.global_id_prefix}#{prefix}_#{@dispute_counter += 1}"
|
198
|
+
@disputes[id] = Data.mock_dispute(params.merge(id: id))
|
199
|
+
id
|
200
|
+
end
|
201
|
+
|
202
|
+
def symbolize_names(hash)
|
203
|
+
Stripe::Util.symbolize_names(hash)
|
204
|
+
end
|
205
|
+
|
206
|
+
def to_faraday_hash(hash)
|
207
|
+
response = Struct.new(:data)
|
208
|
+
response.new(hash)
|
209
|
+
end
|
210
|
+
|
211
|
+
def calculate_fees(params)
|
212
|
+
application_fee = params[:application_fee] || 0
|
213
|
+
params[:fee] = processing_fee(params[:amount]) + application_fee
|
214
|
+
params[:fee_details] = [
|
215
|
+
{
|
216
|
+
amount: processing_fee(params[:amount]),
|
217
|
+
application: nil,
|
218
|
+
currency: params[:currency] || StripeMock.default_currency,
|
219
|
+
description: "Stripe processing fees",
|
220
|
+
type: "stripe_fee"
|
221
|
+
}
|
222
|
+
]
|
223
|
+
if application_fee
|
224
|
+
params[:fee_details] << {
|
225
|
+
amount: application_fee,
|
226
|
+
currency: params[:currency] || StripeMock.default_currency,
|
227
|
+
description: "Application fee",
|
228
|
+
type: "application_fee"
|
229
|
+
}
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def processing_fee(amount)
|
234
|
+
(30 + (amount.abs * 0.029).ceil) * (amount > 0 ? 1 : -1)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module StripeMock
|
2
|
+
module RequestHandlers
|
3
|
+
module Accounts
|
4
|
+
VALID_START_YEAR = 2009
|
5
|
+
|
6
|
+
def Accounts.included(klass)
|
7
|
+
klass.add_handler 'post /v1/accounts', :new_account
|
8
|
+
klass.add_handler 'get /v1/account', :get_account
|
9
|
+
klass.add_handler 'get /v1/accounts/(.*)', :get_account
|
10
|
+
klass.add_handler 'post /v1/accounts/(.*)', :update_account
|
11
|
+
klass.add_handler 'get /v1/accounts', :list_accounts
|
12
|
+
klass.add_handler 'post /oauth/deauthorize',:deauthorize
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_account(route, method_url, params, headers)
|
16
|
+
params[:id] ||= new_id('acct')
|
17
|
+
route =~ method_url
|
18
|
+
accounts[params[:id]] ||= Data.mock_account(params)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_account(route, method_url, params, headers)
|
22
|
+
route =~ method_url
|
23
|
+
init_account
|
24
|
+
id = $1 || accounts.keys[0]
|
25
|
+
assert_existence :account, id, accounts[id]
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_account(route, method_url, params, headers)
|
29
|
+
route =~ method_url
|
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
|
38
|
+
end
|
39
|
+
|
40
|
+
def list_accounts(route, method_url, params, headers)
|
41
|
+
init_account
|
42
|
+
Data.mock_list_object(accounts.values, params)
|
43
|
+
end
|
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
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def init_account
|
54
|
+
if accounts == {}
|
55
|
+
acc = Data.mock_account
|
56
|
+
accounts[acc[:id]] = acc
|
57
|
+
end
|
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
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|