activemerchant 1.126.0 → 1.129.0
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/CHANGELOG +241 -0
- data/lib/active_merchant/billing/check.rb +40 -8
- data/lib/active_merchant/billing/credit_card.rb +28 -1
- data/lib/active_merchant/billing/credit_card_methods.rb +79 -23
- data/lib/active_merchant/billing/gateways/adyen.rb +67 -8
- data/lib/active_merchant/billing/gateways/airwallex.rb +40 -11
- data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -4
- data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -1
- data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +56 -16
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +64 -17
- data/lib/active_merchant/billing/gateways/card_connect.rb +27 -9
- data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +228 -57
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
- data/lib/active_merchant/billing/gateways/credorax.rb +47 -27
- data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +100 -26
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
- data/lib/active_merchant/billing/gateways/d_local.rb +44 -5
- data/lib/active_merchant/billing/gateways/decidir.rb +15 -4
- data/lib/active_merchant/billing/gateways/ebanx.rb +36 -24
- data/lib/active_merchant/billing/gateways/element.rb +21 -1
- data/lib/active_merchant/billing/gateways/global_collect.rb +73 -22
- data/lib/active_merchant/billing/gateways/ipg.rb +13 -8
- data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
- data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
- data/lib/active_merchant/billing/gateways/litle.rb +25 -5
- data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
- data/lib/active_merchant/billing/gateways/monei.rb +2 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +20 -5
- data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
- data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
- data/lib/active_merchant/billing/gateways/orbital.rb +43 -22
- data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
- data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
- data/lib/active_merchant/billing/gateways/paymentez.rb +18 -6
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +22 -14
- data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -0
- data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
- data/lib/active_merchant/billing/gateways/priority.rb +29 -6
- data/lib/active_merchant/billing/gateways/rapyd.rb +110 -49
- data/lib/active_merchant/billing/gateways/reach.rb +277 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +9 -5
- data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
- data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
- data/lib/active_merchant/billing/gateways/simetrik.rb +28 -22
- data/lib/active_merchant/billing/gateways/stripe.rb +21 -1
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +62 -22
- data/lib/active_merchant/billing/gateways/tns.rb +2 -5
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
- data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +1 -1
- data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
- data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
- data/lib/active_merchant/billing/gateways/worldpay.rb +117 -9
- data/lib/active_merchant/billing/response.rb +15 -1
- data/lib/active_merchant/connection.rb +0 -2
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/errors.rb +4 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +24 -3
@@ -0,0 +1,342 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class Shift4Gateway < Gateway
|
4
|
+
self.test_url = 'https://utgapi.shift4test.com/api/rest/v1/'
|
5
|
+
self.live_url = 'https://utg.shift4api.net/api/rest/v1/'
|
6
|
+
|
7
|
+
self.supported_countries = %w(US CA CU HT DO PR JM TT GP MQ BS BB LC CW AW VC VI GD AG DM KY KN SX TC MF VG BQ AI BL MS)
|
8
|
+
self.default_currency = 'USD'
|
9
|
+
self.supported_cardtypes = %i[visa master american_express discover]
|
10
|
+
|
11
|
+
self.homepage_url = 'https://shift4.com'
|
12
|
+
self.display_name = 'Shift4'
|
13
|
+
|
14
|
+
RECURRING_TYPE_TRANSACTIONS = %w(recurring installment)
|
15
|
+
TRANSACTIONS_WITHOUT_RESPONSE_CODE = %w(accesstoken add)
|
16
|
+
SUCCESS_TRANSACTION_STATUS = %w(A)
|
17
|
+
DISALLOWED_ENTRY_MODE_ACTIONS = %w(capture refund add verify)
|
18
|
+
URL_POSTFIX_MAPPING = {
|
19
|
+
'accesstoken' => 'credentials',
|
20
|
+
'add' => 'tokens',
|
21
|
+
'verify' => 'cards'
|
22
|
+
}
|
23
|
+
STANDARD_ERROR_CODE_MAPPING = {
|
24
|
+
'incorrect_number' => STANDARD_ERROR_CODE[:incorrect_number],
|
25
|
+
'invalid_number' => STANDARD_ERROR_CODE[:invalid_number],
|
26
|
+
'invalid_expiry_month' => STANDARD_ERROR_CODE[:invalid_expiry_date],
|
27
|
+
'invalid_expiry_year' => STANDARD_ERROR_CODE[:invalid_expiry_date],
|
28
|
+
'invalid_cvc' => STANDARD_ERROR_CODE[:invalid_cvc],
|
29
|
+
'expired_card' => STANDARD_ERROR_CODE[:expired_card],
|
30
|
+
'insufficient_funds' => STANDARD_ERROR_CODE[:card_declined],
|
31
|
+
'incorrect_cvc' => STANDARD_ERROR_CODE[:incorrect_cvc],
|
32
|
+
'incorrect_zip' => STANDARD_ERROR_CODE[:incorrect_zip],
|
33
|
+
'card_declined' => STANDARD_ERROR_CODE[:card_declined],
|
34
|
+
'processing_error' => STANDARD_ERROR_CODE[:processing_error],
|
35
|
+
'lost_or_stolen' => STANDARD_ERROR_CODE[:card_declined],
|
36
|
+
'suspected_fraud' => STANDARD_ERROR_CODE[:card_declined],
|
37
|
+
'expired_token' => STANDARD_ERROR_CODE[:card_declined]
|
38
|
+
}
|
39
|
+
|
40
|
+
def initialize(options = {})
|
41
|
+
requires!(options, :client_guid, :auth_token)
|
42
|
+
@client_guid = options[:client_guid]
|
43
|
+
@auth_token = options[:auth_token]
|
44
|
+
@access_token = options[:access_token]
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def purchase(money, payment_method, options = {})
|
49
|
+
post = {}
|
50
|
+
action = 'sale'
|
51
|
+
|
52
|
+
payment_method = get_card_token(payment_method) if payment_method.is_a?(String)
|
53
|
+
add_datetime(post, options)
|
54
|
+
add_invoice(post, money, options)
|
55
|
+
add_clerk(post, options)
|
56
|
+
add_transaction(post, options)
|
57
|
+
add_card(action, post, payment_method, options)
|
58
|
+
add_card_present(post, options)
|
59
|
+
add_customer(post, payment_method, options)
|
60
|
+
|
61
|
+
commit(action, post, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def authorize(money, payment_method, options = {})
|
65
|
+
post = {}
|
66
|
+
action = 'authorization'
|
67
|
+
|
68
|
+
payment_method = get_card_token(payment_method) if payment_method.is_a?(String)
|
69
|
+
add_datetime(post, options)
|
70
|
+
add_invoice(post, money, options)
|
71
|
+
add_clerk(post, options)
|
72
|
+
add_transaction(post, options)
|
73
|
+
add_card(action, post, payment_method, options)
|
74
|
+
add_card_present(post, options)
|
75
|
+
add_customer(post, payment_method, options)
|
76
|
+
|
77
|
+
commit(action, post, options)
|
78
|
+
end
|
79
|
+
|
80
|
+
def capture(money, authorization, options = {})
|
81
|
+
post = {}
|
82
|
+
action = 'capture'
|
83
|
+
options[:invoice] = get_invoice(authorization)
|
84
|
+
|
85
|
+
add_datetime(post, options)
|
86
|
+
add_invoice(post, money, options)
|
87
|
+
add_clerk(post, options)
|
88
|
+
add_transaction(post, options)
|
89
|
+
add_card(action, post, get_card_token(authorization), options)
|
90
|
+
|
91
|
+
commit(action, post, options)
|
92
|
+
end
|
93
|
+
|
94
|
+
def refund(money, authorization, options = {})
|
95
|
+
post = {}
|
96
|
+
action = 'refund'
|
97
|
+
|
98
|
+
add_datetime(post, options)
|
99
|
+
add_invoice(post, money, options)
|
100
|
+
add_clerk(post, options)
|
101
|
+
add_transaction(post, options)
|
102
|
+
add_card(action, post, get_card_token(authorization), options)
|
103
|
+
add_card_present(post, options)
|
104
|
+
|
105
|
+
commit(action, post, options)
|
106
|
+
end
|
107
|
+
|
108
|
+
def void(authorization, options = {})
|
109
|
+
options[:invoice] = get_invoice(authorization)
|
110
|
+
commit('invoice', {}, options)
|
111
|
+
end
|
112
|
+
|
113
|
+
def verify(credit_card, options = {})
|
114
|
+
post = {}
|
115
|
+
action = 'verify'
|
116
|
+
post[:transaction] = {}
|
117
|
+
|
118
|
+
add_datetime(post, options)
|
119
|
+
add_card(action, post, credit_card, options)
|
120
|
+
add_customer(post, credit_card, options)
|
121
|
+
add_card_on_file(post[:transaction], options)
|
122
|
+
|
123
|
+
commit(action, post, options)
|
124
|
+
end
|
125
|
+
|
126
|
+
def store(credit_card, options = {})
|
127
|
+
post = {}
|
128
|
+
action = 'add'
|
129
|
+
|
130
|
+
add_datetime(post, options)
|
131
|
+
add_card(action, post, credit_card, options)
|
132
|
+
add_customer(post, credit_card, options)
|
133
|
+
|
134
|
+
commit(action, post, options)
|
135
|
+
end
|
136
|
+
|
137
|
+
def supports_scrubbing?
|
138
|
+
true
|
139
|
+
end
|
140
|
+
|
141
|
+
def scrub(transcript)
|
142
|
+
transcript.
|
143
|
+
gsub(%r(("Number\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
144
|
+
gsub(%r(("expirationDate\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
145
|
+
gsub(%r(("FirstName\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
146
|
+
gsub(%r(("LastName\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
147
|
+
gsub(%r(("securityCode\\?":{\\?"[\w]+\\?":[\d]+,\\?"value\\?":\\?")[\d]*)i, '\1[FILTERED]')
|
148
|
+
end
|
149
|
+
|
150
|
+
def setup_access_token
|
151
|
+
post = {}
|
152
|
+
add_credentials(post, options)
|
153
|
+
add_datetime(post, options)
|
154
|
+
|
155
|
+
response = commit('accesstoken', post, request_headers('accesstoken', options))
|
156
|
+
raise OAuthResponseError.new(response, response.params.fetch('result', [{}]).first.dig('error', 'longText')) unless response.success?
|
157
|
+
|
158
|
+
response.params['result'].first['credential']['accessToken']
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def add_credentials(post, options)
|
164
|
+
post[:credential] = {}
|
165
|
+
post[:credential][:clientGuid] = @client_guid
|
166
|
+
post[:credential][:authToken] = @auth_token
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_clerk(post, options)
|
170
|
+
post[:clerk] = {}
|
171
|
+
post[:clerk][:numericId] = options[:clerk_id] || '1'
|
172
|
+
end
|
173
|
+
|
174
|
+
def add_invoice(post, money, options)
|
175
|
+
post[:amount] = {}
|
176
|
+
post[:amount][:total] = amount(money.to_f)
|
177
|
+
post[:amount][:tax] = options[:tax].to_f || 0.0
|
178
|
+
end
|
179
|
+
|
180
|
+
def add_datetime(post, options)
|
181
|
+
post[:dateTime] = options[:date_time] || current_date_time(options)
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_transaction(post, options)
|
185
|
+
post[:transaction] = {}
|
186
|
+
post[:transaction][:invoice] = options[:invoice] || Time.new.to_i.to_s[1..3] + rand.to_s[2..7]
|
187
|
+
post[:transaction][:notes] = options[:notes] if options[:notes].present?
|
188
|
+
post[:transaction][:vendorReference] = options[:order_id]
|
189
|
+
|
190
|
+
add_purchase_card(post[:transaction], options)
|
191
|
+
add_card_on_file(post[:transaction], options)
|
192
|
+
end
|
193
|
+
|
194
|
+
def add_card(action, post, payment_method, options)
|
195
|
+
post[:card] = {}
|
196
|
+
post[:card][:entryMode] = options[:entry_mode] || 'M' unless DISALLOWED_ENTRY_MODE_ACTIONS.include?(action)
|
197
|
+
if payment_method.is_a?(CreditCard)
|
198
|
+
post[:card][:expirationDate] = "#{format(payment_method.month, :two_digits)}#{format(payment_method.year, :two_digits)}"
|
199
|
+
post[:card][:number] = payment_method.number
|
200
|
+
post[:card][:securityCode] = {}
|
201
|
+
post[:card][:securityCode][:indicator] = 1
|
202
|
+
post[:card][:securityCode][:value] = payment_method.verification_value
|
203
|
+
else
|
204
|
+
post[:card] = {} if post[:card].nil?
|
205
|
+
post[:card][:token] = {}
|
206
|
+
post[:card][:token][:value] = payment_method
|
207
|
+
post[:card][:expirationDate] = options[:expiration_date] if options[:expiration_date]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_card_present(post, options)
|
212
|
+
post[:card] = {} unless post[:card].present?
|
213
|
+
|
214
|
+
post[:card][:present] = options[:card_present] || 'N'
|
215
|
+
end
|
216
|
+
|
217
|
+
def add_customer(post, card, options)
|
218
|
+
address = options[:billing_address] || {}
|
219
|
+
|
220
|
+
post[:customer] = {}
|
221
|
+
post[:customer][:addressLine1] = address[:address1] if address[:address1]
|
222
|
+
post[:customer][:postalCode] = address[:zip] if address[:zip] && !address[:zip]&.to_s&.empty?
|
223
|
+
post[:customer][:firstName] = card.first_name if card.is_a?(CreditCard) && card.first_name
|
224
|
+
post[:customer][:lastName] = card.last_name if card.is_a?(CreditCard) && card.last_name
|
225
|
+
post[:customer][:emailAddress] = options[:email] if options[:email]
|
226
|
+
post[:customer][:ipAddress] = options[:ip] if options[:ip]
|
227
|
+
end
|
228
|
+
|
229
|
+
def add_purchase_card(post, options)
|
230
|
+
return unless options[:customer_reference] || options[:destination_postal_code] || options[:product_descriptors]
|
231
|
+
|
232
|
+
post[:purchaseCard] = {}
|
233
|
+
post[:purchaseCard][:customerReference] = options[:customer_reference] if options[:customer_reference]
|
234
|
+
post[:purchaseCard][:destinationPostalCode] = options[:destination_postal_code] if options[:destination_postal_code]
|
235
|
+
post[:purchaseCard][:productDescriptors] = options[:product_descriptors] if options[:product_descriptors]
|
236
|
+
end
|
237
|
+
|
238
|
+
def add_card_on_file(post, options)
|
239
|
+
return unless options[:stored_credential] || options[:usage_indicator] || options[:indicator] || options[:scheduled_indicator] || options[:transaction_id]
|
240
|
+
|
241
|
+
stored_credential = options[:stored_credential] || {}
|
242
|
+
post[:cardOnFile] = {}
|
243
|
+
post[:cardOnFile][:usageIndicator] = options[:usage_indicator] || (stored_credential[:initial_transaction] ? '01' : '02')
|
244
|
+
post[:cardOnFile][:indicator] = options[:indicator] || '01'
|
245
|
+
post[:cardOnFile][:scheduledIndicator] = options[:scheduled_indicator] || (RECURRING_TYPE_TRANSACTIONS.include?(stored_credential[:reason_type]) ? '01' : '02')
|
246
|
+
post[:cardOnFile][:transactionId] = options[:transaction_id] || stored_credential[:network_transaction_id] if options[:transaction_id] || stored_credential[:network_transaction_id]
|
247
|
+
end
|
248
|
+
|
249
|
+
def commit(action, parameters, option)
|
250
|
+
url_postfix = URL_POSTFIX_MAPPING[action] || 'transactions'
|
251
|
+
url = (test? ? "#{test_url}#{url_postfix}/#{action}" : "#{live_url}#{url_postfix}/#{action}")
|
252
|
+
if action == 'invoice'
|
253
|
+
response = parse(ssl_request(:delete, url, parameters.to_json, request_headers(action, option)))
|
254
|
+
else
|
255
|
+
response = parse(ssl_post(url, parameters.to_json, request_headers(action, option)))
|
256
|
+
end
|
257
|
+
|
258
|
+
Response.new(
|
259
|
+
success_from(action, response),
|
260
|
+
message_from(action, response),
|
261
|
+
response,
|
262
|
+
authorization: authorization_from(action, response),
|
263
|
+
test: test?,
|
264
|
+
error_code: error_code_from(action, response)
|
265
|
+
)
|
266
|
+
end
|
267
|
+
|
268
|
+
def handle_response(response)
|
269
|
+
case response.code.to_i
|
270
|
+
when 200...300, 400, 401, 500
|
271
|
+
response.body
|
272
|
+
else
|
273
|
+
raise ResponseError.new(response)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def parse(body)
|
278
|
+
return {} if body == ''
|
279
|
+
|
280
|
+
JSON.parse(body)
|
281
|
+
end
|
282
|
+
|
283
|
+
def message_from(action, response)
|
284
|
+
success_from(action, response) ? 'Transaction successful' : (error(response)&.dig('longText') || 'Transaction declined')
|
285
|
+
end
|
286
|
+
|
287
|
+
def error_code_from(action, response)
|
288
|
+
return unless success_from(action, response)
|
289
|
+
|
290
|
+
STANDARD_ERROR_CODE_MAPPING[response['primaryCode']]
|
291
|
+
end
|
292
|
+
|
293
|
+
def authorization_from(action, response)
|
294
|
+
return unless success_from(action, response)
|
295
|
+
|
296
|
+
authorization = response.dig('result', 0, 'card', 'token', 'value').to_s
|
297
|
+
invoice = response.dig('result', 0, 'transaction', 'invoice')
|
298
|
+
authorization += "|#{invoice}" if invoice
|
299
|
+
authorization
|
300
|
+
end
|
301
|
+
|
302
|
+
def get_card_token(authorization)
|
303
|
+
authorization.is_a?(CreditCard) ? authorization : authorization.split('|')[0]
|
304
|
+
end
|
305
|
+
|
306
|
+
def get_invoice(authorization)
|
307
|
+
authorization.is_a?(CreditCard) ? authorization : authorization.split('|')[1]
|
308
|
+
end
|
309
|
+
|
310
|
+
def request_headers(action, options)
|
311
|
+
headers = {
|
312
|
+
'Content-Type' => 'application/json'
|
313
|
+
}
|
314
|
+
headers['AccessToken'] = @access_token
|
315
|
+
headers['Invoice'] = options[:invoice] if action != 'capture' && options[:invoice].present?
|
316
|
+
headers['InterfaceVersion'] = '1'
|
317
|
+
headers['InterfaceName'] = 'Spreedly'
|
318
|
+
headers['CompanyName'] = 'Spreedly'
|
319
|
+
headers
|
320
|
+
end
|
321
|
+
|
322
|
+
def success_from(action, response)
|
323
|
+
success = error(response).nil?
|
324
|
+
success &&= SUCCESS_TRANSACTION_STATUS.include?(response['result'].first['transaction']['responseCode']) unless TRANSACTIONS_WITHOUT_RESPONSE_CODE.include?(action)
|
325
|
+
success
|
326
|
+
end
|
327
|
+
|
328
|
+
def error(response)
|
329
|
+
server_error = { 'longText' => response['error'] } if response['error']
|
330
|
+
server_error || response['result'].first['error']
|
331
|
+
end
|
332
|
+
|
333
|
+
def current_date_time(options = {})
|
334
|
+
time_zone = options[:merchant_time_zone] || 'Pacific Time (US & Canada)'
|
335
|
+
time = Time.now.in_time_zone(time_zone)
|
336
|
+
offset = Time.now.in_time_zone(time_zone).formatted_offset
|
337
|
+
|
338
|
+
time.strftime('%Y-%m-%dT%H:%M:%S.%3N') + offset
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
@@ -4,10 +4,13 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.test_url = 'https://payments.sta.simetrik.com/v1'
|
5
5
|
self.live_url = 'https://payments.simetrik.com/v1'
|
6
6
|
|
7
|
-
class_attribute :test_auth_url, :live_auth_url
|
7
|
+
class_attribute :test_auth_url, :live_auth_url, :test_audience, :live_audience
|
8
8
|
self.test_auth_url = 'https://tenant-payments-dev.us.auth0.com/oauth/token'
|
9
9
|
self.live_auth_url = 'https://tenant-payments-prod.us.auth0.com/oauth/token'
|
10
10
|
|
11
|
+
self.test_audience = 'https://tenant-payments-dev.us.auth0.com/api/v2/'
|
12
|
+
self.live_audience = 'https://tenant-payments-prod.us.auth0.com/api/v2/'
|
13
|
+
|
11
14
|
self.supported_countries = %w(PE AR)
|
12
15
|
self.default_currency = 'USD'
|
13
16
|
self.supported_cardtypes = %i[visa master american_express discover]
|
@@ -39,7 +42,7 @@ module ActiveMerchant #:nodoc:
|
|
39
42
|
}
|
40
43
|
|
41
44
|
def initialize(options = {})
|
42
|
-
requires!(options, :client_id, :client_secret
|
45
|
+
requires!(options, :client_id, :client_secret)
|
43
46
|
super
|
44
47
|
@access_token = {}
|
45
48
|
sign_access_token()
|
@@ -52,7 +55,6 @@ module ActiveMerchant #:nodoc:
|
|
52
55
|
add_forward_route(post, options)
|
53
56
|
add_forward_payload(post, money, payment, options)
|
54
57
|
add_stored_credential(post, options)
|
55
|
-
|
56
58
|
commit('authorize', post, { token_acquirer: options[:token_acquirer] })
|
57
59
|
end
|
58
60
|
|
@@ -70,7 +72,7 @@ module ActiveMerchant #:nodoc:
|
|
70
72
|
acquire_extra_options: options[:acquire_extra_options] || {}
|
71
73
|
}
|
72
74
|
}
|
73
|
-
post[:forward_payload][:amount][:vat] = options[:vat] if options[:vat]
|
75
|
+
post[:forward_payload][:amount][:vat] = options[:vat].to_f / 100 if options[:vat]
|
74
76
|
|
75
77
|
add_forward_route(post, options)
|
76
78
|
commit('capture', post, { token_acquirer: options[:token_acquirer] })
|
@@ -127,12 +129,10 @@ module ActiveMerchant #:nodoc:
|
|
127
129
|
|
128
130
|
def scrub(transcript)
|
129
131
|
transcript.
|
130
|
-
gsub(%r((
|
131
|
-
gsub(%r((
|
132
|
-
gsub(%r((
|
133
|
-
gsub(%r((
|
134
|
-
gsub(%r((\"holder_first_name\\\":\\\")"\w+"), '\1[FILTERED]').
|
135
|
-
gsub(%r((\"holder_last_name\\\":\\\")"\w+"), '\1[FILTERED]')
|
132
|
+
gsub(%r((Authorization: Bearer ).+), '\1[FILTERED]').
|
133
|
+
gsub(%r(("client_secret\\?":\\?")\w+), '\1[FILTERED]').
|
134
|
+
gsub(%r(("number\\?":\\?")\d+), '\1[FILTERED]').
|
135
|
+
gsub(%r(("security_code\\?":\\?")\d+), '\1[FILTERED]')
|
136
136
|
end
|
137
137
|
|
138
138
|
private
|
@@ -148,7 +148,7 @@ module ActiveMerchant #:nodoc:
|
|
148
148
|
def add_forward_payload(post, money, payment, options)
|
149
149
|
forward_payload = {}
|
150
150
|
add_user(forward_payload, options[:user]) if options[:user]
|
151
|
-
add_order(forward_payload, money, options
|
151
|
+
add_order(forward_payload, money, options)
|
152
152
|
add_payment_method(forward_payload, payment, options[:payment_method]) if options[:payment_method] || payment
|
153
153
|
|
154
154
|
forward_payload[:payment_method] = {} unless forward_payload[:payment_method]
|
@@ -230,29 +230,34 @@ module ActiveMerchant #:nodoc:
|
|
230
230
|
post[:forward_payload][:authentication][:stored_credential] = options[:stored_credential] if check_initiator && check_reason_type
|
231
231
|
end
|
232
232
|
|
233
|
-
def add_order(post, money,
|
233
|
+
def add_order(post, money, options)
|
234
|
+
return unless options[:order] || money
|
235
|
+
|
234
236
|
order = {}
|
235
|
-
|
236
|
-
order[:
|
237
|
-
order[:
|
237
|
+
order_options = options[:order] || {}
|
238
|
+
order[:id] = options[:order_id] if options[:order_id]
|
239
|
+
order[:description] = options[:description] if options[:description]
|
240
|
+
order[:installments] = order_options[:installments].to_i if order_options[:installments]
|
238
241
|
order[:datetime_local_transaction] = order_options[:datetime_local_transaction] if order_options[:datetime_local_transaction]
|
239
242
|
|
240
|
-
add_amount(order, money,
|
241
|
-
add_address('shipping_address', order,
|
243
|
+
add_amount(order, money, options)
|
244
|
+
add_address('shipping_address', order, options)
|
242
245
|
|
243
246
|
post[:order] = order
|
244
247
|
end
|
245
248
|
|
246
|
-
def add_amount(post, money,
|
249
|
+
def add_amount(post, money, options)
|
247
250
|
amount_obj = {}
|
248
251
|
amount_obj[:total_amount] = amount(money).to_f
|
249
|
-
amount_obj[:currency] = (
|
250
|
-
amount_obj[:vat] =
|
252
|
+
amount_obj[:currency] = (options[:currency] || currency(money))
|
253
|
+
amount_obj[:vat] = options[:vat].to_f / 100 if options[:vat]
|
251
254
|
|
252
255
|
post[:amount] = amount_obj
|
253
256
|
end
|
254
257
|
|
255
|
-
def add_address(tag, post,
|
258
|
+
def add_address(tag, post, options)
|
259
|
+
return unless address_options = options[:shipping_address]
|
260
|
+
|
256
261
|
address = {}
|
257
262
|
address[:name] = address_options[:name] if address_options[:name]
|
258
263
|
address[:address1] = address_options[:address1] if address_options[:address1]
|
@@ -335,6 +340,7 @@ module ActiveMerchant #:nodoc:
|
|
335
340
|
}
|
336
341
|
end
|
337
342
|
|
343
|
+
# if this method is refactored, ensure that the client_secret is properly scrubbed
|
338
344
|
def sign_access_token
|
339
345
|
fetch_access_token() if Time.new.to_i > (@access_token[:expires_at] || 0) + 10
|
340
346
|
@access_token[:access_token]
|
@@ -348,7 +354,7 @@ module ActiveMerchant #:nodoc:
|
|
348
354
|
login_info = {}
|
349
355
|
login_info[:client_id] = @options[:client_id]
|
350
356
|
login_info[:client_secret] = @options[:client_secret]
|
351
|
-
login_info[:audience] =
|
357
|
+
login_info[:audience] = test? ? test_audience : live_audience
|
352
358
|
login_info[:grant_type] = 'client_credentials'
|
353
359
|
response = parse(ssl_post(auth_url(), login_info.to_json, {
|
354
360
|
'content-Type' => 'application/json'
|
@@ -145,6 +145,7 @@ module ActiveMerchant #:nodoc:
|
|
145
145
|
|
146
146
|
def void(identification, options = {})
|
147
147
|
post = {}
|
148
|
+
post[:reverse_transfer] = options[:reverse_transfer] if options[:reverse_transfer]
|
148
149
|
post[:metadata] = options[:metadata] if options[:metadata]
|
149
150
|
post[:reason] = options[:reason] if options[:reason]
|
150
151
|
post[:expand] = [:charge]
|
@@ -280,6 +281,7 @@ module ActiveMerchant #:nodoc:
|
|
280
281
|
def scrub(transcript)
|
281
282
|
transcript.
|
282
283
|
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
284
|
+
gsub(%r((Authorization: Bearer )\w+), '\1[FILTERED]').
|
283
285
|
gsub(%r((&?three_d_secure\[cryptogram\]=)[\w=]*(&?)), '\1[FILTERED]\2').
|
284
286
|
gsub(%r(((\[card\]|card)\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
285
287
|
gsub(%r(((\[card\]|card)\[cvc\]=)\d+), '\1[FILTERED]').
|
@@ -301,7 +303,7 @@ module ActiveMerchant #:nodoc:
|
|
301
303
|
def delete_latest_test_external_account(account)
|
302
304
|
return unless test?
|
303
305
|
|
304
|
-
auth_header = { 'Authorization'
|
306
|
+
auth_header = { 'Authorization' => 'Basic ' + Base64.strict_encode64(options[:login].to_s + ':').strip }
|
305
307
|
url = "#{live_url}accounts/#{CGI.escape(account)}/external_accounts"
|
306
308
|
accounts_response = JSON.parse(ssl_get("#{url}?limit=100", auth_header))
|
307
309
|
to_delete = accounts_response['data'].reject { |ac| ac['default_for_currency'] }
|
@@ -389,6 +391,7 @@ module ActiveMerchant #:nodoc:
|
|
389
391
|
end
|
390
392
|
|
391
393
|
add_metadata(post, options)
|
394
|
+
add_shipping_address(post, payment, options)
|
392
395
|
add_application_fee(post, options)
|
393
396
|
add_exchange_rate(post, options)
|
394
397
|
add_destination(post, options)
|
@@ -555,6 +558,23 @@ module ActiveMerchant #:nodoc:
|
|
555
558
|
post[:metadata][:card_read_method] = creditcard.read_method if creditcard.respond_to?(:read_method)
|
556
559
|
end
|
557
560
|
|
561
|
+
def add_shipping_address(post, payment, options = {})
|
562
|
+
return unless shipping = options[:shipping_address]
|
563
|
+
return unless shipping_name = shipping[:name]
|
564
|
+
|
565
|
+
post[:shipping] = {}
|
566
|
+
|
567
|
+
post[:shipping][:name] = shipping_name
|
568
|
+
post[:shipping][:address] = {}
|
569
|
+
post[:shipping][:address][:line1] = shipping[:address1]
|
570
|
+
post[:shipping][:address][:line2] = shipping[:address2] if shipping[:address2]
|
571
|
+
post[:shipping][:address][:city] = shipping[:city] if shipping[:city]
|
572
|
+
post[:shipping][:address][:country] = shipping[:country] if shipping[:country]
|
573
|
+
post[:shipping][:address][:state] = shipping[:state] if shipping[:state]
|
574
|
+
post[:shipping][:address][:postal_code] = shipping[:zip] if shipping[:zip]
|
575
|
+
post[:shipping][:phone] = shipping[:phone_number] if shipping[:phone_number]
|
576
|
+
end
|
577
|
+
|
558
578
|
def add_source_owner(post, creditcard, options)
|
559
579
|
post[:owner] = {}
|
560
580
|
post[:owner][:name] = creditcard.name if creditcard.name
|