activemerchant 1.129.0 → 1.133.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +51 -1
- data/lib/active_merchant/billing/credit_card.rb +2 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +7 -3
- data/lib/active_merchant/billing/gateways/adyen.rb +82 -2
- data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
- data/lib/active_merchant/billing/gateways/borgun.rb +11 -8
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +8 -7
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +15 -8
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +13 -4
- data/lib/active_merchant/billing/gateways/cyber_source.rb +32 -7
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +6 -8
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +41 -19
- data/lib/active_merchant/billing/gateways/ipg.rb +1 -1
- data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
- data/lib/active_merchant/billing/gateways/mit.rb +18 -18
- data/lib/active_merchant/billing/gateways/nmi.rb +5 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +2 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +1 -1
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +1 -1
- data/lib/active_merchant/billing/gateways/redsys.rb +2 -1
- data/lib/active_merchant/billing/gateways/safe_charge.rb +2 -1
- data/lib/active_merchant/billing/gateways/shift4.rb +5 -2
- data/lib/active_merchant/billing/gateways/stripe.rb +21 -5
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +111 -68
- data/lib/active_merchant/billing/gateways/vpos.rb +1 -1
- data/lib/active_merchant/billing/gateways/worldpay.rb +12 -24
- data/lib/active_merchant/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d705df588bf311375b4dfc46da6912709e0aaecc7bd1800e69af7b61fcfa23b
|
4
|
+
data.tar.gz: 80ae4869bcbf875c2ef0bd7b5b257641c1810bc5110958a66d1cda956e6a994a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba783e41a2872b825b73e5b20c6084e2d4b7200ab899a91ee6aa31977c6e4b3da651f96cd3c895417a8e3e70fdd84cd082a7450eb8a2d35c48b4fc2410ea2c02
|
7
|
+
data.tar.gz: b6c1718e9160fdf16745eff1758f5ffc25cbdd6a4bb219c4e13510e3a40b998f9f01b1426985fcb8b987cf73c1c5e8a760a4ffb8b506459ce4501ddb242bedb4
|
data/CHANGELOG
CHANGED
@@ -3,7 +3,57 @@
|
|
3
3
|
|
4
4
|
== HEAD
|
5
5
|
|
6
|
-
== Version 1.
|
6
|
+
== Version 1.133.0 (July 20, 2023)
|
7
|
+
* CyberSource: remove credentials from tests [bbraschi] #4836
|
8
|
+
|
9
|
+
== Version 1.132.0 (July 20, 2023)
|
10
|
+
* Stripe Payment Intents: Add support for new card on file field [aenand] #4807
|
11
|
+
* Commerce Hub: Add `physicalGoodsIndicator` and `schemeReferenceTransactionId` GSFs [sinourain] #4786
|
12
|
+
* Nuvei (formerly SafeCharge): Add customer details to credit action [yunnydang] #4820
|
13
|
+
* IPG: Update live url to correct endpoint [curiousepic] #4121
|
14
|
+
* VPos: Adding Panal Credit Card type [jherreraa] #4814
|
15
|
+
* Stripe PI: Update parameters for creation of customer [almalee24] #4782
|
16
|
+
* WorldPay: Update xml tag for Credit Cards [almalee24] #4797
|
17
|
+
* PaywayDotCom: update `live_url` [jcreiff] #4824
|
18
|
+
* Stripe & Stripe PI: Update login key validation [almalee24] #4816
|
19
|
+
* CheckoutV2: Parse the AVS and CVV checks more often [aenand] #4822
|
20
|
+
* NMI: Add shipping_firstname, shipping_lastname, shipping_email, and surcharge fields [jcreiff] #4825
|
21
|
+
* Borgun: Update authorization_from & message_from [almalee24] #4826
|
22
|
+
* Kushki: Add Brazil as supported country [almalee24] #4829
|
23
|
+
* Adyen: Add additional data for airline and lodging [javierpedrozaing] #4815
|
24
|
+
* MIT: Changed how the payload was sent to the gateway [alejandrofloresm] #4655
|
25
|
+
* SafeCharge: Add unreferenced_refund field [yunnydang] #4831
|
26
|
+
* CyberSource: include `paymentSolution` for ApplePay and GooglePay [bbraschi] #4835
|
27
|
+
|
28
|
+
== Version 1.131.0 (June 21, 2023)
|
29
|
+
* Redsys: Add supported countries [jcreiff] #4811
|
30
|
+
* Authorize.net: Truncate nameOnAccount for bank refunds [jcreiff] #4808
|
31
|
+
* CheckoutV2: Add support for several customer data fields [rachelkirk] #4800
|
32
|
+
* Worldpay: check payment_method responds to payment_cryptogram and eci [bbraschi] #4812
|
33
|
+
|
34
|
+
== Version 1.130.0 (June 13th, 2023)
|
35
|
+
* Payu Latam - Update error code method to surface network code [yunnydang] #4773
|
36
|
+
* CyberSource: Handling Canadian bank accounts [heavyblade] #4764
|
37
|
+
* CyberSource Rest: Fixing currency detection [heavyblade] #4777
|
38
|
+
* CyberSource: Allow business rules for requests with network tokens [aenand] #4764
|
39
|
+
* Adyen: Update Mastercard error messaging [kylene-spreedly] #4770
|
40
|
+
* Authorize.net: Update mapping for billing address phone number [jcreiff] #4778
|
41
|
+
* Braintree: Update mapping for billing address phone number [jcreiff] #4779
|
42
|
+
* CommerceHub: Enabling multi-use public key encryption [jherreraa] #4771
|
43
|
+
* Ogone: Enable 3ds Global for Ogone Gateway [javierpedrozaing] #4776
|
44
|
+
* Worldpay: Fix Google Pay [almalee24] #4774
|
45
|
+
* Borgun change default TrCurrencyExponent and MerchantReturnUrl [naashton] #4788
|
46
|
+
* Borgun: support for GBP currency [naashton] #4789
|
47
|
+
* CyberSource: Enable auto void on r230 [aenand] #4794
|
48
|
+
* Redsys: Set appropriate request fields for stored credentials with CITs and MITs [BritneyS] #4784
|
49
|
+
* Stripe & Stripe PI: Validate API Key [almalee24] #4801
|
50
|
+
* Add BIN for Maestro [jcreiff] #4799
|
51
|
+
* D_Local: Add save field on card object [yunnydang] #4805
|
52
|
+
* PayPal Express: Adds support for MsgSubID property on DoReferenceTransaction and DoExpressCheckoutPayment [wikiti] #4798
|
53
|
+
* Checkout_v2: use credit_card?, not case equality with CreditCard [bbraschi] #4803
|
54
|
+
* Shift4: Enable general credit feature [jherreraa] #4790
|
55
|
+
|
56
|
+
== Version 1.129.0 (May 3rd, 2023)
|
7
57
|
* Adyen: Update selectedBrand mapping for Google Pay [jcreiff] #4763
|
8
58
|
* Shift4: Add vendorReference field [jcreiff] #4762
|
9
59
|
* Shift4: Add OAuth error [aenand] #4760
|
@@ -38,6 +38,7 @@ module ActiveMerchant #:nodoc:
|
|
38
38
|
# * Edenred
|
39
39
|
# * Anda
|
40
40
|
# * Creditos directos (Tarjeta D)
|
41
|
+
# * Panal
|
41
42
|
#
|
42
43
|
# For testing purposes, use the 'bogus' credit card brand. This skips the vast majority of
|
43
44
|
# validations, allowing you to focus on your core concerns until you're ready to be more concerned
|
@@ -130,6 +131,7 @@ module ActiveMerchant #:nodoc:
|
|
130
131
|
# * +'edenred'+
|
131
132
|
# * +'anda'+
|
132
133
|
# * +'tarjeta-d'+
|
134
|
+
# * +'panal'+
|
133
135
|
#
|
134
136
|
# Or, if you wish to test your implementation, +'bogus'+.
|
135
137
|
#
|
@@ -46,7 +46,8 @@ module ActiveMerchant #:nodoc:
|
|
46
46
|
'edenred' => ->(num) { num =~ /^637483\d{10}$/ },
|
47
47
|
'anda' => ->(num) { num =~ /^603199\d{10}$/ },
|
48
48
|
'tarjeta-d' => ->(num) { num =~ /^601828\d{10}$/ },
|
49
|
-
'hipercard' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), HIPERCARD_RANGES) }
|
49
|
+
'hipercard' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), HIPERCARD_RANGES) },
|
50
|
+
'panal' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), PANAL_RANGES) }
|
50
51
|
}
|
51
52
|
|
52
53
|
SODEXO_NO_LUHN = ->(num) { num =~ /^(505864|505865)\d{10}$/ }
|
@@ -109,7 +110,7 @@ module ActiveMerchant #:nodoc:
|
|
109
110
|
MAESTRO_BINS = Set.new(
|
110
111
|
%w[ 500057
|
111
112
|
501018 501043 501045 501047 501049 501051 501072 501075 501083 501087 501089 501095
|
112
|
-
501500
|
113
|
+
501500 501623
|
113
114
|
501879 502113 502120 502121 502301
|
114
115
|
503175 503337 503645 503670
|
115
116
|
504310 504338 504363 504533 504587 504620 504639 504656 504738 504781 504910
|
@@ -182,7 +183,8 @@ module ActiveMerchant #:nodoc:
|
|
182
183
|
(601256..601276),
|
183
184
|
(601640..601652),
|
184
185
|
(601689..601700),
|
185
|
-
(602011..
|
186
|
+
(602011..602048),
|
187
|
+
[602050],
|
186
188
|
(630400..630499),
|
187
189
|
(639000..639099),
|
188
190
|
(670000..679999),
|
@@ -247,6 +249,8 @@ module ActiveMerchant #:nodoc:
|
|
247
249
|
637568..637568, 637599..637599, 637609..637609, 637612..637612
|
248
250
|
]
|
249
251
|
|
252
|
+
PANAL_RANGES = [[602049]]
|
253
|
+
|
250
254
|
def self.included(base)
|
251
255
|
base.extend(ClassMethods)
|
252
256
|
end
|
@@ -68,6 +68,8 @@ module ActiveMerchant #:nodoc:
|
|
68
68
|
add_application_info(post, options)
|
69
69
|
add_level_2_data(post, options)
|
70
70
|
add_level_3_data(post, options)
|
71
|
+
add_data_airline(post, options)
|
72
|
+
add_data_lodging(post, options)
|
71
73
|
commit('authorise', post, options)
|
72
74
|
end
|
73
75
|
|
@@ -291,6 +293,84 @@ module ActiveMerchant #:nodoc:
|
|
291
293
|
post[:additionalData].compact!
|
292
294
|
end
|
293
295
|
|
296
|
+
def add_data_airline(post, options)
|
297
|
+
return unless options[:additional_data_airline]
|
298
|
+
|
299
|
+
mapper = %w[
|
300
|
+
agency_invoice_number
|
301
|
+
agency_plan_name
|
302
|
+
airline_code
|
303
|
+
airline_designator_code
|
304
|
+
boarding_fee
|
305
|
+
computerized_reservation_system
|
306
|
+
customer_reference_number
|
307
|
+
document_type
|
308
|
+
flight_date
|
309
|
+
ticket_issue_address
|
310
|
+
ticket_number
|
311
|
+
travel_agency_code
|
312
|
+
travel_agency_name
|
313
|
+
passenger_name
|
314
|
+
].each_with_object({}) { |value, hash| hash["airline.#{value}"] = value }
|
315
|
+
|
316
|
+
post[:additionalData].merge!(extract_and_transform(mapper, options[:additional_data_airline]))
|
317
|
+
|
318
|
+
if options[:additional_data_airline][:leg].present?
|
319
|
+
leg_data = %w[
|
320
|
+
carrier_code
|
321
|
+
class_of_travel
|
322
|
+
date_of_travel
|
323
|
+
depart_airport
|
324
|
+
depart_tax
|
325
|
+
destination_code
|
326
|
+
fare_base_code
|
327
|
+
flight_number
|
328
|
+
stop_over_code
|
329
|
+
].each_with_object({}) { |value, hash| hash["airline.leg.#{value}"] = value }
|
330
|
+
|
331
|
+
post[:additionalData].merge!(extract_and_transform(leg_data, options[:additional_data_airline][:leg]))
|
332
|
+
end
|
333
|
+
|
334
|
+
if options[:additional_data_airline][:passenger].present?
|
335
|
+
passenger_data = %w[
|
336
|
+
date_of_birth
|
337
|
+
first_name
|
338
|
+
last_name
|
339
|
+
telephone_number
|
340
|
+
traveller_type
|
341
|
+
].each_with_object({}) { |value, hash| hash["airline.passenger.#{value}"] = value }
|
342
|
+
|
343
|
+
post[:additionalData].merge!(extract_and_transform(passenger_data, options[:additional_data_airline][:passenger]))
|
344
|
+
end
|
345
|
+
post[:additionalData].compact!
|
346
|
+
end
|
347
|
+
|
348
|
+
def add_data_lodging(post, options)
|
349
|
+
return unless options[:additional_data_lodging]
|
350
|
+
|
351
|
+
mapper = {
|
352
|
+
'lodging.checkInDate': 'check_in_date',
|
353
|
+
'lodging.checkOutDate': 'check_out_date',
|
354
|
+
'lodging.customerServiceTollFreeNumber': 'customer_service_toll_free_number',
|
355
|
+
'lodging.fireSafetyActIndicator': 'fire_safety_act_indicator',
|
356
|
+
'lodging.folioCashAdvances': 'folio_cash_advances',
|
357
|
+
'lodging.folioNumber': 'folio_number',
|
358
|
+
'lodging.foodBeverageCharges': 'food_beverage_charges',
|
359
|
+
'lodging.noShowIndicator': 'no_show_indicator',
|
360
|
+
'lodging.prepaidExpenses': 'prepaid_expenses',
|
361
|
+
'lodging.propertyPhoneNumber': 'property_phone_number',
|
362
|
+
'lodging.room1.numberOfNights': 'number_of_nights',
|
363
|
+
'lodging.room1.rate': 'rate',
|
364
|
+
'lodging.totalRoomTax': 'total_room_tax',
|
365
|
+
'lodging.totalTax': 'totalTax',
|
366
|
+
'travelEntertainmentAuthData.duration': 'duration',
|
367
|
+
'travelEntertainmentAuthData.market': 'market'
|
368
|
+
}
|
369
|
+
|
370
|
+
post[:additionalData].merge!(extract_and_transform(mapper, options[:additional_data_lodging]))
|
371
|
+
post[:additionalData].compact!
|
372
|
+
end
|
373
|
+
|
294
374
|
def add_shopper_data(post, options)
|
295
375
|
post[:shopperEmail] = options[:email] if options[:email]
|
296
376
|
post[:shopperEmail] = options[:shopper_email] if options[:shopper_email]
|
@@ -703,8 +783,8 @@ module ActiveMerchant #:nodoc:
|
|
703
783
|
end
|
704
784
|
|
705
785
|
def authorize_message_from(response)
|
706
|
-
if response['refusalReason'] && response['additionalData'] && response['additionalData']['refusalReasonRaw']
|
707
|
-
"#{response['refusalReason']} | #{response['additionalData']['refusalReasonRaw']}"
|
786
|
+
if response['refusalReason'] && response['additionalData'] && (response['additionalData']['merchantAdviceCode'] || response['additionalData']['refusalReasonRaw'])
|
787
|
+
"#{response['refusalReason']} | #{response['additionalData']['merchantAdviceCode'] || response['additionalData']['refusalReasonRaw']}"
|
708
788
|
else
|
709
789
|
response['refusalReason'] || response['resultCode'] || response['message'] || response['result']
|
710
790
|
end
|
@@ -362,7 +362,7 @@ module ActiveMerchant
|
|
362
362
|
xml.accountType(options[:account_type])
|
363
363
|
xml.routingNumber(options[:routing_number])
|
364
364
|
xml.accountNumber(options[:account_number])
|
365
|
-
xml.nameOnAccount("#{options[:first_name]} #{options[:last_name]}")
|
365
|
+
xml.nameOnAccount(truncate("#{options[:first_name]} #{options[:last_name]}", 22))
|
366
366
|
end
|
367
367
|
else
|
368
368
|
xml.creditCard do
|
@@ -604,6 +604,7 @@ module ActiveMerchant
|
|
604
604
|
first_name, last_name = names_from(payment_source, address, options)
|
605
605
|
state = state_from(address, options)
|
606
606
|
full_address = "#{address[:address1]} #{address[:address2]}".strip
|
607
|
+
phone = address[:phone] || address[:phone_number] || ''
|
607
608
|
|
608
609
|
xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
|
609
610
|
xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
|
@@ -613,7 +614,7 @@ module ActiveMerchant
|
|
613
614
|
xml.state(truncate(state, 40))
|
614
615
|
xml.zip(truncate((address[:zip] || options[:zip]), 20))
|
615
616
|
xml.country(truncate(address[:country], 60))
|
616
|
-
xml.phoneNumber(truncate(
|
617
|
+
xml.phoneNumber(truncate(phone, 25)) unless empty?(phone)
|
617
618
|
xml.faxNumber(truncate(address[:fax], 25)) unless empty?(address[:fax])
|
618
619
|
end
|
619
620
|
end
|
@@ -96,6 +96,7 @@ module ActiveMerchant #:nodoc:
|
|
96
96
|
CURRENCY_CODES['ISK'] = '352'
|
97
97
|
CURRENCY_CODES['EUR'] = '978'
|
98
98
|
CURRENCY_CODES['USD'] = '840'
|
99
|
+
CURRENCY_CODES['GBP'] = '826'
|
99
100
|
|
100
101
|
def add_3ds_fields(post, options)
|
101
102
|
post[:ThreeDSMessageId] = options[:three_ds_message_id] if options[:three_ds_message_id]
|
@@ -105,17 +106,17 @@ module ActiveMerchant #:nodoc:
|
|
105
106
|
|
106
107
|
def add_3ds_preauth_fields(post, options)
|
107
108
|
post[:SaleDescription] = options[:sale_description] || ''
|
108
|
-
post[:MerchantReturnURL] = options[:
|
109
|
+
post[:MerchantReturnURL] = options[:redirect_url] if options[:redirect_url]
|
109
110
|
end
|
110
111
|
|
111
112
|
def add_invoice(post, money, options)
|
112
113
|
post[:TrAmount] = amount(money)
|
113
114
|
post[:TrCurrency] = CURRENCY_CODES[options[:currency] || currency(money)]
|
114
115
|
# The ISK currency must have a currency exponent of 2 on the 3DS request but not on the auth request
|
115
|
-
if post[:TrCurrency] == '352' && options[:apply_3d_secure]
|
116
|
-
post[:TrCurrencyExponent] = 2
|
117
|
-
else
|
116
|
+
if post[:TrCurrency] == '352' && options[:apply_3d_secure] != '1'
|
118
117
|
post[:TrCurrencyExponent] = 0
|
118
|
+
else
|
119
|
+
post[:TrCurrencyExponent] = 2
|
119
120
|
end
|
120
121
|
post[:TerminalID] = options[:terminal_id] || '1'
|
121
122
|
end
|
@@ -171,7 +172,7 @@ module ActiveMerchant #:nodoc:
|
|
171
172
|
success,
|
172
173
|
message_from(success, pairs),
|
173
174
|
pairs,
|
174
|
-
authorization: authorization_from(pairs),
|
175
|
+
authorization: authorization_from(pairs, options),
|
175
176
|
test: test?
|
176
177
|
)
|
177
178
|
end
|
@@ -184,12 +185,12 @@ module ActiveMerchant #:nodoc:
|
|
184
185
|
if succeeded
|
185
186
|
'Succeeded'
|
186
187
|
else
|
187
|
-
response[:message] || "Error with ActionCode=#{response[:actioncode]}"
|
188
|
+
response[:message] || response[:status_errormessage] || "Error with ActionCode=#{response[:actioncode]}"
|
188
189
|
end
|
189
190
|
end
|
190
191
|
|
191
|
-
def authorization_from(response)
|
192
|
-
[
|
192
|
+
def authorization_from(response, options)
|
193
|
+
authorization = [
|
193
194
|
response[:dateandtime],
|
194
195
|
response[:batch],
|
195
196
|
response[:transaction],
|
@@ -199,6 +200,8 @@ module ActiveMerchant #:nodoc:
|
|
199
200
|
response[:tramount],
|
200
201
|
response[:trcurrency]
|
201
202
|
].join('|')
|
203
|
+
|
204
|
+
authorization == '|||||||' ? nil : authorization
|
202
205
|
end
|
203
206
|
|
204
207
|
def split_authorization(authorization)
|
@@ -197,8 +197,7 @@ module ActiveMerchant #:nodoc:
|
|
197
197
|
first_name: creditcard.first_name,
|
198
198
|
last_name: creditcard.last_name,
|
199
199
|
email: scrub_email(options[:email]),
|
200
|
-
phone:
|
201
|
-
options[:billing_address][:phone]),
|
200
|
+
phone: phone_from(options),
|
202
201
|
credit_card: credit_card_params)
|
203
202
|
Response.new(result.success?, message_from_result(result),
|
204
203
|
braintree_customer: (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
|
@@ -267,8 +266,7 @@ module ActiveMerchant #:nodoc:
|
|
267
266
|
first_name: creditcard.first_name,
|
268
267
|
last_name: creditcard.last_name,
|
269
268
|
email: scrub_email(options[:email]),
|
270
|
-
phone:
|
271
|
-
options[:billing_address][:phone]),
|
269
|
+
phone: phone_from(options),
|
272
270
|
id: options[:customer],
|
273
271
|
device_data: options[:device_data]
|
274
272
|
}.merge credit_card_params
|
@@ -348,6 +346,10 @@ module ActiveMerchant #:nodoc:
|
|
348
346
|
parameters
|
349
347
|
end
|
350
348
|
|
349
|
+
def phone_from(options)
|
350
|
+
options[:phone] || options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
|
351
|
+
end
|
352
|
+
|
351
353
|
def map_address(address)
|
352
354
|
mapped = {
|
353
355
|
street_address: address[:address1],
|
@@ -628,8 +630,7 @@ module ActiveMerchant #:nodoc:
|
|
628
630
|
customer: {
|
629
631
|
id: options[:store] == true ? '' : options[:store],
|
630
632
|
email: scrub_email(options[:email]),
|
631
|
-
phone:
|
632
|
-
options[:billing_address][:phone])
|
633
|
+
phone: phone_from(options)
|
633
634
|
},
|
634
635
|
options: {
|
635
636
|
store_in_vault: options[:store] ? true : false,
|
@@ -932,7 +933,7 @@ module ActiveMerchant #:nodoc:
|
|
932
933
|
first_name: payment_method.first_name,
|
933
934
|
last_name: payment_method.last_name,
|
934
935
|
email: scrub_email(options[:email]),
|
935
|
-
phone: options
|
936
|
+
phone: phone_from(options),
|
936
937
|
device_data: options[:device_data]
|
937
938
|
}.compact
|
938
939
|
|
@@ -139,6 +139,7 @@ module ActiveMerchant #:nodoc:
|
|
139
139
|
add_authorization_type(post, options)
|
140
140
|
add_payment_method(post, payment_method, options)
|
141
141
|
add_customer_data(post, options)
|
142
|
+
add_extra_customer_data(post, payment_method, options)
|
142
143
|
add_shipping_address(post, options)
|
143
144
|
add_stored_credential_options(post, options)
|
144
145
|
add_transaction_data(post, options)
|
@@ -185,7 +186,7 @@ module ActiveMerchant #:nodoc:
|
|
185
186
|
post[key][:token_type] = token_type
|
186
187
|
post[key][:cryptogram] = cryptogram if cryptogram
|
187
188
|
post[key][:eci] = eci if eci
|
188
|
-
when
|
189
|
+
when ->(pm) { pm.try(:credit_card?) }
|
189
190
|
post[key][:type] = 'card'
|
190
191
|
post[key][:name] = payment_method.name
|
191
192
|
post[key][:number] = payment_method.number
|
@@ -239,6 +240,15 @@ module ActiveMerchant #:nodoc:
|
|
239
240
|
end
|
240
241
|
end
|
241
242
|
|
243
|
+
# created a separate method for these fields because they should not be included
|
244
|
+
# in all transaction types that include methods with source and customer fields
|
245
|
+
def add_extra_customer_data(post, payment_method, options)
|
246
|
+
post[:source][:phone] = {}
|
247
|
+
post[:source][:phone][:number] = options[:phone] || options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
|
248
|
+
post[:source][:phone][:country_code] = options[:phone_country_code] if options[:phone_country_code]
|
249
|
+
post[:customer][:name] = payment_method.name if payment_method.respond_to?(:name)
|
250
|
+
end
|
251
|
+
|
242
252
|
def add_shipping_address(post, options)
|
243
253
|
if address = options[:shipping_address]
|
244
254
|
post[:shipping] = {}
|
@@ -353,9 +363,6 @@ module ActiveMerchant #:nodoc:
|
|
353
363
|
end
|
354
364
|
|
355
365
|
def response(action, succeeded, response, source_id = nil)
|
356
|
-
successful_response = succeeded && action == :purchase || action == :authorize
|
357
|
-
avs_result = successful_response ? avs_result(response) : nil
|
358
|
-
cvv_result = successful_response ? cvv_result(response) : nil
|
359
366
|
authorization = authorization_from(response) unless action == :unstore
|
360
367
|
body = action == :unstore ? { response_code: response.to_s } : response
|
361
368
|
Response.new(
|
@@ -365,8 +372,8 @@ module ActiveMerchant #:nodoc:
|
|
365
372
|
authorization: authorization,
|
366
373
|
error_code: error_code_from(succeeded, body),
|
367
374
|
test: test?,
|
368
|
-
avs_result: avs_result,
|
369
|
-
cvv_result: cvv_result
|
375
|
+
avs_result: avs_result(response),
|
376
|
+
cvv_result: cvv_result(response)
|
370
377
|
)
|
371
378
|
end
|
372
379
|
|
@@ -417,11 +424,11 @@ module ActiveMerchant #:nodoc:
|
|
417
424
|
end
|
418
425
|
|
419
426
|
def avs_result(response)
|
420
|
-
response
|
427
|
+
response.respond_to?(:dig) && response.dig('source', 'avs_check') ? AVSResult.new(code: response['source']['avs_check']) : nil
|
421
428
|
end
|
422
429
|
|
423
430
|
def cvv_result(response)
|
424
|
-
response
|
431
|
+
response.respond_to?(:dig) && response.dig('source', 'cvv_check') ? CVVResult.new(response['source']['cvv_check']) : nil
|
425
432
|
end
|
426
433
|
|
427
434
|
def parse(body, error: nil)
|
@@ -114,13 +114,17 @@ module ActiveMerchant #:nodoc:
|
|
114
114
|
post[:transactionInteraction][:origin] = options[:origin] || 'ECOM'
|
115
115
|
post[:transactionInteraction][:eciIndicator] = options[:eci_indicator] || 'CHANNEL_ENCRYPTED'
|
116
116
|
post[:transactionInteraction][:posConditionCode] = options[:pos_condition_code] || 'CARD_NOT_PRESENT_ECOM'
|
117
|
-
post[:transactionInteraction][:posEntryMode] = options[:pos_entry_mode] || 'MANUAL'
|
117
|
+
post[:transactionInteraction][:posEntryMode] = (options[:pos_entry_mode] || 'MANUAL') unless options[:encryption_data].present?
|
118
118
|
post[:transactionInteraction][:additionalPosInformation] = {}
|
119
119
|
post[:transactionInteraction][:additionalPosInformation][:dataEntrySource] = options[:data_entry_source] || 'UNSPECIFIED'
|
120
120
|
end
|
121
121
|
|
122
122
|
def add_transaction_details(post, options, action = nil)
|
123
|
-
details = {
|
123
|
+
details = {
|
124
|
+
captureFlag: options[:capture_flag],
|
125
|
+
createToken: options[:create_token],
|
126
|
+
physicalGoodsIndicator: [true, 'true'].include?(options[:physical_goods_indicator])
|
127
|
+
}
|
124
128
|
|
125
129
|
if options[:order_id].present? && action == 'sale'
|
126
130
|
details[:merchantOrderId] = options[:order_id]
|
@@ -214,7 +218,7 @@ module ActiveMerchant #:nodoc:
|
|
214
218
|
post[:storedCredentials][:sequence] = stored_credential[:initial_transaction] ? 'FIRST' : 'SUBSEQUENT'
|
215
219
|
post[:storedCredentials][:initiator] = stored_credential[:initiator] == 'merchant' ? 'MERCHANT' : 'CARD_HOLDER'
|
216
220
|
post[:storedCredentials][:scheduled] = SCHEDULED_REASON_TYPES.include?(stored_credential[:reason_type])
|
217
|
-
post[:storedCredentials][:schemeReferenceTransactionId] =
|
221
|
+
post[:storedCredentials][:schemeReferenceTransactionId] = options[:scheme_reference_transaction_id] || stored_credential[:network_transaction_id]
|
218
222
|
end
|
219
223
|
|
220
224
|
def add_credit_card(source, payment, options)
|
@@ -256,7 +260,12 @@ module ActiveMerchant #:nodoc:
|
|
256
260
|
when NetworkTokenizationCreditCard
|
257
261
|
add_decrypted_wallet(source, payment, options)
|
258
262
|
when CreditCard
|
259
|
-
|
263
|
+
if options[:encryption_data].present?
|
264
|
+
source[:sourceType] = 'PaymentCard'
|
265
|
+
source[:encryptionData] = options[:encryption_data]
|
266
|
+
else
|
267
|
+
add_credit_card(source, payment, options)
|
268
|
+
end
|
260
269
|
when String
|
261
270
|
add_payment_token(source, payment, options)
|
262
271
|
end
|
@@ -132,6 +132,11 @@ module ActiveMerchant #:nodoc:
|
|
132
132
|
r703: 'Export hostname_country/ip_country match'
|
133
133
|
}
|
134
134
|
|
135
|
+
@@payment_solution = {
|
136
|
+
apple_pay: '001',
|
137
|
+
google_pay: '012'
|
138
|
+
}
|
139
|
+
|
135
140
|
# These are the options that can be used when creating a new CyberSource
|
136
141
|
# Gateway object.
|
137
142
|
#
|
@@ -322,6 +327,7 @@ module ActiveMerchant #:nodoc:
|
|
322
327
|
add_airline_data(xml, options)
|
323
328
|
add_sales_slip_number(xml, options)
|
324
329
|
add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
|
330
|
+
add_payment_solution(xml, creditcard_or_reference.source) if network_tokenization?(creditcard_or_reference)
|
325
331
|
add_tax_management_indicator(xml, options)
|
326
332
|
add_stored_credential_subsequent_auth(xml, options)
|
327
333
|
add_issuer_additional_data(xml, options)
|
@@ -393,6 +399,7 @@ module ActiveMerchant #:nodoc:
|
|
393
399
|
add_airline_data(xml, options)
|
394
400
|
add_sales_slip_number(xml, options)
|
395
401
|
add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
|
402
|
+
add_payment_solution(xml, payment_method_or_reference.source) if network_tokenization?(payment_method_or_reference)
|
396
403
|
add_tax_management_indicator(xml, options)
|
397
404
|
add_stored_credential_subsequent_auth(xml, options)
|
398
405
|
add_issuer_additional_data(xml, options)
|
@@ -519,11 +526,9 @@ module ActiveMerchant #:nodoc:
|
|
519
526
|
def add_business_rules_data(xml, payment_method, options)
|
520
527
|
prioritized_options = [options, @options]
|
521
528
|
|
522
|
-
|
523
|
-
xml.tag! '
|
524
|
-
|
525
|
-
xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
|
526
|
-
end
|
529
|
+
xml.tag! 'businessRules' do
|
530
|
+
xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true'
|
531
|
+
xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
|
527
532
|
end
|
528
533
|
end
|
529
534
|
|
@@ -672,6 +677,12 @@ module ActiveMerchant #:nodoc:
|
|
672
677
|
end
|
673
678
|
end
|
674
679
|
|
680
|
+
def add_payment_solution(xml, source)
|
681
|
+
return unless (payment_solution = @@payment_solution[source])
|
682
|
+
|
683
|
+
xml.tag! 'paymentSolution', payment_solution
|
684
|
+
end
|
685
|
+
|
675
686
|
def add_issuer_additional_data(xml, options)
|
676
687
|
return unless options[:issuer_additional_data]
|
677
688
|
|
@@ -705,8 +716,8 @@ module ActiveMerchant #:nodoc:
|
|
705
716
|
def add_check(xml, check, options)
|
706
717
|
xml.tag! 'check' do
|
707
718
|
xml.tag! 'accountNumber', check.account_number
|
708
|
-
xml.tag! 'accountType', check.account_type
|
709
|
-
xml.tag! 'bankTransitNumber', check.routing_number
|
719
|
+
xml.tag! 'accountType', check.account_type == 'checking' ? 'C' : 'S'
|
720
|
+
xml.tag! 'bankTransitNumber', format_routing_number(check.routing_number, options)
|
710
721
|
xml.tag! 'secCode', options[:sec_code] if options[:sec_code]
|
711
722
|
end
|
712
723
|
end
|
@@ -1055,6 +1066,8 @@ module ActiveMerchant #:nodoc:
|
|
1055
1066
|
message = message_from(response)
|
1056
1067
|
authorization = success || in_fraud_review?(response) ? authorization_from(response, action, amount, options) : nil
|
1057
1068
|
|
1069
|
+
message = auto_void?(authorization_from(response, action, amount, options), response, message, options)
|
1070
|
+
|
1058
1071
|
Response.new(success, message, response,
|
1059
1072
|
test: test?,
|
1060
1073
|
authorization: authorization,
|
@@ -1063,6 +1076,14 @@ module ActiveMerchant #:nodoc:
|
|
1063
1076
|
cvv_result: response[:cvCode])
|
1064
1077
|
end
|
1065
1078
|
|
1079
|
+
def auto_void?(authorization, response, message, options = {})
|
1080
|
+
return message unless response[:reasonCode] == '230' && options[:auto_void_230]
|
1081
|
+
|
1082
|
+
response = void(authorization, options)
|
1083
|
+
response&.success? ? message += ' - transaction has been auto-voided.' : message += ' - transaction could not be auto-voided.'
|
1084
|
+
message
|
1085
|
+
end
|
1086
|
+
|
1066
1087
|
# Parse the SOAP response
|
1067
1088
|
# Technique inspired by the Paypal Gateway
|
1068
1089
|
def parse(xml)
|
@@ -1131,6 +1152,10 @@ module ActiveMerchant #:nodoc:
|
|
1131
1152
|
def eligible_for_zero_auth?(payment_method, options = {})
|
1132
1153
|
payment_method.is_a?(CreditCard) && options[:zero_amount_auth]
|
1133
1154
|
end
|
1155
|
+
|
1156
|
+
def format_routing_number(routing_number, options)
|
1157
|
+
options[:currency] == 'CAD' && routing_number.length > 8 ? routing_number[-8..-1] : routing_number
|
1158
|
+
end
|
1134
1159
|
end
|
1135
1160
|
end
|
1136
1161
|
end
|
@@ -112,7 +112,7 @@ module ActiveMerchant #:nodoc:
|
|
112
112
|
add_code(post, options)
|
113
113
|
add_payment(post, payment, options)
|
114
114
|
add_mdd_fields(post, options)
|
115
|
-
add_amount(post, amount)
|
115
|
+
add_amount(post, amount, options)
|
116
116
|
add_address(post, payment, options[:billing_address], options, :billTo)
|
117
117
|
add_address(post, payment, options[:shipping_address], options, :shipTo)
|
118
118
|
add_business_rules_data(post, payment, options)
|
@@ -125,7 +125,7 @@ module ActiveMerchant #:nodoc:
|
|
125
125
|
{ clientReferenceInformation: {}, orderInformation: {} }.tap do |post|
|
126
126
|
add_code(post, options)
|
127
127
|
add_mdd_fields(post, options)
|
128
|
-
add_amount(post, amount)
|
128
|
+
add_amount(post, amount, options)
|
129
129
|
add_partner_solution_id(post)
|
130
130
|
end.compact
|
131
131
|
end
|
@@ -135,7 +135,7 @@ module ActiveMerchant #:nodoc:
|
|
135
135
|
add_code(post, options)
|
136
136
|
add_credit_card(post, payment)
|
137
137
|
add_mdd_fields(post, options)
|
138
|
-
add_amount(post, amount)
|
138
|
+
add_amount(post, amount, options)
|
139
139
|
add_address(post, payment, options[:billing_address], options, :billTo)
|
140
140
|
add_merchant_description(post, options)
|
141
141
|
end.compact
|
@@ -161,7 +161,7 @@ module ActiveMerchant #:nodoc:
|
|
161
161
|
}
|
162
162
|
end
|
163
163
|
|
164
|
-
def add_amount(post, amount)
|
164
|
+
def add_amount(post, amount, options)
|
165
165
|
currency = options[:currency] || currency(amount)
|
166
166
|
post[:orderInformation][:amountDetails] = {
|
167
167
|
totalAmount: localized_amount(amount, currency),
|
@@ -413,10 +413,8 @@ module ActiveMerchant #:nodoc:
|
|
413
413
|
|
414
414
|
def add_business_rules_data(post, payment, options)
|
415
415
|
post[:processingInformation][:authorizationOptions] = {}
|
416
|
-
|
417
|
-
|
418
|
-
post[:processingInformation][:authorizationOptions][:ignoreCvResult] = 'true' if options[:ignore_cvv].to_s == 'true'
|
419
|
-
end
|
416
|
+
post[:processingInformation][:authorizationOptions][:ignoreAvsResult] = 'true' if options[:ignore_avs].to_s == 'true'
|
417
|
+
post[:processingInformation][:authorizationOptions][:ignoreCvResult] = 'true' if options[:ignore_cvv].to_s == 'true'
|
420
418
|
end
|
421
419
|
|
422
420
|
def add_mdd_fields(post, options)
|
@@ -188,6 +188,7 @@ module ActiveMerchant #:nodoc:
|
|
188
188
|
post[:card][:installments] = options[:installments] if options[:installments]
|
189
189
|
post[:card][:installments_id] = options[:installments_id] if options[:installments_id]
|
190
190
|
post[:card][:force_type] = options[:force_type].to_s.upcase if options[:force_type]
|
191
|
+
post[:card][:save] = options[:save] if options[:save]
|
191
192
|
end
|
192
193
|
|
193
194
|
def parse(body)
|