mangopay-v4 4.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +29 -29
- data/.rspec +3 -3
- data/.rubocop.yml +1 -1
- data/.travis.yml +21 -13
- data/Gemfile +2 -2
- data/LICENSE +20 -20
- data/README.md +379 -379
- data/bin/mangopay +9 -9
- data/lib/mangopay.rb +132 -132
- data/lib/mangopay/api/api.rb +8 -8
- data/lib/mangopay/api/api_methods.rb +160 -136
- data/lib/mangopay/api/auth_token_manager.rb +173 -173
- data/lib/mangopay/api/http_client.rb +324 -324
- data/lib/mangopay/api/service/bank_accounts.rb +145 -145
- data/lib/mangopay/api/service/banking_aliases.rb +83 -0
- data/lib/mangopay/api/service/cards.rb +151 -151
- data/lib/mangopay/api/service/client_wallets.rb +88 -88
- data/lib/mangopay/api/service/clients.rb +67 -67
- data/lib/mangopay/api/service/dispute_documents.rb +157 -157
- data/lib/mangopay/api/service/disputes.rb +186 -186
- data/lib/mangopay/api/service/e_money.rb +63 -41
- data/lib/mangopay/api/service/events.rb +46 -46
- data/lib/mangopay/api/service/hooks.rb +92 -92
- data/lib/mangopay/api/service/kyc_documents.rb +152 -152
- data/lib/mangopay/api/service/mandates.rb +141 -141
- data/lib/mangopay/api/service/oauth_tokens.rb +24 -24
- data/lib/mangopay/api/service/pay_ins.rb +369 -259
- data/lib/mangopay/api/service/pay_outs.rb +53 -53
- data/lib/mangopay/api/service/pre_authorizations.rb +126 -68
- data/lib/mangopay/api/service/refunds.rb +159 -61
- data/lib/mangopay/api/service/reports.rb +150 -150
- data/lib/mangopay/api/service/repudiations.rb +31 -31
- data/lib/mangopay/api/service/responses.rb +101 -101
- data/lib/mangopay/api/service/settlement_transfers.rb +54 -54
- data/lib/mangopay/api/service/transactions.rb +246 -182
- data/lib/mangopay/api/service/transfers.rb +53 -53
- data/lib/mangopay/api/service/ubo_declarations.rb +94 -69
- data/lib/mangopay/api/service/users.rb +162 -162
- data/lib/mangopay/api/service/wallets.rb +98 -98
- data/lib/mangopay/api/uri_provider.rb +32 -34
- data/lib/mangopay/common/json_tag_converter.rb +70 -67
- data/lib/mangopay/common/jsonifier.rb +266 -248
- data/lib/mangopay/common/log_provider.rb +33 -33
- data/lib/mangopay/common/rate_limit_interval.rb +16 -16
- data/lib/mangopay/common/read_only_fields.rb +26 -26
- data/lib/mangopay/common/response_error.rb +61 -61
- data/lib/mangopay/common/sort_direction.rb +14 -14
- data/lib/mangopay/common/sort_field.rb +12 -12
- data/lib/mangopay/common/template_url_options.rb +8 -8
- data/lib/mangopay/configuration.rb +38 -38
- data/lib/mangopay/environment.rb +65 -65
- data/lib/mangopay/model/address.rb +26 -26
- data/lib/mangopay/model/billing.rb +13 -0
- data/lib/mangopay/model/birthplace.rb +15 -0
- data/lib/mangopay/model/declared_ubo.rb +20 -20
- data/lib/mangopay/model/dispute_reason.rb +14 -14
- data/lib/mangopay/model/document_page_consult.rb +14 -14
- data/lib/mangopay/model/e_money.rb +17 -17
- data/lib/mangopay/model/entity/account/bank_account.rb +25 -25
- data/lib/mangopay/model/entity/account/ca_bank_account.rb +26 -26
- data/lib/mangopay/model/entity/account/debited_bank_account.rb +31 -0
- data/lib/mangopay/model/entity/account/gb_bank_account.rb +20 -20
- data/lib/mangopay/model/entity/account/iban_bank_account.rb +20 -20
- data/lib/mangopay/model/entity/account/other_bank_account.rb +23 -23
- data/lib/mangopay/model/entity/account/us_bank_account.rb +23 -23
- data/lib/mangopay/model/entity/banking_alias.rb +27 -0
- data/lib/mangopay/model/entity/card.rb +44 -44
- data/lib/mangopay/model/entity/card_registration.rb +42 -42
- data/lib/mangopay/model/entity/client.rb +65 -62
- data/lib/mangopay/model/entity/client_wallet.rb +22 -22
- data/lib/mangopay/model/entity/dispute.rb +49 -49
- data/lib/mangopay/model/entity/dispute_document.rb +28 -28
- data/lib/mangopay/model/entity/entity_base.rb +17 -17
- data/lib/mangopay/model/entity/hook.rb +25 -25
- data/lib/mangopay/model/entity/kyc_document.rb +27 -27
- data/lib/mangopay/model/entity/mandate.rb +50 -50
- data/lib/mangopay/model/entity/pay_in/apple_pay_direct_pay_in.rb +26 -0
- data/lib/mangopay/model/entity/pay_in/bank_wire_direct_pay_in.rb +24 -21
- data/lib/mangopay/model/entity/pay_in/bank_wire_external_instruction_pay_in.rb +19 -0
- data/lib/mangopay/model/entity/pay_in/card_direct_pay_in.rb +41 -32
- data/lib/mangopay/model/entity/pay_in/card_pre_authorized_pay_in.rb +15 -12
- data/lib/mangopay/model/entity/pay_in/card_web_pay_in.rb +36 -39
- data/lib/mangopay/model/entity/pay_in/direct_debit_direct_pay_in.rb +25 -22
- data/lib/mangopay/model/entity/pay_in/direct_debit_web_pay_in.rb +37 -37
- data/lib/mangopay/model/entity/pay_in/google_pay_direct_pay_in.rb +28 -0
- data/lib/mangopay/model/entity/pay_in/pay_in.rb +18 -15
- data/lib/mangopay/model/entity/pay_in/paypal_web_pay_in.rb +15 -0
- data/lib/mangopay/model/entity/pay_out.rb +21 -21
- data/lib/mangopay/model/entity/pre_authorization.rb +74 -67
- data/lib/mangopay/model/entity/refund.rb +17 -17
- data/lib/mangopay/model/entity/report.rb +50 -50
- data/lib/mangopay/model/entity/repudiation.rb +17 -17
- data/lib/mangopay/model/entity/settlement_transfer.rb +16 -16
- data/lib/mangopay/model/entity/transaction.rb +51 -51
- data/lib/mangopay/model/entity/transfer.rb +12 -12
- data/lib/mangopay/model/entity/ubo.rb +30 -0
- data/lib/mangopay/model/entity/ubo_declaration.rb +29 -31
- data/lib/mangopay/model/entity/user/legal_user.rb +55 -52
- data/lib/mangopay/model/entity/user/natural_user.rb +49 -49
- data/lib/mangopay/model/entity/user/user.rb +17 -17
- data/lib/mangopay/model/entity/wallet.rb +27 -27
- data/lib/mangopay/model/enum/account_type.rb +23 -23
- data/lib/mangopay/model/enum/avs_result.rb +19 -0
- data/lib/mangopay/model/enum/banking_alias_type.rb +12 -0
- data/lib/mangopay/model/enum/business_type.rb +17 -0
- data/lib/mangopay/model/enum/card_status.rb +14 -14
- data/lib/mangopay/model/enum/card_type.rb +32 -32
- data/lib/mangopay/model/enum/card_validity.rb +18 -18
- data/lib/mangopay/model/enum/country_iso.rb +758 -758
- data/lib/mangopay/model/enum/culture_code.rb +43 -43
- data/lib/mangopay/model/enum/currency_iso.rb +551 -551
- data/lib/mangopay/model/enum/declared_ubo_refused_reason_type.rb +15 -15
- data/lib/mangopay/model/enum/declared_ubo_status.rb +17 -17
- data/lib/mangopay/model/enum/deposit_type.rb +14 -14
- data/lib/mangopay/model/enum/direct_debit_type.rb +12 -12
- data/lib/mangopay/model/enum/dispute_doc_refused_reason_type.rb +24 -24
- data/lib/mangopay/model/enum/dispute_document_type.rb +22 -22
- data/lib/mangopay/model/enum/dispute_reason_type.rb +32 -32
- data/lib/mangopay/model/enum/dispute_status.rb +20 -20
- data/lib/mangopay/model/enum/dispute_type.rb +14 -14
- data/lib/mangopay/model/enum/document_status.rb +20 -20
- data/lib/mangopay/model/enum/download_format.rb +10 -10
- data/lib/mangopay/model/enum/event_type.rb +76 -73
- data/lib/mangopay/model/enum/funds_type.rb +14 -14
- data/lib/mangopay/model/enum/hook_status.rb +12 -12
- data/lib/mangopay/model/enum/hook_validity.rb +14 -14
- data/lib/mangopay/model/enum/income_range.rb +20 -20
- data/lib/mangopay/model/enum/kyc_doc_refused_reason_type.rb +36 -36
- data/lib/mangopay/model/enum/kyc_document_type.rb +18 -18
- data/lib/mangopay/model/enum/kyc_level.rb +12 -12
- data/lib/mangopay/model/enum/legal_person_type.rb +14 -14
- data/lib/mangopay/model/enum/mandate_culture_code.rb +22 -22
- data/lib/mangopay/model/enum/mandate_execution_type.rb +10 -10
- data/lib/mangopay/model/enum/mandate_scheme.rb +12 -12
- data/lib/mangopay/model/enum/mandate_status.rb +23 -23
- data/lib/mangopay/model/enum/mandate_type.rb +10 -10
- data/lib/mangopay/model/enum/natural_user_capacity.rb +14 -14
- data/lib/mangopay/model/enum/pay_in_execution_type.rb +17 -17
- data/lib/mangopay/model/enum/pay_in_payment_type.rb +29 -20
- data/lib/mangopay/model/enum/pay_out_payment_type.rb +10 -10
- data/lib/mangopay/model/enum/payment_status.rb +20 -20
- data/lib/mangopay/model/enum/person_type.rb +14 -14
- data/lib/mangopay/model/enum/platform_type.rb +22 -22
- data/lib/mangopay/model/enum/pre_authorization_execution_type.rb +10 -10
- data/lib/mangopay/model/enum/pre_authorization_status.rb +17 -17
- data/lib/mangopay/model/enum/refund_reason_type.rb +20 -20
- data/lib/mangopay/model/enum/report_status.rb +16 -16
- data/lib/mangopay/model/enum/report_type.rb +12 -12
- data/lib/mangopay/model/enum/sector.rb +29 -0
- data/lib/mangopay/model/enum/secure_mode.rb +15 -15
- data/lib/mangopay/model/enum/transaction_nature.rb +16 -16
- data/lib/mangopay/model/enum/transaction_status.rb +14 -14
- data/lib/mangopay/model/enum/transaction_type.rb +14 -14
- data/lib/mangopay/model/enum/ubo_declaration_refused_reason_type.rb +18 -18
- data/lib/mangopay/model/enum/ubo_declaration_status.rb +20 -20
- data/lib/mangopay/model/event.rb +17 -17
- data/lib/mangopay/model/model.rb +214 -193
- data/lib/mangopay/model/money.rb +16 -16
- data/lib/mangopay/model/pay_in_web_extended_view.rb +30 -30
- data/lib/mangopay/model/platform_categorization.rb +15 -0
- data/lib/mangopay/model/refund_reason.rb +14 -14
- data/lib/mangopay/model/report_filter.rb +82 -82
- data/lib/mangopay/model/request/cancel_request.rb +15 -15
- data/lib/mangopay/model/request/complete_registration_request.rb +12 -12
- data/lib/mangopay/model/request/currency_request.rb +12 -12
- data/lib/mangopay/model/request/deactivation_request.rb +9 -9
- data/lib/mangopay/model/request/filter_request.rb +37 -37
- data/lib/mangopay/model/request/submit_document_request.rb +13 -13
- data/lib/mangopay/model/request/submit_ubo_declaration_request.rb +16 -13
- data/lib/mangopay/model/request/upload_file_request.rb +8 -8
- data/lib/mangopay/model/response_replica.rb +26 -26
- data/lib/mangopay/model/security_info.rb +13 -0
- data/lib/mangopay/util/custom_formatter.rb +11 -11
- data/lib/mangopay/util/custom_logger.rb +33 -33
- data/lib/mangopay/util/enum.rb +51 -51
- data/lib/mangopay/util/file_encoder.rb +15 -15
- data/lib/mangopay/util/non_instantiable.rb +5 -5
- data/lib/mangopay/util/storage_strategy.rb +9 -9
- data/lib/mangopay/util/void_logger.rb +5 -5
- data/mangopay-v4.gemspec +32 -0
- data/mangopay.gemspec +32 -32
- data/spec/context/address_context.rb +24 -24
- data/spec/context/bank_account_context.rb +137 -137
- data/spec/context/banking_alias_context.rb +17 -0
- data/spec/context/birthplace_context.rb +17 -0
- data/spec/context/card_context.rb +45 -45
- data/spec/context/client_context.rb +43 -44
- data/spec/context/dispute_context.rb +36 -36
- data/spec/context/dispute_document_context.rb +19 -19
- data/spec/context/hook_context.rb +15 -15
- data/spec/context/kyc_document_context.rb +22 -22
- data/spec/context/mandate_context.rb +26 -26
- data/spec/context/pay_in_context.rb +319 -224
- data/spec/context/pay_out_context.rb +39 -38
- data/spec/context/pre_authorization_context.rb +44 -40
- data/spec/context/refund_context.rb +32 -32
- data/spec/context/report_context.rb +21 -21
- data/spec/context/repudiation_context.rb +18 -18
- data/spec/context/settlement_transfer_context.rb +27 -27
- data/spec/context/transfer_context.rb +50 -50
- data/spec/context/ubo_declaration_context.rb +29 -24
- data/spec/context/user_context.rb +83 -82
- data/spec/context/wallet_context.rb +52 -52
- data/spec/mangopay/bank_accounts_spec.rb +228 -228
- data/spec/mangopay/banking_alias_spec.rb +85 -0
- data/spec/mangopay/cards_spec.rb +133 -134
- data/spec/mangopay/client_wallets_spec.rb +147 -147
- data/spec/mangopay/clients_spec.rb +56 -54
- data/spec/mangopay/configuration_spec.rb +125 -125
- data/spec/mangopay/dispute_documents_spec.rb +173 -173
- data/spec/mangopay/disputes_spec.rb +264 -264
- data/spec/mangopay/e_money_spec.rb +57 -37
- data/spec/mangopay/events_spec.rb +49 -49
- data/spec/mangopay/hooks_spec.rb +70 -70
- data/spec/mangopay/kyc_documents_spec.rb +179 -179
- data/spec/mangopay/mandates_spec.rb +218 -218
- data/spec/mangopay/oauth_tokens_spec.rb +40 -40
- data/spec/mangopay/pay_ins_spec.rb +279 -180
- data/spec/mangopay/pay_outs_spec.rb +38 -38
- data/spec/mangopay/pre_authorizations_spec.rb +134 -57
- data/spec/mangopay/refunds_spec.rb +187 -39
- data/spec/mangopay/reports_spec.rb +118 -120
- data/spec/mangopay/responses_spec.rb +324 -294
- data/spec/mangopay/settlement_transfers_spec.rb +36 -36
- data/spec/mangopay/transactions_spec.rb +347 -232
- data/spec/mangopay/transfers_spec.rb +37 -37
- data/spec/mangopay/ubo_declarations_spec.rb +127 -64
- data/spec/mangopay/users_spec.rb +145 -145
- data/spec/mangopay/wallets_spec.rb +103 -103
- data/spec/spec_helper.rb +72 -72
- data/spec/tmp/MangoPay.AuthorizationToken.FileStore.tmp +6 -0
- data/spec/tmp/mangopay.log.tmp +1201 -0
- metadata +31 -5
@@ -1,173 +1,173 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require_relative '../common/log_provider'
|
3
|
-
|
4
|
-
module MangoApi
|
5
|
-
|
6
|
-
# Manages acquisition and storage of API authorization token.
|
7
|
-
module AuthTokenManager
|
8
|
-
LOG = MangoPay::LogProvider.provide(self)
|
9
|
-
|
10
|
-
class << self
|
11
|
-
|
12
|
-
# Provides a valid authorization token for API calls.
|
13
|
-
def token
|
14
|
-
client_id = MangoPay.configuration.client_id
|
15
|
-
token_valid? && storage.retrieve_for(client_id) || refresh_token
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
# Retrieves authorization token storage object.
|
21
|
-
def storage
|
22
|
-
return @storage if @storage
|
23
|
-
init_storage
|
24
|
-
end
|
25
|
-
|
26
|
-
# Initializes storage strategy for OAuth tokens.
|
27
|
-
# Returns the storage object.
|
28
|
-
def init_storage
|
29
|
-
client_id = MangoPay.configuration.client_id
|
30
|
-
dir = MangoPay.configuration.temp_dir
|
31
|
-
@storage = dir ? FileStorage.new : MemoryStorage.new
|
32
|
-
strategy = @storage.class.name.split('::').last
|
33
|
-
location_if_file = dir ? " at '/#{dir}'" : ''
|
34
|
-
LOG.info 'Using {}{} for {} client\'s OAuth tokens',
|
35
|
-
strategy, location_if_file, client_id
|
36
|
-
@storage
|
37
|
-
end
|
38
|
-
|
39
|
-
# Returns true if the current client's
|
40
|
-
# authorization token is valid
|
41
|
-
def token_valid?
|
42
|
-
!token_invalid?
|
43
|
-
end
|
44
|
-
|
45
|
-
# Returns true if the current client's
|
46
|
-
# stored token is no longer valid.
|
47
|
-
def token_invalid?
|
48
|
-
token = storage.retrieve_for MangoPay.configuration.client_id
|
49
|
-
token.nil? ||
|
50
|
-
token['expire_time'].nil? ||
|
51
|
-
token['expire_time'] <= Time.now ||
|
52
|
-
token['environment_key'] != environment_key
|
53
|
-
end
|
54
|
-
|
55
|
-
# Provides a configuration-specific hash key.
|
56
|
-
def environment_key
|
57
|
-
config = MangoPay.configuration
|
58
|
-
key = [config.root_url, config.client_id, config.
|
59
|
-
.join('|')
|
60
|
-
Digest::MD5.hexdigest(key)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Refreshes the stored authorization token.
|
64
|
-
def refresh_token
|
65
|
-
LOG.info 'Refreshing OAuth token'
|
66
|
-
config = MangoPay.configuration
|
67
|
-
unless config.client_id && config.
|
68
|
-
raise 'You must specify your client ID and
|
69
|
-
end
|
70
|
-
token = MangoApi::OAuthTokens.create(config)
|
71
|
-
append_data token
|
72
|
-
store_token token
|
73
|
-
token
|
74
|
-
end
|
75
|
-
|
76
|
-
# Appends some useful data to the token object.
|
77
|
-
#
|
78
|
-
# @param +token+ the token object
|
79
|
-
def append_data(token)
|
80
|
-
token['expire_time'] = Time.now + token['expires_in'].to_i
|
81
|
-
token['environment_key'] = environment_key
|
82
|
-
end
|
83
|
-
|
84
|
-
# Stores the OAuth token.
|
85
|
-
#
|
86
|
-
# @param +token+ the OAuth token to be stored
|
87
|
-
def store_token(token)
|
88
|
-
client_id = MangoPay.configuration.client_id
|
89
|
-
storage.store_for client_id, token
|
90
|
-
LOG.info 'OAuth token stored in {} for client {}',
|
91
|
-
storage.class.name.split('::').last, client_id
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# Stores client-specific OAuth tokens in-memory.
|
97
|
-
class MemoryStorage
|
98
|
-
def initialize
|
99
|
-
@token = {}
|
100
|
-
end
|
101
|
-
|
102
|
-
# Retrieves a client-specific OAuth token.
|
103
|
-
#
|
104
|
-
# @param +client_id+ ID of the client whose token to retrieve
|
105
|
-
def retrieve_for(client_id)
|
106
|
-
@token[client_id]
|
107
|
-
end
|
108
|
-
|
109
|
-
# Stores a client-specific OAuth token.
|
110
|
-
#
|
111
|
-
# @param +client_id+ ID of the client for which token is being stored
|
112
|
-
# @param +token+ OAuth token for this client
|
113
|
-
def store_for(client_id, token)
|
114
|
-
@token[client_id] = token
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Stores client-specific OAuth tokens in temporary files
|
119
|
-
# in the user-specified directory.
|
120
|
-
class FileStorage
|
121
|
-
require 'yaml'
|
122
|
-
|
123
|
-
def initialize
|
124
|
-
@temp_dir = MangoPay.configuration.temp_dir
|
125
|
-
raise 'Path to temporary folder is not defined' unless @temp_dir
|
126
|
-
end
|
127
|
-
|
128
|
-
# Retrieves a client's OAuth token from its storage file.
|
129
|
-
#
|
130
|
-
# @param +client_id+ ID of the client whose OAuth token to retrieve
|
131
|
-
#
|
132
|
-
# noinspection RubyResolve
|
133
|
-
def retrieve_for(client_id)
|
134
|
-
path = file_path(client_id)
|
135
|
-
return nil unless File.exist? path
|
136
|
-
File.open(path, 'r') do |file|
|
137
|
-
file.flock File::LOCK_SH
|
138
|
-
oauth_data = file.read
|
139
|
-
YAML.load oauth_data || nil
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
# Generates the file path to a certain client's OAuth token file.
|
144
|
-
#
|
145
|
-
# @param +client_id+ ID of the client whose file path to generate
|
146
|
-
def file_path(client_id)
|
147
|
-
File.join(@temp_dir, "mangopay_oauth_token_#{client_id}.tmp")
|
148
|
-
end
|
149
|
-
|
150
|
-
# Stores client-specific OAuth token in its own file.
|
151
|
-
#
|
152
|
-
# @param +client_id+ ID of the client whose token is being stored
|
153
|
-
# @param +token+ OAuth token for this client
|
154
|
-
#
|
155
|
-
# noinspection RubyResolve
|
156
|
-
def store_for(client_id, token)
|
157
|
-
ensure_folder_exists MangoPay.configuration.temp_dir
|
158
|
-
File.open(file_path(client_id), 'w') do |file|
|
159
|
-
file.flock File::LOCK_EX
|
160
|
-
file.truncate(0)
|
161
|
-
file.rewind
|
162
|
-
file.puts YAML.dump(token)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
# Creates a folder at the given path if none exists.
|
167
|
-
#
|
168
|
-
# @param +folder+ path at which folder should exist
|
169
|
-
def ensure_folder_exists(folder)
|
170
|
-
FileUtils.mkdir_p folder unless File.directory?(folder)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
1
|
+
require 'fileutils'
|
2
|
+
require_relative '../common/log_provider'
|
3
|
+
|
4
|
+
module MangoApi
|
5
|
+
|
6
|
+
# Manages acquisition and storage of API authorization token.
|
7
|
+
module AuthTokenManager
|
8
|
+
LOG = MangoPay::LogProvider.provide(self)
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
# Provides a valid authorization token for API calls.
|
13
|
+
def token
|
14
|
+
client_id = MangoPay.configuration.client_id
|
15
|
+
token_valid? && storage.retrieve_for(client_id) || refresh_token
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Retrieves authorization token storage object.
|
21
|
+
def storage
|
22
|
+
return @storage if @storage
|
23
|
+
init_storage
|
24
|
+
end
|
25
|
+
|
26
|
+
# Initializes storage strategy for OAuth tokens.
|
27
|
+
# Returns the storage object.
|
28
|
+
def init_storage
|
29
|
+
client_id = MangoPay.configuration.client_id
|
30
|
+
dir = MangoPay.configuration.temp_dir
|
31
|
+
@storage = dir ? FileStorage.new : MemoryStorage.new
|
32
|
+
strategy = @storage.class.name.split('::').last
|
33
|
+
location_if_file = dir ? " at '/#{dir}'" : ''
|
34
|
+
LOG.info 'Using {}{} for {} client\'s OAuth tokens',
|
35
|
+
strategy, location_if_file, client_id
|
36
|
+
@storage
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns true if the current client's
|
40
|
+
# authorization token is valid
|
41
|
+
def token_valid?
|
42
|
+
!token_invalid?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns true if the current client's
|
46
|
+
# stored token is no longer valid.
|
47
|
+
def token_invalid?
|
48
|
+
token = storage.retrieve_for MangoPay.configuration.client_id
|
49
|
+
token.nil? ||
|
50
|
+
token['expire_time'].nil? ||
|
51
|
+
token['expire_time'] <= Time.now ||
|
52
|
+
token['environment_key'] != environment_key
|
53
|
+
end
|
54
|
+
|
55
|
+
# Provides a configuration-specific hash key.
|
56
|
+
def environment_key
|
57
|
+
config = MangoPay.configuration
|
58
|
+
key = [config.root_url, config.client_id, config.client_apiKey]
|
59
|
+
.join('|')
|
60
|
+
Digest::MD5.hexdigest(key)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Refreshes the stored authorization token.
|
64
|
+
def refresh_token
|
65
|
+
LOG.info 'Refreshing OAuth token'
|
66
|
+
config = MangoPay.configuration
|
67
|
+
unless config.client_id && config.client_apiKey
|
68
|
+
raise 'You must specify your client ID and apiKey'
|
69
|
+
end
|
70
|
+
token = MangoApi::OAuthTokens.create(config)
|
71
|
+
append_data token
|
72
|
+
store_token token
|
73
|
+
token
|
74
|
+
end
|
75
|
+
|
76
|
+
# Appends some useful data to the token object.
|
77
|
+
#
|
78
|
+
# @param +token+ the token object
|
79
|
+
def append_data(token)
|
80
|
+
token['expire_time'] = Time.now + token['expires_in'].to_i
|
81
|
+
token['environment_key'] = environment_key
|
82
|
+
end
|
83
|
+
|
84
|
+
# Stores the OAuth token.
|
85
|
+
#
|
86
|
+
# @param +token+ the OAuth token to be stored
|
87
|
+
def store_token(token)
|
88
|
+
client_id = MangoPay.configuration.client_id
|
89
|
+
storage.store_for client_id, token
|
90
|
+
LOG.info 'OAuth token stored in {} for client {}',
|
91
|
+
storage.class.name.split('::').last, client_id
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Stores client-specific OAuth tokens in-memory.
|
97
|
+
class MemoryStorage
|
98
|
+
def initialize
|
99
|
+
@token = {}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Retrieves a client-specific OAuth token.
|
103
|
+
#
|
104
|
+
# @param +client_id+ ID of the client whose token to retrieve
|
105
|
+
def retrieve_for(client_id)
|
106
|
+
@token[client_id]
|
107
|
+
end
|
108
|
+
|
109
|
+
# Stores a client-specific OAuth token.
|
110
|
+
#
|
111
|
+
# @param +client_id+ ID of the client for which token is being stored
|
112
|
+
# @param +token+ OAuth token for this client
|
113
|
+
def store_for(client_id, token)
|
114
|
+
@token[client_id] = token
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Stores client-specific OAuth tokens in temporary files
|
119
|
+
# in the user-specified directory.
|
120
|
+
class FileStorage
|
121
|
+
require 'yaml'
|
122
|
+
|
123
|
+
def initialize
|
124
|
+
@temp_dir = MangoPay.configuration.temp_dir
|
125
|
+
raise 'Path to temporary folder is not defined' unless @temp_dir
|
126
|
+
end
|
127
|
+
|
128
|
+
# Retrieves a client's OAuth token from its storage file.
|
129
|
+
#
|
130
|
+
# @param +client_id+ ID of the client whose OAuth token to retrieve
|
131
|
+
#
|
132
|
+
# noinspection RubyResolve
|
133
|
+
def retrieve_for(client_id)
|
134
|
+
path = file_path(client_id)
|
135
|
+
return nil unless File.exist? path
|
136
|
+
File.open(path, 'r') do |file|
|
137
|
+
file.flock File::LOCK_SH
|
138
|
+
oauth_data = file.read
|
139
|
+
YAML.load oauth_data || nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Generates the file path to a certain client's OAuth token file.
|
144
|
+
#
|
145
|
+
# @param +client_id+ ID of the client whose file path to generate
|
146
|
+
def file_path(client_id)
|
147
|
+
File.join(@temp_dir, "mangopay_oauth_token_#{client_id}.tmp")
|
148
|
+
end
|
149
|
+
|
150
|
+
# Stores client-specific OAuth token in its own file.
|
151
|
+
#
|
152
|
+
# @param +client_id+ ID of the client whose token is being stored
|
153
|
+
# @param +token+ OAuth token for this client
|
154
|
+
#
|
155
|
+
# noinspection RubyResolve
|
156
|
+
def store_for(client_id, token)
|
157
|
+
ensure_folder_exists MangoPay.configuration.temp_dir
|
158
|
+
File.open(file_path(client_id), 'w') do |file|
|
159
|
+
file.flock File::LOCK_EX
|
160
|
+
file.truncate(0)
|
161
|
+
file.rewind
|
162
|
+
file.puts YAML.dump(token)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Creates a folder at the given path if none exists.
|
167
|
+
#
|
168
|
+
# @param +folder+ path at which folder should exist
|
169
|
+
def ensure_folder_exists(folder)
|
170
|
+
FileUtils.mkdir_p folder unless File.directory?(folder)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -1,325 +1,325 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'json'
|
3
|
-
require_relative '../../mangopay'
|
4
|
-
require_relative '../common/log_provider'
|
5
|
-
|
6
|
-
module MangoApi
|
7
|
-
|
8
|
-
# Handles HTTP communication.
|
9
|
-
module HttpClient
|
10
|
-
LOG = MangoPay::LogProvider.provide(self)
|
11
|
-
|
12
|
-
class << self
|
13
|
-
|
14
|
-
# Launches a self-configuring POST request,
|
15
|
-
# with headers required by the API.
|
16
|
-
#
|
17
|
-
# @param +uri+ [String] request URI
|
18
|
-
# @param +entity+ [Object] object to be JSON-serialized and sent as body
|
19
|
-
# Must include Jsonifier.
|
20
|
-
# @param +id_key+ [String] idempotency key for future response replication
|
21
|
-
# @return [Hash] hashed request response JSON body
|
22
|
-
def post(uri, entity, id_key = nil)
|
23
|
-
request proc { |ury, &block| post_raw(ury, &block) },
|
24
|
-
uri,
|
25
|
-
entity,
|
26
|
-
nil,
|
27
|
-
id_key
|
28
|
-
end
|
29
|
-
|
30
|
-
# Launches a fully customizable POST request.
|
31
|
-
# Expects to be given a block to which it yields the
|
32
|
-
# request object before execution to be configured.
|
33
|
-
#
|
34
|
-
# @param +uri+ [String] request URI
|
35
|
-
# @return [Hash] hashed request response JSON body
|
36
|
-
def post_raw(uri, &block)
|
37
|
-
request_raw Net::HTTP::Post,
|
38
|
-
uri,
|
39
|
-
&block
|
40
|
-
end
|
41
|
-
|
42
|
-
# Launches a self-configuring PUT request,
|
43
|
-
# with headers required by the API.
|
44
|
-
#
|
45
|
-
# @param +uri+ [URI] request URI
|
46
|
-
# @param +entity+ [Object] object to be JSON-serialized and sent as body
|
47
|
-
# Must include Jsonifier.
|
48
|
-
# @return [Hash] hashed request response JSON body
|
49
|
-
def put(uri, entity = nil)
|
50
|
-
request proc { |ury, &block| put_raw(ury, &block) },
|
51
|
-
uri,
|
52
|
-
entity
|
53
|
-
end
|
54
|
-
|
55
|
-
# Launches a fully customizable PUT request.
|
56
|
-
# Expects to be given a block to which it yields the
|
57
|
-
# request object before execution to be configured.
|
58
|
-
#
|
59
|
-
# @param +uri+ [String] request URI
|
60
|
-
# @return [Hash] hashed request response JSON body
|
61
|
-
def put_raw(uri, &block)
|
62
|
-
request_raw Net::HTTP::Put,
|
63
|
-
uri,
|
64
|
-
&block
|
65
|
-
end
|
66
|
-
|
67
|
-
# Launches a self-configuring GET request,
|
68
|
-
# with headers required by the API.
|
69
|
-
# Applies filters if provided.
|
70
|
-
#
|
71
|
-
# @param +uri+ [URI] request URI
|
72
|
-
# @param +filters+ [FilterRequest] response entity filtering object
|
73
|
-
# @return [Hash] hashed request response JSON body
|
74
|
-
def get(uri, filter_request = nil)
|
75
|
-
request proc { |ury, &block| get_raw(ury, &block) },
|
76
|
-
uri,
|
77
|
-
nil,
|
78
|
-
filter_request
|
79
|
-
end
|
80
|
-
|
81
|
-
# Launches a fully customizable GET request.
|
82
|
-
# Expects to be given a block to which it yields the
|
83
|
-
# request object before execution to be configured.
|
84
|
-
#
|
85
|
-
# @param +uri+ [URI] request URI
|
86
|
-
# @return [Hash] hashed request response JSON body
|
87
|
-
def get_raw(uri, &block)
|
88
|
-
request_raw Net::HTTP::Get,
|
89
|
-
uri,
|
90
|
-
&block
|
91
|
-
end
|
92
|
-
|
93
|
-
# Provides a hash containing necessary headers for API calls.
|
94
|
-
def api_headers
|
95
|
-
initialize_headers unless @default_headers
|
96
|
-
@default_headers
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
# Launches a self-configuring generic request,
|
102
|
-
# with headers required by the API.
|
103
|
-
# Applies filters and idempotency key header if provided.
|
104
|
-
# Sends JSON serialization of an object as body if provided.
|
105
|
-
#
|
106
|
-
# @param +http_client_method+ [Proc] proc representing the HttpClient
|
107
|
-
# method to be called for this particular request
|
108
|
-
# @param +uri+ [URI] request URI
|
109
|
-
# @param +entity+ [Object] object to be JSON-serialized and sent as body
|
110
|
-
# Must include Jsonifier.
|
111
|
-
# @param +filter+ [FilterRequest] response entity filtering object
|
112
|
-
# @param +id_key+ [String] idempotency key for future response replication
|
113
|
-
# @return [Hash] hashed request response JSON body
|
114
|
-
def request(http_client_method,
|
115
|
-
uri,
|
116
|
-
entity = nil,
|
117
|
-
filter = nil,
|
118
|
-
id_key = nil)
|
119
|
-
validate entity if entity
|
120
|
-
apply_filter(uri, filter) if filter
|
121
|
-
http_client_method.call(uri) do |request|
|
122
|
-
api_headers.each { |k, v| request.add_field(k, v) }
|
123
|
-
request.add_field('Idempotency-Key', id_key) if id_key
|
124
|
-
request.body = entity.jsonify! if entity
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
# Launches a fully customizable generic request.
|
129
|
-
# Expects to be given a block to which it yields the
|
130
|
-
# request object before execution to be configured.
|
131
|
-
#
|
132
|
-
# @param +http_method+ [HTTPRequest] method type class
|
133
|
-
# @param +uri+ [URI] request URI
|
134
|
-
# @return [Hash] hashed request response JSON body
|
135
|
-
def request_raw(http_method, uri)
|
136
|
-
http_timeout = MangoPay.configuration.http_timeout
|
137
|
-
response = Net::HTTP.start(uri.host,
|
138
|
-
uri.port,
|
139
|
-
use_ssl: true,
|
140
|
-
read_timeout: http_timeout) do |http|
|
141
|
-
request = http_method.new(uri.request_uri)
|
142
|
-
yield request if block_given?
|
143
|
-
log_request request
|
144
|
-
http.request request
|
145
|
-
end
|
146
|
-
handle response
|
147
|
-
end
|
148
|
-
|
149
|
-
# Validates a provided object as being serializable
|
150
|
-
# into an API-acceptable JSON format. Raises if validation fails.
|
151
|
-
#
|
152
|
-
# @param +entity+ [Object] object meant to be serialized and sent as body
|
153
|
-
def validate(entity)
|
154
|
-
included_modules = entity.singleton_class.included_modules
|
155
|
-
raise 'Request body entity must include Jsonifier module'\
|
156
|
-
unless included_modules.include? MangoPay::Jsonifier
|
157
|
-
end
|
158
|
-
|
159
|
-
# Applies provided filters as path params
|
160
|
-
# to the provided URI.
|
161
|
-
#
|
162
|
-
# @param +uri+ [URI] URI upon which to apply filters
|
163
|
-
# @param +filter+ [FilterRequest] the filtering object
|
164
|
-
def apply_filter(uri, filter)
|
165
|
-
query = []
|
166
|
-
paging = paging_filter(filter.page, filter.per_page)
|
167
|
-
sorting = sorting_filter(filter.sort_field, filter.sort_direction)
|
168
|
-
others = other_filters(filter)
|
169
|
-
query << paging if paging
|
170
|
-
query << sorting if sorting
|
171
|
-
query << others if others
|
172
|
-
uri.query = query.join('&')
|
173
|
-
end
|
174
|
-
|
175
|
-
# Builds query string corresponding to paging filter components.
|
176
|
-
#
|
177
|
-
# @param +page+ [Integer] number of page of results
|
178
|
-
# @param +per_page+ [Integer] number of results per page
|
179
|
-
# @return [String] query string corresponding to provided values
|
180
|
-
def paging_filter(page, per_page)
|
181
|
-
return nil unless page && per_page
|
182
|
-
paging_filter = {}
|
183
|
-
paging_filter['Page'] = page || 1
|
184
|
-
paging_filter['Per_Page'] = per_page
|
185
|
-
URI.encode_www_form paging_filter
|
186
|
-
end
|
187
|
-
|
188
|
-
# Builds query string corresponding to sorting filter components.
|
189
|
-
#
|
190
|
-
# @param +field+ [SortField] field by which to sort results
|
191
|
-
# @param +direction+ [SortDirection] direction to sort results in
|
192
|
-
# @return [String] query string corresponding to provided values
|
193
|
-
def sorting_filter(field, direction)
|
194
|
-
return nil unless field && direction
|
195
|
-
sort_param = field.to_s + ':' + direction.to_s
|
196
|
-
sorting_filter = { Sort: sort_param }
|
197
|
-
URI.encode_www_form sorting_filter
|
198
|
-
end
|
199
|
-
|
200
|
-
# Builds query string corresponding to all other filter parameters except
|
201
|
-
# the ones for paging and sorting
|
202
|
-
#
|
203
|
-
# @param +filter+ [FilterRequest] the filtering object
|
204
|
-
# @return [String] query string corresponding to provided values
|
205
|
-
def other_filters(filter)
|
206
|
-
filters = {}
|
207
|
-
filters['BeforeDate'] = filter.before_date if filter.before_date
|
208
|
-
filters['AfterDate'] = filter.after_date if filter.after_date
|
209
|
-
filters['Status'] = filter.status.to_s if filter.status
|
210
|
-
filters['Nature'] = filter.nature.to_s if filter.nature
|
211
|
-
filters['Type'] = filter.type.to_s if filter.type
|
212
|
-
filters['EventType'] = filter.event_type.to_s if filter.event_type
|
213
|
-
return nil if filters.empty?
|
214
|
-
URI.encode_www_form filters
|
215
|
-
end
|
216
|
-
|
217
|
-
# Handles responses from the API.
|
218
|
-
def handle(response)
|
219
|
-
update_rate_limits response
|
220
|
-
log_response response
|
221
|
-
code = response.code.to_i
|
222
|
-
body_object = code == 204 ? nil : objectify(response.body)
|
223
|
-
unless (200..299).cover? code
|
224
|
-
raise MangoPay::ResponseError.new response.uri,
|
225
|
-
response.code,
|
226
|
-
body_object
|
227
|
-
end
|
228
|
-
body_object
|
229
|
-
end
|
230
|
-
|
231
|
-
# Turns response body into a Hash object if it is JSON-standard.
|
232
|
-
def objectify(response_body)
|
233
|
-
JSON.parse(response_body)
|
234
|
-
rescue
|
235
|
-
response_body
|
236
|
-
end
|
237
|
-
|
238
|
-
# Handles external responses (from raw HTTP calls).
|
239
|
-
def handle_raw(response)
|
240
|
-
code = response.code.to_i
|
241
|
-
unless (200..299).cover? code
|
242
|
-
raise "#{code} #{response.message}: #{response.body}"
|
243
|
-
end
|
244
|
-
response.body
|
245
|
-
end
|
246
|
-
|
247
|
-
# Updates the current environment's rate limit
|
248
|
-
# data from response headers.
|
249
|
-
#
|
250
|
-
# @param +response+ response object from API
|
251
|
-
def update_rate_limits(response)
|
252
|
-
rate_limits = {}
|
253
|
-
response.each_header do |k, v|
|
254
|
-
next unless k.include? 'x-ratelimit'
|
255
|
-
rate_limits[k] = v.split(', ')
|
256
|
-
end
|
257
|
-
MangoPay.environment.update_rate_limits rate_limits if rate_limits.any?
|
258
|
-
end
|
259
|
-
|
260
|
-
# Logs request data.
|
261
|
-
#
|
262
|
-
# @param +request+ the request that should be logged
|
263
|
-
def log_request(request)
|
264
|
-
LOG.debug 'Launching request: {}', request.method
|
265
|
-
LOG.debug 'Full URL: {}{}',
|
266
|
-
MangoPay.configuration.root_url, request.path
|
267
|
-
request.each_header do |k, v|
|
268
|
-
LOG.debug 'Request header: {} -> {}', k, v
|
269
|
-
end
|
270
|
-
LOG.debug 'Request body: {}', request.body if request.body
|
271
|
-
end
|
272
|
-
|
273
|
-
# Logs response data.
|
274
|
-
#
|
275
|
-
# @param +response+ the response that should be logged
|
276
|
-
def log_response(response)
|
277
|
-
LOG.debug 'Received response: {} {}', response.code, response.message
|
278
|
-
response.header.each do |k, v|
|
279
|
-
LOG.debug 'Response header: {} -> {}', k, v
|
280
|
-
end
|
281
|
-
LOG.debug 'Response body: {}', response.body if response.body
|
282
|
-
end
|
283
|
-
|
284
|
-
# Initializes the default headers necessary for API calls.
|
285
|
-
#
|
286
|
-
# noinspection RubyStringKeysInHashInspection
|
287
|
-
def initialize_headers
|
288
|
-
auth_token = MangoApi::AuthTokenManager.token
|
289
|
-
@default_headers = {
|
290
|
-
'User-Agent' => "MANGOPAY V2 RubyBindings/#{MangoPay::VERSION}",
|
291
|
-
'Authorization' => "#{auth_token['token_type']} "\
|
292
|
-
"#{auth_token['access_token']}",
|
293
|
-
'Content-Type' => 'application/json'
|
294
|
-
}
|
295
|
-
append_user_agent
|
296
|
-
end
|
297
|
-
|
298
|
-
def append_user_agent
|
299
|
-
@default_headers.update('x_mangopay_client_user_agent' =>
|
300
|
-
JSON.dump(user_agent))
|
301
|
-
rescue => e
|
302
|
-
@default_headers.update('x_mangopay_client_raw_user_agent' =>
|
303
|
-
user_agent.inspect,
|
304
|
-
error: "#{e} (#{e.class})")
|
305
|
-
end
|
306
|
-
|
307
|
-
def user_agent
|
308
|
-
{
|
309
|
-
bindings_version: MangoPay::VERSION,
|
310
|
-
lang: 'ruby',
|
311
|
-
lang_version: "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} "\
|
312
|
-
"(#{RUBY_RELEASE_DATE})",
|
313
|
-
platform: RUBY_PLATFORM,
|
314
|
-
uname: uname
|
315
|
-
}
|
316
|
-
end
|
317
|
-
|
318
|
-
def uname
|
319
|
-
`uname -a 2>/dev/null`.strip if RUBY_PLATFORM =~ /linux|darwin/i
|
320
|
-
rescue Errno::ENOMEM
|
321
|
-
'uname lookup failed'
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require_relative '../../mangopay'
|
4
|
+
require_relative '../common/log_provider'
|
5
|
+
|
6
|
+
module MangoApi
|
7
|
+
|
8
|
+
# Handles HTTP communication.
|
9
|
+
module HttpClient
|
10
|
+
LOG = MangoPay::LogProvider.provide(self)
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Launches a self-configuring POST request,
|
15
|
+
# with headers required by the API.
|
16
|
+
#
|
17
|
+
# @param +uri+ [String] request URI
|
18
|
+
# @param +entity+ [Object] object to be JSON-serialized and sent as body
|
19
|
+
# Must include Jsonifier.
|
20
|
+
# @param +id_key+ [String] idempotency key for future response replication
|
21
|
+
# @return [Hash] hashed request response JSON body
|
22
|
+
def post(uri, entity, id_key = nil)
|
23
|
+
request proc { |ury, &block| post_raw(ury, &block) },
|
24
|
+
uri,
|
25
|
+
entity,
|
26
|
+
nil,
|
27
|
+
id_key
|
28
|
+
end
|
29
|
+
|
30
|
+
# Launches a fully customizable POST request.
|
31
|
+
# Expects to be given a block to which it yields the
|
32
|
+
# request object before execution to be configured.
|
33
|
+
#
|
34
|
+
# @param +uri+ [String] request URI
|
35
|
+
# @return [Hash] hashed request response JSON body
|
36
|
+
def post_raw(uri, &block)
|
37
|
+
request_raw Net::HTTP::Post,
|
38
|
+
uri,
|
39
|
+
&block
|
40
|
+
end
|
41
|
+
|
42
|
+
# Launches a self-configuring PUT request,
|
43
|
+
# with headers required by the API.
|
44
|
+
#
|
45
|
+
# @param +uri+ [URI] request URI
|
46
|
+
# @param +entity+ [Object] object to be JSON-serialized and sent as body
|
47
|
+
# Must include Jsonifier.
|
48
|
+
# @return [Hash] hashed request response JSON body
|
49
|
+
def put(uri, entity = nil)
|
50
|
+
request proc { |ury, &block| put_raw(ury, &block) },
|
51
|
+
uri,
|
52
|
+
entity
|
53
|
+
end
|
54
|
+
|
55
|
+
# Launches a fully customizable PUT request.
|
56
|
+
# Expects to be given a block to which it yields the
|
57
|
+
# request object before execution to be configured.
|
58
|
+
#
|
59
|
+
# @param +uri+ [String] request URI
|
60
|
+
# @return [Hash] hashed request response JSON body
|
61
|
+
def put_raw(uri, &block)
|
62
|
+
request_raw Net::HTTP::Put,
|
63
|
+
uri,
|
64
|
+
&block
|
65
|
+
end
|
66
|
+
|
67
|
+
# Launches a self-configuring GET request,
|
68
|
+
# with headers required by the API.
|
69
|
+
# Applies filters if provided.
|
70
|
+
#
|
71
|
+
# @param +uri+ [URI] request URI
|
72
|
+
# @param +filters+ [FilterRequest] response entity filtering object
|
73
|
+
# @return [Hash] hashed request response JSON body
|
74
|
+
def get(uri, filter_request = nil)
|
75
|
+
request proc { |ury, &block| get_raw(ury, &block) },
|
76
|
+
uri,
|
77
|
+
nil,
|
78
|
+
filter_request
|
79
|
+
end
|
80
|
+
|
81
|
+
# Launches a fully customizable GET request.
|
82
|
+
# Expects to be given a block to which it yields the
|
83
|
+
# request object before execution to be configured.
|
84
|
+
#
|
85
|
+
# @param +uri+ [URI] request URI
|
86
|
+
# @return [Hash] hashed request response JSON body
|
87
|
+
def get_raw(uri, &block)
|
88
|
+
request_raw Net::HTTP::Get,
|
89
|
+
uri,
|
90
|
+
&block
|
91
|
+
end
|
92
|
+
|
93
|
+
# Provides a hash containing necessary headers for API calls.
|
94
|
+
def api_headers
|
95
|
+
initialize_headers unless @default_headers
|
96
|
+
@default_headers
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Launches a self-configuring generic request,
|
102
|
+
# with headers required by the API.
|
103
|
+
# Applies filters and idempotency key header if provided.
|
104
|
+
# Sends JSON serialization of an object as body if provided.
|
105
|
+
#
|
106
|
+
# @param +http_client_method+ [Proc] proc representing the HttpClient
|
107
|
+
# method to be called for this particular request
|
108
|
+
# @param +uri+ [URI] request URI
|
109
|
+
# @param +entity+ [Object] object to be JSON-serialized and sent as body
|
110
|
+
# Must include Jsonifier.
|
111
|
+
# @param +filter+ [FilterRequest] response entity filtering object
|
112
|
+
# @param +id_key+ [String] idempotency key for future response replication
|
113
|
+
# @return [Hash] hashed request response JSON body
|
114
|
+
def request(http_client_method,
|
115
|
+
uri,
|
116
|
+
entity = nil,
|
117
|
+
filter = nil,
|
118
|
+
id_key = nil)
|
119
|
+
validate entity if entity
|
120
|
+
apply_filter(uri, filter) if filter
|
121
|
+
http_client_method.call(uri) do |request|
|
122
|
+
api_headers.each { |k, v| request.add_field(k, v) }
|
123
|
+
request.add_field('Idempotency-Key', id_key) if id_key
|
124
|
+
request.body = entity.jsonify! if entity
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Launches a fully customizable generic request.
|
129
|
+
# Expects to be given a block to which it yields the
|
130
|
+
# request object before execution to be configured.
|
131
|
+
#
|
132
|
+
# @param +http_method+ [HTTPRequest] method type class
|
133
|
+
# @param +uri+ [URI] request URI
|
134
|
+
# @return [Hash] hashed request response JSON body
|
135
|
+
def request_raw(http_method, uri)
|
136
|
+
http_timeout = MangoPay.configuration.http_timeout
|
137
|
+
response = Net::HTTP.start(uri.host,
|
138
|
+
uri.port,
|
139
|
+
use_ssl: true,
|
140
|
+
read_timeout: http_timeout) do |http|
|
141
|
+
request = http_method.new(uri.request_uri)
|
142
|
+
yield request if block_given?
|
143
|
+
log_request request
|
144
|
+
http.request request
|
145
|
+
end
|
146
|
+
handle response
|
147
|
+
end
|
148
|
+
|
149
|
+
# Validates a provided object as being serializable
|
150
|
+
# into an API-acceptable JSON format. Raises if validation fails.
|
151
|
+
#
|
152
|
+
# @param +entity+ [Object] object meant to be serialized and sent as body
|
153
|
+
def validate(entity)
|
154
|
+
included_modules = entity.singleton_class.included_modules
|
155
|
+
raise 'Request body entity must include Jsonifier module'\
|
156
|
+
unless included_modules.include? MangoPay::Jsonifier
|
157
|
+
end
|
158
|
+
|
159
|
+
# Applies provided filters as path params
|
160
|
+
# to the provided URI.
|
161
|
+
#
|
162
|
+
# @param +uri+ [URI] URI upon which to apply filters
|
163
|
+
# @param +filter+ [FilterRequest] the filtering object
|
164
|
+
def apply_filter(uri, filter)
|
165
|
+
query = []
|
166
|
+
paging = paging_filter(filter.page, filter.per_page)
|
167
|
+
sorting = sorting_filter(filter.sort_field, filter.sort_direction)
|
168
|
+
others = other_filters(filter)
|
169
|
+
query << paging if paging
|
170
|
+
query << sorting if sorting
|
171
|
+
query << others if others
|
172
|
+
uri.query = query.join('&')
|
173
|
+
end
|
174
|
+
|
175
|
+
# Builds query string corresponding to paging filter components.
|
176
|
+
#
|
177
|
+
# @param +page+ [Integer] number of page of results
|
178
|
+
# @param +per_page+ [Integer] number of results per page
|
179
|
+
# @return [String] query string corresponding to provided values
|
180
|
+
def paging_filter(page, per_page)
|
181
|
+
return nil unless page && per_page
|
182
|
+
paging_filter = {}
|
183
|
+
paging_filter['Page'] = page || 1
|
184
|
+
paging_filter['Per_Page'] = per_page
|
185
|
+
URI.encode_www_form paging_filter
|
186
|
+
end
|
187
|
+
|
188
|
+
# Builds query string corresponding to sorting filter components.
|
189
|
+
#
|
190
|
+
# @param +field+ [SortField] field by which to sort results
|
191
|
+
# @param +direction+ [SortDirection] direction to sort results in
|
192
|
+
# @return [String] query string corresponding to provided values
|
193
|
+
def sorting_filter(field, direction)
|
194
|
+
return nil unless field && direction
|
195
|
+
sort_param = field.to_s + ':' + direction.to_s
|
196
|
+
sorting_filter = { Sort: sort_param }
|
197
|
+
URI.encode_www_form sorting_filter
|
198
|
+
end
|
199
|
+
|
200
|
+
# Builds query string corresponding to all other filter parameters except
|
201
|
+
# the ones for paging and sorting
|
202
|
+
#
|
203
|
+
# @param +filter+ [FilterRequest] the filtering object
|
204
|
+
# @return [String] query string corresponding to provided values
|
205
|
+
def other_filters(filter)
|
206
|
+
filters = {}
|
207
|
+
filters['BeforeDate'] = filter.before_date if filter.before_date
|
208
|
+
filters['AfterDate'] = filter.after_date if filter.after_date
|
209
|
+
filters['Status'] = filter.status.to_s if filter.status
|
210
|
+
filters['Nature'] = filter.nature.to_s if filter.nature
|
211
|
+
filters['Type'] = filter.type.to_s if filter.type
|
212
|
+
filters['EventType'] = filter.event_type.to_s if filter.event_type
|
213
|
+
return nil if filters.empty?
|
214
|
+
URI.encode_www_form filters
|
215
|
+
end
|
216
|
+
|
217
|
+
# Handles responses from the API.
|
218
|
+
def handle(response)
|
219
|
+
update_rate_limits response
|
220
|
+
log_response response
|
221
|
+
code = response.code.to_i
|
222
|
+
body_object = code == 204 ? nil : objectify(response.body)
|
223
|
+
unless (200..299).cover? code
|
224
|
+
raise MangoPay::ResponseError.new response.uri,
|
225
|
+
response.code,
|
226
|
+
body_object
|
227
|
+
end
|
228
|
+
body_object
|
229
|
+
end
|
230
|
+
|
231
|
+
# Turns response body into a Hash object if it is JSON-standard.
|
232
|
+
def objectify(response_body)
|
233
|
+
JSON.parse(response_body)
|
234
|
+
rescue
|
235
|
+
response_body
|
236
|
+
end
|
237
|
+
|
238
|
+
# Handles external responses (from raw HTTP calls).
|
239
|
+
def handle_raw(response)
|
240
|
+
code = response.code.to_i
|
241
|
+
unless (200..299).cover? code
|
242
|
+
raise "#{code} #{response.message}: #{response.body}"
|
243
|
+
end
|
244
|
+
response.body
|
245
|
+
end
|
246
|
+
|
247
|
+
# Updates the current environment's rate limit
|
248
|
+
# data from response headers.
|
249
|
+
#
|
250
|
+
# @param +response+ response object from API
|
251
|
+
def update_rate_limits(response)
|
252
|
+
rate_limits = {}
|
253
|
+
response.each_header do |k, v|
|
254
|
+
next unless k.include? 'x-ratelimit'
|
255
|
+
rate_limits[k] = v.split(', ')
|
256
|
+
end
|
257
|
+
MangoPay.environment.update_rate_limits rate_limits if rate_limits.any?
|
258
|
+
end
|
259
|
+
|
260
|
+
# Logs request data.
|
261
|
+
#
|
262
|
+
# @param +request+ the request that should be logged
|
263
|
+
def log_request(request)
|
264
|
+
LOG.debug 'Launching request: {}', request.method
|
265
|
+
LOG.debug 'Full URL: {}{}',
|
266
|
+
MangoPay.configuration.root_url, request.path
|
267
|
+
request.each_header do |k, v|
|
268
|
+
LOG.debug 'Request header: {} -> {}', k, v
|
269
|
+
end
|
270
|
+
LOG.debug 'Request body: {}', request.body if request.body
|
271
|
+
end
|
272
|
+
|
273
|
+
# Logs response data.
|
274
|
+
#
|
275
|
+
# @param +response+ the response that should be logged
|
276
|
+
def log_response(response)
|
277
|
+
LOG.debug 'Received response: {} {}', response.code, response.message
|
278
|
+
response.header.each do |k, v|
|
279
|
+
LOG.debug 'Response header: {} -> {}', k, v
|
280
|
+
end
|
281
|
+
LOG.debug 'Response body: {}', response.body if response.body
|
282
|
+
end
|
283
|
+
|
284
|
+
# Initializes the default headers necessary for API calls.
|
285
|
+
#
|
286
|
+
# noinspection RubyStringKeysInHashInspection
|
287
|
+
def initialize_headers
|
288
|
+
auth_token = MangoApi::AuthTokenManager.token
|
289
|
+
@default_headers = {
|
290
|
+
'User-Agent' => "MANGOPAY V2 RubyBindings/#{MangoPay::VERSION}",
|
291
|
+
'Authorization' => "#{auth_token['token_type']} "\
|
292
|
+
"#{auth_token['access_token']}",
|
293
|
+
'Content-Type' => 'application/json'
|
294
|
+
}
|
295
|
+
append_user_agent
|
296
|
+
end
|
297
|
+
|
298
|
+
def append_user_agent
|
299
|
+
@default_headers.update('x_mangopay_client_user_agent' =>
|
300
|
+
JSON.dump(user_agent))
|
301
|
+
rescue => e
|
302
|
+
@default_headers.update('x_mangopay_client_raw_user_agent' =>
|
303
|
+
user_agent.inspect,
|
304
|
+
error: "#{e} (#{e.class})")
|
305
|
+
end
|
306
|
+
|
307
|
+
def user_agent
|
308
|
+
{
|
309
|
+
bindings_version: MangoPay::VERSION,
|
310
|
+
lang: 'ruby',
|
311
|
+
lang_version: "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} "\
|
312
|
+
"(#{RUBY_RELEASE_DATE})",
|
313
|
+
platform: RUBY_PLATFORM,
|
314
|
+
uname: uname
|
315
|
+
}
|
316
|
+
end
|
317
|
+
|
318
|
+
def uname
|
319
|
+
`uname -a 2>/dev/null`.strip if RUBY_PLATFORM =~ /linux|darwin/i
|
320
|
+
rescue Errno::ENOMEM
|
321
|
+
'uname lookup failed'
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
325
|
end
|