activemerchant 1.121.0 → 1.125.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 +217 -0
- data/README.md +1 -1
- data/lib/active_merchant/billing/check.rb +13 -19
- data/lib/active_merchant/billing/credit_card.rb +13 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +24 -12
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/adyen.rb +75 -27
- data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -3
- data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
- data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +33 -4
- data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +41 -6
- data/lib/active_merchant/billing/gateways/d_local.rb +12 -6
- data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +65 -30
- data/lib/active_merchant/billing/gateways/element.rb +22 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +130 -26
- data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +30 -0
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +6 -3
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
- data/lib/active_merchant/billing/gateways/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/moka.rb +290 -0
- data/lib/active_merchant/billing/gateways/monei.rb +228 -144
- data/lib/active_merchant/billing/gateways/mundipagg.rb +22 -11
- data/lib/active_merchant/billing/gateways/nmi.rb +29 -10
- data/lib/active_merchant/billing/gateways/orbital.rb +46 -8
- data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
- data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
- data/lib/active_merchant/billing/gateways/paymentez.rb +14 -2
- data/lib/active_merchant/billing/gateways/paysafe.rb +412 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +9 -4
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
- data/lib/active_merchant/billing/gateways/pin.rb +31 -4
- data/lib/active_merchant/billing/gateways/priority.rb +347 -0
- data/lib/active_merchant/billing/gateways/realex.rb +18 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
- data/lib/active_merchant/billing/gateways/safe_charge.rb +8 -2
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +115 -39
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +21 -7
- data/lib/active_merchant/billing/gateways/vpos.rb +49 -6
- data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +226 -62
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/billing/response.rb +4 -0
- data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +13 -3
@@ -0,0 +1,404 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PayTraceGateway < Gateway
|
4
|
+
self.test_url = 'https://api.paytrace.com'
|
5
|
+
self.live_url = 'https://api.paytrace.com'
|
6
|
+
|
7
|
+
self.supported_countries = ['US']
|
8
|
+
self.default_currency = 'USD'
|
9
|
+
self.supported_cardtypes = %i[visa master american_express discover]
|
10
|
+
|
11
|
+
self.homepage_url = 'https://paytrace.com/'
|
12
|
+
self.display_name = 'PayTrace'
|
13
|
+
|
14
|
+
# Response codes based on API Response Codes found here: https://developers.paytrace.com/support/home#14000041297
|
15
|
+
STANDARD_ERROR_CODE_MAPPING = {
|
16
|
+
'1' => STANDARD_ERROR_CODE[:error_occurred],
|
17
|
+
'102' => STANDARD_ERROR_CODE[:declined],
|
18
|
+
'103' => STANDARD_ERROR_CODE[:auto_voided],
|
19
|
+
'107' => STANDARD_ERROR_CODE[:unsuccessful_refund],
|
20
|
+
'108' => STANDARD_ERROR_CODE[:test_refund],
|
21
|
+
'110' => STANDARD_ERROR_CODE[:unsuccessful_void],
|
22
|
+
'113' => STANDARD_ERROR_CODE[:unsuccessful_capture]
|
23
|
+
}
|
24
|
+
|
25
|
+
ENDPOINTS = {
|
26
|
+
customer_id_sale: 'transactions/sale/by_customer',
|
27
|
+
keyed_sale: 'transactions/sale/keyed',
|
28
|
+
customer_id_auth: 'transactions/authorization/by_customer',
|
29
|
+
keyed_auth: 'transactions/authorization/keyed',
|
30
|
+
capture: 'transactions/authorization/capture',
|
31
|
+
transaction_refund: 'transactions/refund/for_transaction',
|
32
|
+
transaction_void: 'transactions/void',
|
33
|
+
store: 'customer/create',
|
34
|
+
redact: 'customer/delete',
|
35
|
+
level_3_visa: 'level_three/visa',
|
36
|
+
level_3_mastercard: 'level_three/mastercard'
|
37
|
+
}
|
38
|
+
|
39
|
+
def initialize(options = {})
|
40
|
+
requires!(options, :username, :password, :integrator_id)
|
41
|
+
super
|
42
|
+
acquire_access_token
|
43
|
+
end
|
44
|
+
|
45
|
+
def purchase(money, payment_or_customer_id, options = {})
|
46
|
+
if visa_or_mastercard?(options)
|
47
|
+
MultiResponse.run(:use_first_response) do |r|
|
48
|
+
endpoint = customer_id?(payment_or_customer_id) ? ENDPOINTS[:customer_id_sale] : ENDPOINTS[:keyed_sale]
|
49
|
+
|
50
|
+
r.process { commit(endpoint, build_purchase_request(money, payment_or_customer_id, options)) }
|
51
|
+
r.process { commit(ENDPOINTS[:"level_3_#{options[:visa_or_mastercard]}"], send_level_3_data(r, options)) }
|
52
|
+
end
|
53
|
+
else
|
54
|
+
post = build_purchase_request(money, payment_or_customer_id, options)
|
55
|
+
post[:customer_id] ? endpoint = ENDPOINTS[:customer_id_sale] : endpoint = ENDPOINTS[:keyed_sale]
|
56
|
+
response = commit(endpoint, post)
|
57
|
+
check_token_response(response, endpoint, post, options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def authorize(money, payment_or_customer_id, options = {})
|
62
|
+
post = {}
|
63
|
+
add_amount(post, money, options)
|
64
|
+
if customer_id?(payment_or_customer_id)
|
65
|
+
post[:customer_id] = payment_or_customer_id
|
66
|
+
endpoint = ENDPOINTS[:customer_id_auth]
|
67
|
+
else
|
68
|
+
add_payment(post, payment_or_customer_id)
|
69
|
+
add_address(post, payment_or_customer_id, options)
|
70
|
+
add_customer_data(post, options)
|
71
|
+
endpoint = ENDPOINTS[:keyed_auth]
|
72
|
+
end
|
73
|
+
response = commit(endpoint, post)
|
74
|
+
check_token_response(response, endpoint, post, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def capture(money, authorization, options = {})
|
78
|
+
if visa_or_mastercard?(options)
|
79
|
+
MultiResponse.run do |r|
|
80
|
+
r.process { commit(ENDPOINTS[:capture], build_capture_request(money, authorization, options)) }
|
81
|
+
r.process { commit(ENDPOINTS[:"level_3_#{options[:visa_or_mastercard]}"], send_level_3_data(r, options)) }
|
82
|
+
end
|
83
|
+
else
|
84
|
+
post = build_capture_request(money, authorization, options)
|
85
|
+
response = commit(ENDPOINTS[:capture], post)
|
86
|
+
check_token_response(response, ENDPOINTS[:capture], post, options)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def refund(money, authorization, options = {})
|
91
|
+
# currently only support full and partial refunds of settled transactions via a transaction ID
|
92
|
+
post = {}
|
93
|
+
add_amount(post, money, options)
|
94
|
+
post[:transaction_id] = authorization
|
95
|
+
response = commit(ENDPOINTS[:transaction_refund], post)
|
96
|
+
check_token_response(response, ENDPOINTS[:transaction_refund], post, options)
|
97
|
+
end
|
98
|
+
|
99
|
+
def void(authorization, options = {})
|
100
|
+
post = {}
|
101
|
+
post[:transaction_id] = authorization
|
102
|
+
|
103
|
+
response = commit(ENDPOINTS[:transaction_void], post)
|
104
|
+
check_token_response(response, ENDPOINTS[:transaction_void], post, options)
|
105
|
+
end
|
106
|
+
|
107
|
+
def verify(credit_card, options = {})
|
108
|
+
authorize(0, credit_card, options)
|
109
|
+
end
|
110
|
+
|
111
|
+
# The customer_IDs that come from storing cards can be used for auth and purchase transaction types
|
112
|
+
def store(credit_card, options = {})
|
113
|
+
post = {}
|
114
|
+
post[:customer_id] = options[:customer_id] || SecureRandom.hex(12)
|
115
|
+
add_payment(post, credit_card)
|
116
|
+
add_address(post, credit_card, options)
|
117
|
+
response = commit(ENDPOINTS[:store], post)
|
118
|
+
check_token_response(response, ENDPOINTS[:store], post, options)
|
119
|
+
end
|
120
|
+
|
121
|
+
def unstore(customer_id)
|
122
|
+
post = {}
|
123
|
+
post[:customer_id] = customer_id
|
124
|
+
response = commit(ENDPOINTS[:redact], post)
|
125
|
+
check_token_response(response, ENDPOINTS[:redact], post, options)
|
126
|
+
end
|
127
|
+
|
128
|
+
def supports_scrubbing?
|
129
|
+
true
|
130
|
+
end
|
131
|
+
|
132
|
+
def scrub(transcript)
|
133
|
+
transcript.
|
134
|
+
gsub(%r((Authorization: Bearer )[a-zA-Z0-9:_]+), '\1[FILTERED]').
|
135
|
+
gsub(%r(("credit_card\\?":{\\?"number\\?":\\?")\d+), '\1[FILTERED]').
|
136
|
+
gsub(%r(("cvv\\?":\\?")\d+), '\1[FILTERED]').
|
137
|
+
gsub(%r(("username\\?":\\?")\w+@+\w+.+\w+), '\1[FILTERED]').
|
138
|
+
gsub(%r(("password\\?":\\?")\w+), '\1[FILTERED]').
|
139
|
+
gsub(%r(("integrator_id\\?":\\?")\w+), '\1[FILTERED]')
|
140
|
+
end
|
141
|
+
|
142
|
+
def acquire_access_token
|
143
|
+
post = {}
|
144
|
+
post[:grant_type] = 'password'
|
145
|
+
post[:username] = @options[:username]
|
146
|
+
post[:password] = @options[:password]
|
147
|
+
data = post.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
|
148
|
+
url = live_url + '/oauth/token'
|
149
|
+
oauth_headers = {
|
150
|
+
'Accept' => '*/*',
|
151
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
152
|
+
}
|
153
|
+
response = ssl_post(url, data, oauth_headers)
|
154
|
+
json_response = JSON.parse(response)
|
155
|
+
|
156
|
+
@options[:access_token] = json_response['access_token'] if json_response['access_token']
|
157
|
+
response
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def build_purchase_request(money, payment_or_customer_id, options)
|
163
|
+
post = {}
|
164
|
+
add_amount(post, money, options)
|
165
|
+
if customer_id?(payment_or_customer_id)
|
166
|
+
post[:customer_id] = payment_or_customer_id
|
167
|
+
else
|
168
|
+
add_payment(post, payment_or_customer_id)
|
169
|
+
add_address(post, payment_or_customer_id, options)
|
170
|
+
add_customer_data(post, options)
|
171
|
+
end
|
172
|
+
|
173
|
+
post
|
174
|
+
end
|
175
|
+
|
176
|
+
def build_capture_request(money, authorization, options)
|
177
|
+
post = {}
|
178
|
+
post[:transaction_id] = authorization
|
179
|
+
add_amount(post, money, options)
|
180
|
+
|
181
|
+
post
|
182
|
+
end
|
183
|
+
|
184
|
+
# method can only be used to add level 3 data to any approved and unsettled sale transaction so it is built into the standard purchase workflow above
|
185
|
+
def send_level_3_data(response, options)
|
186
|
+
post = {}
|
187
|
+
post[:transaction_id] = response.authorization
|
188
|
+
add_level_3_data(post, options)
|
189
|
+
|
190
|
+
post
|
191
|
+
end
|
192
|
+
|
193
|
+
def visa_or_mastercard?(options)
|
194
|
+
return false unless options[:visa_or_mastercard]
|
195
|
+
|
196
|
+
options[:visa_or_mastercard] == 'visa' || options[:visa_or_mastercard] == 'mastercard'
|
197
|
+
end
|
198
|
+
|
199
|
+
def customer_id?(payment_or_customer_id)
|
200
|
+
payment_or_customer_id.class == String
|
201
|
+
end
|
202
|
+
|
203
|
+
def string_literal_to_boolean(value)
|
204
|
+
return value unless value.class == String
|
205
|
+
|
206
|
+
if value.casecmp('true').zero?
|
207
|
+
true
|
208
|
+
elsif value.casecmp('false').zero?
|
209
|
+
false
|
210
|
+
else return nil
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def add_customer_data(post, options)
|
215
|
+
return unless options[:email]
|
216
|
+
|
217
|
+
post[:email] = options[:email]
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_address(post, creditcard, options)
|
221
|
+
return unless options[:billing_address] || options[:address]
|
222
|
+
|
223
|
+
address = options[:billing_address] || options[:address]
|
224
|
+
post[:billing_address] = {}
|
225
|
+
post[:billing_address][:name] = creditcard.name
|
226
|
+
post[:billing_address][:street_address] = address[:address1]
|
227
|
+
post[:billing_address][:city] = address[:city]
|
228
|
+
post[:billing_address][:state] = address[:state]
|
229
|
+
post[:billing_address][:zip] = address[:zip]
|
230
|
+
end
|
231
|
+
|
232
|
+
def add_amount(post, money, options)
|
233
|
+
post[:amount] = amount(money)
|
234
|
+
end
|
235
|
+
|
236
|
+
def add_payment(post, payment)
|
237
|
+
post[:credit_card] = {}
|
238
|
+
post[:credit_card][:number] = payment.number
|
239
|
+
post[:credit_card][:expiration_month] = payment.month
|
240
|
+
post[:credit_card][:expiration_year] = payment.year
|
241
|
+
end
|
242
|
+
|
243
|
+
def add_level_3_data(post, options)
|
244
|
+
post[:invoice_id] = options[:invoice_id] if options[:invoice_id]
|
245
|
+
post[:customer_reference_id] = options[:customer_reference_id] if options[:customer_reference_id]
|
246
|
+
post[:tax_amount] = options[:tax_amount].to_i if options[:tax_amount]
|
247
|
+
post[:national_tax_amount] = options[:national_tax_amount].to_i if options[:national_tax_amount]
|
248
|
+
post[:merchant_tax_id] = options[:merchant_tax_id] if options[:merchant_tax_id]
|
249
|
+
post[:customer_tax_id] = options[:customer_tax_id] if options[:customer_tax_id]
|
250
|
+
post[:commodity_code] = options[:commodity_code] if options[:commodity_code]
|
251
|
+
post[:discount_amount] = options[:discount_amount].to_i if options[:discount_amount]
|
252
|
+
post[:freight_amount] = options[:freight_amount].to_i if options[:freight_amount]
|
253
|
+
post[:duty_amount] = options[:duty_amount].to_i if options[:duty_amount]
|
254
|
+
post[:additional_tax_amount] = options[:additional_tax_amount].to_i if options[:additional_tax_amount]
|
255
|
+
post[:additional_tax_rate] = options[:additional_tax_rate].to_i if options[:additional_tax_rate]
|
256
|
+
|
257
|
+
add_source_address(post, options)
|
258
|
+
add_shipping_address(post, options)
|
259
|
+
add_line_items(post, options)
|
260
|
+
end
|
261
|
+
|
262
|
+
def add_source_address(post, options)
|
263
|
+
return unless source_address = options[:source_address] ||
|
264
|
+
options[:billing_address] ||
|
265
|
+
options[:address]
|
266
|
+
|
267
|
+
post[:source_address] = {}
|
268
|
+
post[:source_address][:zip] = source_address[:zip] if source_address[:zip]
|
269
|
+
end
|
270
|
+
|
271
|
+
def add_shipping_address(post, options)
|
272
|
+
return unless shipping_address = options[:shipping_address]
|
273
|
+
|
274
|
+
post[:shipping_address] = {}
|
275
|
+
post[:shipping_address][:name] = shipping_address[:name] if shipping_address[:name]
|
276
|
+
post[:shipping_address][:street_address] = shipping_address[:address1] if shipping_address[:address1]
|
277
|
+
post[:shipping_address][:street_address2] = shipping_address[:address2] if shipping_address[:address2]
|
278
|
+
post[:shipping_address][:city] = shipping_address[:city] if shipping_address[:city]
|
279
|
+
post[:shipping_address][:state] = shipping_address[:state] if shipping_address[:state]
|
280
|
+
post[:shipping_address][:zip] = shipping_address[:zip] if shipping_address[:zip]
|
281
|
+
post[:shipping_address][:country] = shipping_address[:country] if shipping_address[:country]
|
282
|
+
end
|
283
|
+
|
284
|
+
def add_line_items(post, options)
|
285
|
+
return unless options[:line_items]
|
286
|
+
|
287
|
+
line_items = []
|
288
|
+
options[:line_items].each do |li|
|
289
|
+
obj = {}
|
290
|
+
|
291
|
+
obj[:additional_tax_amount] = li[:additional_tax_amount].to_i if li[:additional_tax_amount]
|
292
|
+
obj[:additional_tax_included] = string_literal_to_boolean(li[:additional_tax_included]) if li[:additional_tax_included]
|
293
|
+
obj[:additional_tax_rate] = li[:additional_tax_rate].to_i if li[:additional_tax_rate]
|
294
|
+
obj[:amount] = li[:amount].to_i if li[:amount]
|
295
|
+
obj[:commodity_code] = li[:commodity_code] if li[:commodity_code]
|
296
|
+
obj[:debit_or_credit] = li[:debit_or_credit] if li[:debit_or_credit]
|
297
|
+
obj[:description] = li[:description] if li[:description]
|
298
|
+
obj[:discount_amount] = li[:discount_amount].to_i if li[:discount_amount]
|
299
|
+
obj[:discount_rate] = li[:discount_rate].to_i if li[:discount_rate]
|
300
|
+
obj[:discount_included] = string_literal_to_boolean(li[:discount_included]) if li[:discount_included]
|
301
|
+
obj[:merchant_tax_id] = li[:merchant_tax_id] if li[:merchant_tax_id]
|
302
|
+
obj[:product_id] = li[:product_id] if li[:product_id]
|
303
|
+
obj[:quantity] = li[:quantity] if li[:quantity]
|
304
|
+
obj[:transaction_id] = li[:transaction_id] if li[:transaction_id]
|
305
|
+
obj[:tax_included] = string_literal_to_boolean(li[:tax_included]) if li[:tax_included]
|
306
|
+
obj[:unit_of_measure] = li[:unit_of_measure] if li[:unit_of_measure]
|
307
|
+
obj[:unit_cost] = li[:unit_cost].to_i if li[:unit_cost]
|
308
|
+
|
309
|
+
line_items << obj
|
310
|
+
end
|
311
|
+
post[:line_items] = line_items
|
312
|
+
end
|
313
|
+
|
314
|
+
def check_token_response(response, endpoint, body = {}, options = {})
|
315
|
+
return response unless response.params['error'] == 'invalid_token'
|
316
|
+
|
317
|
+
acquire_access_token
|
318
|
+
commit(endpoint, body)
|
319
|
+
end
|
320
|
+
|
321
|
+
def parse(body)
|
322
|
+
JSON.parse(body)
|
323
|
+
end
|
324
|
+
|
325
|
+
def commit(action, parameters)
|
326
|
+
base_url = (test? ? test_url : live_url)
|
327
|
+
url = base_url + '/v1/' + action
|
328
|
+
raw_response = ssl_post(url, post_data(parameters), headers)
|
329
|
+
response = parse(raw_response)
|
330
|
+
success = success_from(response)
|
331
|
+
|
332
|
+
Response.new(
|
333
|
+
success,
|
334
|
+
message_from(success, response),
|
335
|
+
response,
|
336
|
+
authorization: authorization_from(action, response),
|
337
|
+
avs_result: AVSResult.new(code: response['avs_response']),
|
338
|
+
cvv_result: response['csc_response'],
|
339
|
+
test: test?,
|
340
|
+
error_code: success ? nil : error_code_from(response)
|
341
|
+
)
|
342
|
+
rescue JSON::ParserError
|
343
|
+
unparsable_response(raw_response)
|
344
|
+
end
|
345
|
+
|
346
|
+
def unparsable_response(raw_response)
|
347
|
+
message = 'Unparsable response received from PayTrace. Please contact PayTrace if you continue to receive this message.'
|
348
|
+
message += " (The raw response returned by the API was #{raw_response.inspect})"
|
349
|
+
return Response.new(false, message)
|
350
|
+
end
|
351
|
+
|
352
|
+
def headers
|
353
|
+
{
|
354
|
+
'Content-type' => 'application/json',
|
355
|
+
'Authorization' => 'Bearer ' + @options[:access_token]
|
356
|
+
}
|
357
|
+
end
|
358
|
+
|
359
|
+
def success_from(response)
|
360
|
+
response['success']
|
361
|
+
end
|
362
|
+
|
363
|
+
def message_from(success, response)
|
364
|
+
return response['status_message'] if success
|
365
|
+
|
366
|
+
if error = response['errors']
|
367
|
+
message = 'Errors-'
|
368
|
+
error.each do |k, v|
|
369
|
+
message.concat(" code:#{k}, message:#{v}")
|
370
|
+
end
|
371
|
+
else
|
372
|
+
message = response['status_message'].to_s + " #{response['approval_message']}"
|
373
|
+
end
|
374
|
+
|
375
|
+
message
|
376
|
+
end
|
377
|
+
|
378
|
+
# store transactions do not return a transaction_id, but they return a customer_id that will then be used as the third_party_token for the stored payment method
|
379
|
+
def authorization_from(action, response)
|
380
|
+
if action == ENDPOINTS[:store]
|
381
|
+
response['customer_id']
|
382
|
+
else
|
383
|
+
response['transaction_id']
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def post_data(parameters = {})
|
388
|
+
parameters[:password] = @options[:password]
|
389
|
+
parameters[:username] = @options[:username]
|
390
|
+
parameters[:integrator_id] = @options[:integrator_id]
|
391
|
+
|
392
|
+
parameters.to_json
|
393
|
+
end
|
394
|
+
|
395
|
+
def error_code_from(response)
|
396
|
+
STANDARD_ERROR_CODE_MAPPING[response['response_code']]
|
397
|
+
end
|
398
|
+
|
399
|
+
def handle_response(response)
|
400
|
+
response.body
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
@@ -75,6 +75,8 @@ module ActiveMerchant
|
|
75
75
|
|
76
76
|
add_authorization_info(params, authorization)
|
77
77
|
add_amount(params, (amount || amount_from_authorization(authorization)), options)
|
78
|
+
add_soft_descriptors(params, options)
|
79
|
+
add_invoice(params, options)
|
78
80
|
|
79
81
|
commit(params, options)
|
80
82
|
end
|
@@ -84,6 +86,8 @@ module ActiveMerchant
|
|
84
86
|
|
85
87
|
add_amount(params, amount, options)
|
86
88
|
add_payment_method(params, payment_method, options)
|
89
|
+
add_soft_descriptors(params, options)
|
90
|
+
add_invoice(params, options)
|
87
91
|
commit(params, options)
|
88
92
|
end
|
89
93
|
|
@@ -118,6 +118,7 @@ module ActiveMerchant #:nodoc:
|
|
118
118
|
xml.tag!('Description', options[:description]) unless options[:description].blank?
|
119
119
|
xml.tag!('Comment', options[:comment]) unless options[:comment].blank?
|
120
120
|
xml.tag!('ExtData', 'Name' => 'COMMENT2', 'Value' => options[:comment2]) unless options[:comment2].blank?
|
121
|
+
xml.tag!('MerchDescr', options[:merch_descr]) unless options[:merch_descr].blank?
|
121
122
|
xml.tag!(
|
122
123
|
'ExtData',
|
123
124
|
'Name' => 'CAPTURECOMPLETE',
|
@@ -56,6 +56,10 @@ module ActiveMerchant #:nodoc:
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
def store(payment, options = {})
|
60
|
+
raise ArgumentError, 'Store is not supported on Payflow gateways'
|
61
|
+
end
|
62
|
+
|
59
63
|
def verify_credentials
|
60
64
|
response = void('0')
|
61
65
|
response.params['result'] != '26'
|
@@ -141,6 +145,7 @@ module ActiveMerchant #:nodoc:
|
|
141
145
|
xml.tag! 'FreightAmt', options[:freightamt] unless options[:freightamt].blank?
|
142
146
|
xml.tag! 'DutyAmt', options[:dutyamt] unless options[:dutyamt].blank?
|
143
147
|
xml.tag! 'DiscountAmt', options[:discountamt] unless options[:discountamt].blank?
|
148
|
+
xml.tag! 'MerchDescr', options[:merch_descr] unless options[:merch_descr].blank?
|
144
149
|
|
145
150
|
billing_address = options[:billing_address] || options[:address]
|
146
151
|
add_address(xml, 'BillTo', billing_address, options) if billing_address
|
@@ -176,6 +181,7 @@ module ActiveMerchant #:nodoc:
|
|
176
181
|
xml.tag! 'DutyAmt', options[:dutyamt] unless options[:dutyamt].blank?
|
177
182
|
xml.tag! 'DiscountAmt', options[:discountamt] unless options[:discountamt].blank?
|
178
183
|
xml.tag! 'EMail', options[:email] unless options[:email].nil?
|
184
|
+
xml.tag! 'MerchDescr', options[:merch_descr] unless options[:merch_descr].blank?
|
179
185
|
|
180
186
|
billing_address = options[:billing_address] || options[:address]
|
181
187
|
add_address(xml, 'BillTo', billing_address, options) if billing_address
|
@@ -239,6 +245,7 @@ module ActiveMerchant #:nodoc:
|
|
239
245
|
xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
|
240
246
|
xml.tag! 'Description', options[:description] unless options[:description].blank?
|
241
247
|
xml.tag! 'OrderDesc', options[:order_desc] unless options[:order_desc].blank?
|
248
|
+
xml.tag! 'MerchDescr', options[:merch_descr] unless options[:merch_descr].blank?
|
242
249
|
xml.tag! 'BillTo' do
|
243
250
|
xml.tag! 'Name', check.name
|
244
251
|
end
|
@@ -282,18 +289,28 @@ module ActiveMerchant #:nodoc:
|
|
282
289
|
xml.tag! 'ECI', three_d_secure[:eci] unless three_d_secure[:eci].blank?
|
283
290
|
xml.tag! 'CAVV', three_d_secure[:cavv] unless three_d_secure[:cavv].blank?
|
284
291
|
xml.tag! 'XID', three_d_secure[:xid] unless three_d_secure[:xid].blank?
|
292
|
+
xml.tag! 'ThreeDSVersion', three_d_secure[:version] unless three_d_secure[:version].blank?
|
293
|
+
xml.tag! 'DSTransactionID', three_d_secure[:ds_transaction_id] unless three_d_secure[:ds_transaction_id].blank?
|
285
294
|
end
|
286
295
|
end
|
287
296
|
end
|
288
297
|
|
289
298
|
def authentication_status(three_d_secure, xml)
|
290
|
-
if three_d_secure[:authentication_response_status].present?
|
291
|
-
|
292
|
-
|
293
|
-
|
299
|
+
status = if three_d_secure[:authentication_response_status].present?
|
300
|
+
three_d_secure[:authentication_response_status]
|
301
|
+
elsif three_d_secure[:directory_response_status].present?
|
302
|
+
three_d_secure[:directory_response_status]
|
303
|
+
end
|
304
|
+
if status.present?
|
305
|
+
xml.tag! 'Status', status
|
306
|
+
xml.tag! 'AuthenticationStatus', status if version_2_or_newer?(three_d_secure)
|
294
307
|
end
|
295
308
|
end
|
296
309
|
|
310
|
+
def version_2_or_newer?(three_d_secure)
|
311
|
+
three_d_secure[:version]&.start_with?('2')
|
312
|
+
end
|
313
|
+
|
297
314
|
def credit_card_type(credit_card)
|
298
315
|
return '' if card_brand(credit_card).blank?
|
299
316
|
|
@@ -86,8 +86,8 @@ module ActiveMerchant #:nodoc:
|
|
86
86
|
refund(money, identification, options)
|
87
87
|
end
|
88
88
|
|
89
|
-
def verify(
|
90
|
-
request = build_purchase_or_authorization_request(
|
89
|
+
def verify(payment_source, options = {})
|
90
|
+
request = build_purchase_or_authorization_request(100, payment_source, options)
|
91
91
|
commit(:validate, request)
|
92
92
|
end
|
93
93
|
|
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
|
|
9
9
|
|
10
10
|
self.supported_countries = %w[MX EC CO BR CL PE]
|
11
11
|
self.default_currency = 'USD'
|
12
|
-
self.supported_cardtypes = %i[visa master american_express diners_club elo alia olimpica]
|
12
|
+
self.supported_cardtypes = %i[visa master american_express diners_club elo alia olimpica discover maestro sodexo carnet unionpay jcb]
|
13
13
|
|
14
14
|
self.homepage_url = 'https://secure.paymentez.com/'
|
15
15
|
self.display_name = 'Paymentez'
|
@@ -39,7 +39,14 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
'master' => 'mc',
|
40
40
|
'american_express' => 'ax',
|
41
41
|
'diners_club' => 'di',
|
42
|
-
'elo' => 'el'
|
42
|
+
'elo' => 'el',
|
43
|
+
'discover' => 'dc',
|
44
|
+
'maestro' => 'ms',
|
45
|
+
'sodexo' => 'sx',
|
46
|
+
'olimpica' => 'ol',
|
47
|
+
'carnet' => 'ct',
|
48
|
+
'unionpay' => 'up',
|
49
|
+
'jcb' => 'jc'
|
43
50
|
}.freeze
|
44
51
|
|
45
52
|
def initialize(options = {})
|
@@ -82,6 +89,7 @@ module ActiveMerchant #:nodoc:
|
|
82
89
|
def refund(money, authorization, options = {})
|
83
90
|
post = { transaction: { id: authorization } }
|
84
91
|
post[:order] = { amount: amount(money).to_f } if money
|
92
|
+
add_more_info(post, options)
|
85
93
|
|
86
94
|
commit_transaction('refund', post)
|
87
95
|
end
|
@@ -198,6 +206,10 @@ module ActiveMerchant #:nodoc:
|
|
198
206
|
extra_params[:auth_data] = auth_data
|
199
207
|
end
|
200
208
|
|
209
|
+
def add_more_info(post, options)
|
210
|
+
post[:more_info] = options[:more_info] if options[:more_info]
|
211
|
+
end
|
212
|
+
|
201
213
|
def parse(body)
|
202
214
|
JSON.parse(body)
|
203
215
|
end
|