activemerchant 1.129.0 → 1.133.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 +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)
|