activemerchant 1.116.0 → 1.121.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 +148 -1
- data/README.md +4 -2
- data/lib/active_merchant/billing/check.rb +10 -0
- data/lib/active_merchant/billing/credit_card.rb +3 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +80 -15
- data/lib/active_merchant/billing/gateways/adyen.rb +29 -8
- data/lib/active_merchant/billing/gateways/authorize_net.rb +37 -1
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +4 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +3 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +54 -7
- data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +33 -2
- data/lib/active_merchant/billing/gateways/credorax.rb +30 -14
- data/lib/active_merchant/billing/gateways/cyber_source.rb +51 -8
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +22 -2
- data/lib/active_merchant/billing/gateways/elavon.rb +54 -2
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +13 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +17 -6
- data/lib/active_merchant/billing/gateways/forte.rb +12 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +25 -6
- data/lib/active_merchant/billing/gateways/hps.rb +65 -2
- data/lib/active_merchant/billing/gateways/litle.rb +21 -5
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +2 -2
- data/lib/active_merchant/billing/gateways/netbanx.rb +37 -2
- data/lib/active_merchant/billing/gateways/orbital.rb +178 -45
- data/lib/active_merchant/billing/gateways/payeezy.rb +53 -11
- data/lib/active_merchant/billing/gateways/payment_express.rb +10 -5
- data/lib/active_merchant/billing/gateways/paymentez.rb +21 -1
- data/lib/active_merchant/billing/gateways/paypal.rb +10 -2
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
- data/lib/active_merchant/billing/gateways/pin.rb +11 -0
- data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
- data/lib/active_merchant/billing/gateways/redsys.rb +101 -5
- data/lib/active_merchant/billing/gateways/safe_charge.rb +39 -6
- data/lib/active_merchant/billing/gateways/stripe.rb +9 -9
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +82 -25
- data/lib/active_merchant/billing/gateways/vpos.rb +177 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +31 -14
- data/lib/active_merchant/billing/response.rb +2 -1
- data/lib/active_merchant/version.rb +1 -1
- data/lib/certs/cacert.pem +1582 -2431
- metadata +5 -3
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
|
7
7
|
self.supported_countries = %w[AR BR CL CO MX PE UY TR]
|
8
8
|
self.default_currency = 'USD'
|
9
|
-
self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro naranja cabal]
|
9
|
+
self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro naranja cabal elo alia carnet]
|
10
10
|
|
11
11
|
self.homepage_url = 'https://dlocal.com/'
|
12
12
|
self.display_name = 'dLocal'
|
@@ -170,6 +170,12 @@ module ActiveMerchant #:nodoc:
|
|
170
170
|
card_data[:security_code] = credit_card.verification_value if credit_card.verification_value?
|
171
171
|
card_data[:card_holder_name] = credit_card.name if credit_card.name
|
172
172
|
|
173
|
+
# the device_unique_id has to be sent in via the card data (as device_unique_identifier) no other fraud detection fields require this
|
174
|
+
if options[:fraud_detection].present?
|
175
|
+
card_data[:fraud_detection] = {} if (options[:fraud_detection][:device_unique_id]).present?
|
176
|
+
card_data[:fraud_detection][:device_unique_identifier] = (options[:fraud_detection][:device_unique_id]) if (options[:fraud_detection][:device_unique_id]).present?
|
177
|
+
end
|
178
|
+
|
173
179
|
# additional data used for Visa transactions
|
174
180
|
card_data[:card_holder_door_number] = options[:card_holder_door_number].to_i if options[:card_holder_door_number]
|
175
181
|
card_data[:card_holder_birthday] = options[:card_holder_birthday] if options[:card_holder_birthday]
|
@@ -210,6 +216,14 @@ module ActiveMerchant #:nodoc:
|
|
210
216
|
hsh[:channel] = options[:channel] if valid_fraud_detection_option?(options[:channel])
|
211
217
|
hsh[:dispatch_method] = options[:dispatch_method] if valid_fraud_detection_option?(options[:dispatch_method])
|
212
218
|
hsh[:csmdds] = options[:csmdds] if valid_fraud_detection_option?(options[:csmdds])
|
219
|
+
hsh[:device_unique_id] = options[:device_unique_id] if valid_fraud_detection_option?(options[:device_unique_id])
|
220
|
+
hsh[:bill_to] = options[:bill_to] if valid_fraud_detection_option?(options[:bill_to])
|
221
|
+
hsh[:purchase_totals] = options[:purchase_totals] if valid_fraud_detection_option?(options[:purchase_totals])
|
222
|
+
hsh[:customer_in_site] = options[:customer_in_site] if valid_fraud_detection_option?(options[:customer_in_site])
|
223
|
+
hsh[:retail_transaction_data] = options[:retail_transaction_data] if valid_fraud_detection_option?(options[:retail_transaction_data])
|
224
|
+
hsh[:ship_to] = options[:ship_to] if valid_fraud_detection_option?(options[:ship_to])
|
225
|
+
hsh[:tax_voucher_required] = options[:tax_voucher_required] if valid_fraud_detection_option?(options[:tax_voucher_required])
|
226
|
+
hsh[:copy_paste_card_data] = options[:copy_paste_card_data] if valid_fraud_detection_option?(options[:copy_paste_card_data])
|
213
227
|
end
|
214
228
|
end
|
215
229
|
|
@@ -287,15 +301,21 @@ module ActiveMerchant #:nodoc:
|
|
287
301
|
error_code = nil
|
288
302
|
if error = response.dig('status_details', 'error')
|
289
303
|
code = error.dig('reason', 'id')
|
290
|
-
|
304
|
+
standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
|
305
|
+
error_code = "#{code}, #{standard_error_code}"
|
291
306
|
error_code ||= error['type']
|
292
307
|
elsif response['error_type']
|
293
308
|
error_code = response['error_type'] if response['validation_errors']
|
294
|
-
elsif
|
309
|
+
elsif response.dig('error', 'validation_errors')
|
310
|
+
error = response.dig('error')
|
295
311
|
validation_errors = error.dig('validation_errors', 0)
|
296
312
|
code = validation_errors['code'] if validation_errors && validation_errors['code']
|
297
313
|
param = validation_errors['param'] if validation_errors && validation_errors['param']
|
298
314
|
error_code = "#{error['error_type']} | #{code} | #{param}" if error['error_type']
|
315
|
+
elsif error = response.dig('error')
|
316
|
+
code = error.dig('reason', 'id')
|
317
|
+
standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
|
318
|
+
error_code = "#{code}, #{standard_error_code}"
|
299
319
|
end
|
300
320
|
|
301
321
|
error_code || STANDARD_ERROR_CODE[:processing_error]
|
@@ -39,6 +39,7 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
|
40
40
|
def purchase(money, payment_method, options = {})
|
41
41
|
request = build_xml_request do |xml|
|
42
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
42
43
|
xml.ssl_transaction_type self.actions[:purchase]
|
43
44
|
xml.ssl_amount amount(money)
|
44
45
|
|
@@ -63,6 +64,7 @@ module ActiveMerchant #:nodoc:
|
|
63
64
|
|
64
65
|
def authorize(money, creditcard, options = {})
|
65
66
|
request = build_xml_request do |xml|
|
67
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
66
68
|
xml.ssl_transaction_type self.actions[:authorize]
|
67
69
|
xml.ssl_amount amount(money)
|
68
70
|
|
@@ -82,6 +84,8 @@ module ActiveMerchant #:nodoc:
|
|
82
84
|
|
83
85
|
def capture(money, authorization, options = {})
|
84
86
|
request = build_xml_request do |xml|
|
87
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
88
|
+
|
85
89
|
if options[:credit_card]
|
86
90
|
xml.ssl_transaction_type self.actions[:capture]
|
87
91
|
xml.ssl_amount amount(money)
|
@@ -107,6 +111,7 @@ module ActiveMerchant #:nodoc:
|
|
107
111
|
|
108
112
|
def refund(money, identification, options = {})
|
109
113
|
request = build_xml_request do |xml|
|
114
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
110
115
|
xml.ssl_transaction_type self.actions[:refund]
|
111
116
|
xml.ssl_amount amount(money)
|
112
117
|
add_txn_id(xml, identification)
|
@@ -117,6 +122,7 @@ module ActiveMerchant #:nodoc:
|
|
117
122
|
|
118
123
|
def void(identification, options = {})
|
119
124
|
request = build_xml_request do |xml|
|
125
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
120
126
|
xml.ssl_transaction_type self.actions[:void]
|
121
127
|
|
122
128
|
add_txn_id(xml, identification)
|
@@ -129,6 +135,7 @@ module ActiveMerchant #:nodoc:
|
|
129
135
|
raise ArgumentError, 'Reference credits are not supported. Please supply the original credit card or use the #refund method.' if creditcard.is_a?(String)
|
130
136
|
|
131
137
|
request = build_xml_request do |xml|
|
138
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
132
139
|
xml.ssl_transaction_type self.actions[:credit]
|
133
140
|
xml.ssl_amount amount(money)
|
134
141
|
add_invoice(xml, options)
|
@@ -143,6 +150,7 @@ module ActiveMerchant #:nodoc:
|
|
143
150
|
|
144
151
|
def verify(credit_card, options = {})
|
145
152
|
request = build_xml_request do |xml|
|
153
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
146
154
|
xml.ssl_transaction_type self.actions[:verify]
|
147
155
|
add_creditcard(xml, credit_card)
|
148
156
|
add_address(xml, options)
|
@@ -154,6 +162,7 @@ module ActiveMerchant #:nodoc:
|
|
154
162
|
|
155
163
|
def store(creditcard, options = {})
|
156
164
|
request = build_xml_request do |xml|
|
165
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
157
166
|
xml.ssl_transaction_type self.actions[:store]
|
158
167
|
xml.ssl_add_token 'Y'
|
159
168
|
add_creditcard(xml, creditcard)
|
@@ -167,6 +176,7 @@ module ActiveMerchant #:nodoc:
|
|
167
176
|
|
168
177
|
def update(token, creditcard, options = {})
|
169
178
|
request = build_xml_request do |xml|
|
179
|
+
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
|
170
180
|
xml.ssl_transaction_type self.actions[:update]
|
171
181
|
add_token(xml, token)
|
172
182
|
add_creditcard(xml, creditcard)
|
@@ -285,10 +295,12 @@ module ActiveMerchant #:nodoc:
|
|
285
295
|
|
286
296
|
def add_auth_purchase_params(xml, options)
|
287
297
|
xml.ssl_dynamic_dba options[:dba] if options.has_key?(:dba)
|
288
|
-
xml.ssl_merchant_initiated_unscheduled options
|
298
|
+
xml.ssl_merchant_initiated_unscheduled merchant_initiated_unscheduled(options) if merchant_initiated_unscheduled(options)
|
289
299
|
xml.ssl_customer_code options[:customer] if options.has_key?(:customer)
|
290
300
|
xml.ssl_customer_number options[:customer_number] if options.has_key?(:customer_number)
|
301
|
+
xml.ssl_entry_mode entry_mode(options) if entry_mode(options)
|
291
302
|
add_custom_fields(xml, options) if options[:custom_fields]
|
303
|
+
add_stored_credential(xml, options) if options[:stored_credential]
|
292
304
|
end
|
293
305
|
|
294
306
|
def add_custom_fields(xml, options)
|
@@ -337,6 +349,32 @@ module ActiveMerchant #:nodoc:
|
|
337
349
|
}
|
338
350
|
end
|
339
351
|
|
352
|
+
def add_stored_credential(xml, options)
|
353
|
+
network_transaction_id = options.dig(:stored_credential, :network_transaction_id)
|
354
|
+
case
|
355
|
+
when network_transaction_id.nil?
|
356
|
+
return
|
357
|
+
when network_transaction_id.to_s.include?('|')
|
358
|
+
oar_data, ps2000_data = options[:stored_credential][:network_transaction_id].split('|')
|
359
|
+
xml.ssl_oar_data oar_data unless oar_data.nil? || oar_data.empty?
|
360
|
+
xml.ssl_ps2000_data ps2000_data unless ps2000_data.nil? || ps2000_data.empty?
|
361
|
+
when network_transaction_id.to_s.length > 22
|
362
|
+
xml.ssl_oar_data options.dig(:stored_credential, :network_transaction_id)
|
363
|
+
else
|
364
|
+
xml.ssl_ps2000_data options.dig(:stored_credential, :network_transaction_id)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def merchant_initiated_unscheduled(options)
|
369
|
+
return options[:merchant_initiated_unscheduled] if options[:merchant_initiated_unscheduled]
|
370
|
+
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
|
371
|
+
end
|
372
|
+
|
373
|
+
def entry_mode(options)
|
374
|
+
return options[:entry_mode] if options[:entry_mode]
|
375
|
+
return 12 if options[:stored_credential]
|
376
|
+
end
|
377
|
+
|
340
378
|
def build_xml_request
|
341
379
|
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
342
380
|
xml.txn do
|
@@ -352,6 +390,7 @@ module ActiveMerchant #:nodoc:
|
|
352
390
|
|
353
391
|
def commit(request)
|
354
392
|
request = "xmldata=#{request}".delete('&')
|
393
|
+
|
355
394
|
response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
|
356
395
|
|
357
396
|
Response.new(
|
@@ -362,10 +401,15 @@ module ActiveMerchant #:nodoc:
|
|
362
401
|
authorization: authorization_from(response),
|
363
402
|
error_code: response[:errorCode],
|
364
403
|
avs_result: { code: response[:avs_response] },
|
365
|
-
cvv_result: response[:cvv2_response]
|
404
|
+
cvv_result: response[:cvv2_response],
|
405
|
+
network_transaction_id: build_network_transaction_id(response)
|
366
406
|
)
|
367
407
|
end
|
368
408
|
|
409
|
+
def build_network_transaction_id(response)
|
410
|
+
"#{response[:oar_data]}|#{response[:ps2000_data]}"
|
411
|
+
end
|
412
|
+
|
369
413
|
def headers
|
370
414
|
{
|
371
415
|
'Accept' => 'application/xml',
|
@@ -383,6 +427,14 @@ module ActiveMerchant #:nodoc:
|
|
383
427
|
def authorization_from(response)
|
384
428
|
[response[:approval_code], response[:txn_id]].join(';')
|
385
429
|
end
|
430
|
+
|
431
|
+
def truncate(value, size)
|
432
|
+
return nil unless value
|
433
|
+
|
434
|
+
difference = value.force_encoding('iso-8859-1').length - value.length
|
435
|
+
|
436
|
+
return value.delete('&"<>').to_s[0, (size - difference)]
|
437
|
+
end
|
386
438
|
end
|
387
439
|
end
|
388
440
|
end
|
@@ -53,6 +53,7 @@ module ActiveMerchant #:nodoc:
|
|
53
53
|
add_invoice(params, amount, options)
|
54
54
|
add_customer_data(params, options, payment_method)
|
55
55
|
add_credit_card(params, payment_method, options)
|
56
|
+
add_3ds_authenticated_data(params, options) if options[:three_d_secure]
|
56
57
|
params['Method'] = payment_method.respond_to?(:number) ? 'ProcessPayment' : 'TokenPayment'
|
57
58
|
commit(url_for('Transaction'), params)
|
58
59
|
end
|
@@ -197,6 +198,18 @@ module ActiveMerchant #:nodoc:
|
|
197
198
|
params
|
198
199
|
end
|
199
200
|
|
201
|
+
def add_3ds_authenticated_data(params, options)
|
202
|
+
three_d_secure_options = options[:three_d_secure]
|
203
|
+
params['PaymentInstrument'] ||= {} if params['PaymentInstrument'].nil?
|
204
|
+
threed_secure_auth = params['PaymentInstrument']['ThreeDSecureAuth'] = {}
|
205
|
+
threed_secure_auth['Cryptogram'] = three_d_secure_options[:cavv]
|
206
|
+
threed_secure_auth['ECI'] = three_d_secure_options[:eci]
|
207
|
+
threed_secure_auth['XID'] = three_d_secure_options[:xid]
|
208
|
+
threed_secure_auth['AuthStatus'] = three_d_secure_options[:authentication_response_status]
|
209
|
+
threed_secure_auth['dsTransactionId'] = three_d_secure_options[:ds_transaction_id]
|
210
|
+
threed_secure_auth['Version'] = three_d_secure_options[:version]
|
211
|
+
end
|
212
|
+
|
200
213
|
def add_invoice(params, money, options, key = 'Payment')
|
201
214
|
currency_code = options[:currency] || currency(money)
|
202
215
|
params[key] = {
|
@@ -212,8 +212,8 @@ module ActiveMerchant #:nodoc:
|
|
212
212
|
xml.tag! 'Expiry_Date', expdate(credit_card)
|
213
213
|
xml.tag! 'CardHoldersName', credit_card.name
|
214
214
|
xml.tag! 'CardType', card_type(credit_card.brand)
|
215
|
-
xml.tag! 'WalletProviderID', options[:wallet_provider_id] if options[:wallet_provider_id]
|
216
215
|
|
216
|
+
add_wallet_provider_id(xml, credit_card, options)
|
217
217
|
add_credit_card_eci(xml, credit_card, options)
|
218
218
|
add_credit_card_verification_strings(xml, credit_card, options)
|
219
219
|
end
|
@@ -221,10 +221,9 @@ module ActiveMerchant #:nodoc:
|
|
221
221
|
|
222
222
|
def add_credit_card_eci(xml, credit_card, options)
|
223
223
|
eci = if credit_card.is_a?(NetworkTokenizationCreditCard) && credit_card.source == :apple_pay && card_brand(credit_card) == 'discover'
|
224
|
-
#
|
225
|
-
#
|
226
|
-
|
227
|
-
'04'
|
224
|
+
# Payeezy requires an ECI of 5 for apple pay transactions
|
225
|
+
# See: https://support.payeezy.com/hc/en-us/articles/203730589-Ecommerce-Flag-Values
|
226
|
+
'05'
|
228
227
|
else
|
229
228
|
(credit_card.respond_to?(:eci) ? credit_card.eci : nil) || options[:eci] || DEFAULT_ECI
|
230
229
|
end
|
@@ -276,10 +275,22 @@ module ActiveMerchant #:nodoc:
|
|
276
275
|
xml.tag! 'Expiry_Date', expdate(credit_card)
|
277
276
|
xml.tag! 'CardHoldersName', credit_card.name
|
278
277
|
xml.tag! 'CardType', card_type(credit_card.brand)
|
279
|
-
|
278
|
+
|
279
|
+
add_wallet_provider_id(xml, credit_card, options)
|
280
280
|
add_card_authentication_data(xml, options)
|
281
281
|
end
|
282
282
|
|
283
|
+
def add_wallet_provider_id(xml, credit_card, options)
|
284
|
+
provider_id = if options[:wallet_provider_id]
|
285
|
+
options[:wallet_provider_id]
|
286
|
+
elsif credit_card.is_a?(NetworkTokenizationCreditCard) && credit_card.source == :apple_pay
|
287
|
+
# See: https://support.payeezy.com/hc/en-us/articles/206601408-First-Data-Payeezy-Gateway-Web-Service-API-Reference-Guide#3.9
|
288
|
+
4
|
289
|
+
end
|
290
|
+
|
291
|
+
xml.tag! 'WalletProviderID', provider_id if provider_id
|
292
|
+
end
|
293
|
+
|
283
294
|
def add_customer_data(xml, options)
|
284
295
|
xml.tag! 'Customer_Ref', options[:customer] if options[:customer]
|
285
296
|
xml.tag! 'Client_IP', options[:ip] if options[:ip]
|
@@ -28,6 +28,7 @@ module ActiveMerchant #:nodoc:
|
|
28
28
|
add_payment_method(post, payment_method, options)
|
29
29
|
add_billing_address(post, payment_method, options)
|
30
30
|
add_shipping_address(post, options)
|
31
|
+
add_xdata(post, options)
|
31
32
|
post[:action] = 'sale'
|
32
33
|
|
33
34
|
commit(:post, post)
|
@@ -41,6 +42,7 @@ module ActiveMerchant #:nodoc:
|
|
41
42
|
add_payment_method(post, payment_method, options)
|
42
43
|
add_billing_address(post, payment_method, options)
|
43
44
|
add_shipping_address(post, options)
|
45
|
+
add_xdata(post, options)
|
44
46
|
post[:action] = 'authorize'
|
45
47
|
|
46
48
|
commit(:post, post)
|
@@ -122,6 +124,16 @@ module ActiveMerchant #:nodoc:
|
|
122
124
|
post[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
|
123
125
|
end
|
124
126
|
|
127
|
+
def add_xdata(post, options)
|
128
|
+
post[:xdata] = {}
|
129
|
+
if xdata = options[:xdata]
|
130
|
+
(1..9).each do |n|
|
131
|
+
field = "xdata_#{n}".to_sym
|
132
|
+
post[:xdata][field] = xdata[field] if xdata[field]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
125
137
|
def add_billing_address(post, payment, options)
|
126
138
|
post[:billing_address] = {}
|
127
139
|
if address = options[:billing_address] || options[:address]
|
@@ -32,6 +32,7 @@ module ActiveMerchant #:nodoc:
|
|
32
32
|
add_address(post, payment, options)
|
33
33
|
add_creator_info(post, options)
|
34
34
|
add_fraud_fields(post, options)
|
35
|
+
add_external_cardholder_authentication_data(post, options)
|
35
36
|
commit(:authorize, post)
|
36
37
|
end
|
37
38
|
|
@@ -200,21 +201,21 @@ module ActiveMerchant #:nodoc:
|
|
200
201
|
shipping_address = options[:shipping_address]
|
201
202
|
if billing_address = options[:billing_address] || options[:address]
|
202
203
|
post['order']['customer']['billingAddress'] = {
|
203
|
-
'street' => billing_address[:address1],
|
204
|
-
'additionalInfo' => billing_address[:address2],
|
204
|
+
'street' => truncate(billing_address[:address1], 50),
|
205
|
+
'additionalInfo' => truncate(billing_address[:address2], 50),
|
205
206
|
'zip' => billing_address[:zip],
|
206
207
|
'city' => billing_address[:city],
|
207
|
-
'state' => billing_address[:state],
|
208
|
+
'state' => truncate(billing_address[:state], 35),
|
208
209
|
'countryCode' => billing_address[:country]
|
209
210
|
}
|
210
211
|
end
|
211
212
|
if shipping_address
|
212
213
|
post['order']['customer']['shippingAddress'] = {
|
213
|
-
'street' => shipping_address[:address1],
|
214
|
-
'additionalInfo' => shipping_address[:address2],
|
214
|
+
'street' => truncate(shipping_address[:address1], 50),
|
215
|
+
'additionalInfo' => truncate(shipping_address[:address2], 50),
|
215
216
|
'zip' => shipping_address[:zip],
|
216
217
|
'city' => shipping_address[:city],
|
217
|
-
'state' => shipping_address[:state],
|
218
|
+
'state' => truncate(shipping_address[:state], 35),
|
218
219
|
'countryCode' => shipping_address[:country]
|
219
220
|
}
|
220
221
|
post['order']['customer']['shippingAddress']['name'] = {
|
@@ -232,6 +233,24 @@ module ActiveMerchant #:nodoc:
|
|
232
233
|
post['fraudFields'] = fraud_fields unless fraud_fields.empty?
|
233
234
|
end
|
234
235
|
|
236
|
+
def add_external_cardholder_authentication_data(post, options)
|
237
|
+
return unless threeds_2_options = options[:three_d_secure]
|
238
|
+
|
239
|
+
authentication_data = {}
|
240
|
+
authentication_data[:acsTransactionId] = threeds_2_options[:acs_transaction_id] if threeds_2_options[:acs_transaction_id]
|
241
|
+
authentication_data[:cavv] = threeds_2_options[:cavv] if threeds_2_options[:cavv]
|
242
|
+
authentication_data[:cavvAlgorithm] = threeds_2_options[:cavv_algorithm] if threeds_2_options[:cavv_algorithm]
|
243
|
+
authentication_data[:directoryServerTransactionId] = threeds_2_options[:ds_transaction_id] if threeds_2_options[:ds_transaction_id]
|
244
|
+
authentication_data[:eci] = threeds_2_options[:eci] if threeds_2_options[:eci]
|
245
|
+
authentication_data[:threeDSecureVersion] = threeds_2_options[:version] if threeds_2_options[:version]
|
246
|
+
authentication_data[:validationResult] = threeds_2_options[:authentication_response_status] if threeds_2_options[:authentication_response_status]
|
247
|
+
authentication_data[:xid] = threeds_2_options[:xid] if threeds_2_options[:xid]
|
248
|
+
|
249
|
+
post['cardPaymentMethodSpecificInput'] ||= {}
|
250
|
+
post['cardPaymentMethodSpecificInput']['threeDSecure'] ||= {}
|
251
|
+
post['cardPaymentMethodSpecificInput']['threeDSecure']['externalCardholderAuthenticationData'] = authentication_data unless authentication_data.empty?
|
252
|
+
end
|
253
|
+
|
235
254
|
def add_number_of_installments(post, options)
|
236
255
|
post['order']['additionalInput']['numberOfInstallments'] = options[:number_of_installments] if options[:number_of_installments]
|
237
256
|
end
|
@@ -39,6 +39,7 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
add_descriptor_name(xml, options)
|
40
40
|
add_card_or_token_payment(xml, card_or_token, options)
|
41
41
|
add_three_d_secure(xml, card_or_token, options)
|
42
|
+
add_stored_credentials(xml, options)
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
@@ -52,6 +53,8 @@ module ActiveMerchant #:nodoc:
|
|
52
53
|
def purchase(money, payment_method, options = {})
|
53
54
|
if payment_method.is_a?(Check)
|
54
55
|
commit_check_sale(money, payment_method, options)
|
56
|
+
elsif options.dig(:stored_credential, :reason_type) == 'recurring'
|
57
|
+
commit_recurring_billing_sale(money, payment_method, options)
|
55
58
|
else
|
56
59
|
commit_credit_sale(money, payment_method, options)
|
57
60
|
end
|
@@ -67,6 +70,15 @@ module ActiveMerchant #:nodoc:
|
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
73
|
+
def credit(money, payment_method, options = {})
|
74
|
+
commit('CreditReturn') do |xml|
|
75
|
+
add_amount(xml, money)
|
76
|
+
add_allow_dup(xml)
|
77
|
+
add_card_or_token_payment(xml, payment_method, options)
|
78
|
+
add_details(xml, options)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
70
82
|
def verify(card_or_token, options = {})
|
71
83
|
commit('CreditAccountVerify') do |xml|
|
72
84
|
add_card_or_token_customer_data(xml, card_or_token, options)
|
@@ -122,6 +134,21 @@ module ActiveMerchant #:nodoc:
|
|
122
134
|
add_descriptor_name(xml, options)
|
123
135
|
add_card_or_token_payment(xml, card_or_token, options)
|
124
136
|
add_three_d_secure(xml, card_or_token, options)
|
137
|
+
add_stored_credentials(xml, options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def commit_recurring_billing_sale(money, card_or_token, options)
|
142
|
+
commit('RecurringBilling') do |xml|
|
143
|
+
add_amount(xml, money)
|
144
|
+
add_allow_dup(xml)
|
145
|
+
add_card_or_token_customer_data(xml, card_or_token, options)
|
146
|
+
add_details(xml, options)
|
147
|
+
add_descriptor_name(xml, options)
|
148
|
+
add_card_or_token_payment(xml, card_or_token, options)
|
149
|
+
add_three_d_secure(xml, card_or_token, options)
|
150
|
+
add_stored_credentials(xml, options)
|
151
|
+
add_stored_credentials_for_recurring_billing(xml, options)
|
125
152
|
end
|
126
153
|
end
|
127
154
|
|
@@ -148,7 +175,7 @@ module ActiveMerchant #:nodoc:
|
|
148
175
|
xml.hps :CardHolderAddr, billing_address[:address1] if billing_address[:address1]
|
149
176
|
xml.hps :CardHolderCity, billing_address[:city] if billing_address[:city]
|
150
177
|
xml.hps :CardHolderState, billing_address[:state] if billing_address[:state]
|
151
|
-
xml.hps :CardHolderZip, billing_address[:zip] if billing_address[:zip]
|
178
|
+
xml.hps :CardHolderZip, alphanumeric_zip(billing_address[:zip]) if billing_address[:zip]
|
152
179
|
end
|
153
180
|
end
|
154
181
|
end
|
@@ -210,7 +237,7 @@ module ActiveMerchant #:nodoc:
|
|
210
237
|
def add_details(xml, options)
|
211
238
|
xml.hps :AdditionalTxnFields do
|
212
239
|
xml.hps :Description, options[:description] if options[:description]
|
213
|
-
xml.hps :InvoiceNbr, options[:order_id] if options[:order_id]
|
240
|
+
xml.hps :InvoiceNbr, options[:order_id][0..59] if options[:order_id]
|
214
241
|
xml.hps :CustomerID, options[:customer_id] if options[:customer_id]
|
215
242
|
end
|
216
243
|
end
|
@@ -256,6 +283,38 @@ module ActiveMerchant #:nodoc:
|
|
256
283
|
end
|
257
284
|
end
|
258
285
|
|
286
|
+
# We do not currently support installments on this gateway.
|
287
|
+
# The HPS gateway treats recurring transactions as a seperate transaction type
|
288
|
+
def add_stored_credentials(xml, options)
|
289
|
+
return unless options[:stored_credential]
|
290
|
+
|
291
|
+
xml.hps :CardOnFileData do
|
292
|
+
if options[:stored_credential][:initiator] == 'customer'
|
293
|
+
xml.hps :CardOnFile, 'C'
|
294
|
+
elsif options[:stored_credential][:initiator] == 'merchant'
|
295
|
+
xml.hps :CardOnFile, 'M'
|
296
|
+
else
|
297
|
+
return
|
298
|
+
end
|
299
|
+
|
300
|
+
if options[:stored_credential][:network_transaction_id]
|
301
|
+
xml.hps :CardBrandTxnId, options[:stored_credential][:network_transaction_id]
|
302
|
+
else
|
303
|
+
return
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def add_stored_credentials_for_recurring_billing(xml, options)
|
309
|
+
xml.hps :RecurringData do
|
310
|
+
if options[:stored_credential][:reason_type] = 'recurring'
|
311
|
+
xml.hps :OneTime, 'N'
|
312
|
+
else
|
313
|
+
xml.hps :OneTime, 'Y'
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
259
318
|
def strip_leading_zero(value)
|
260
319
|
return value unless value[0] == '0'
|
261
320
|
|
@@ -380,6 +439,10 @@ module ActiveMerchant #:nodoc:
|
|
380
439
|
@options[:secret_api_key]&.include?('_cert_')
|
381
440
|
end
|
382
441
|
|
442
|
+
def alphanumeric_zip(zip)
|
443
|
+
zip.gsub(/[^0-9a-z]/i, '')
|
444
|
+
end
|
445
|
+
|
383
446
|
ISSUER_MESSAGES = {
|
384
447
|
'13' => 'Must be greater than or equal 0.',
|
385
448
|
'14' => 'The card number is incorrect.',
|