activemerchant 1.131.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 +22 -0
- data/lib/active_merchant/billing/credit_card.rb +2 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +6 -2
- data/lib/active_merchant/billing/gateways/adyen.rb +80 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +6 -4
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +4 -7
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +6 -2
- data/lib/active_merchant/billing/gateways/cyber_source.rb +13 -0
- 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/payway_dot_com.rb +1 -1
- data/lib/active_merchant/billing/gateways/safe_charge.rb +2 -1
- data/lib/active_merchant/billing/gateways/stripe.rb +13 -1
- 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 +1 -20
- 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,6 +3,28 @@
|
|
3
3
|
|
4
4
|
== HEAD
|
5
5
|
|
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
|
+
|
6
28
|
== Version 1.131.0 (June 21, 2023)
|
7
29
|
* Redsys: Add supported countries [jcreiff] #4811
|
8
30
|
* Authorize.net: Truncate nameOnAccount for bank refunds [jcreiff] #4808
|
@@ -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}$/ }
|
@@ -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]
|
@@ -172,7 +172,7 @@ module ActiveMerchant #:nodoc:
|
|
172
172
|
success,
|
173
173
|
message_from(success, pairs),
|
174
174
|
pairs,
|
175
|
-
authorization: authorization_from(pairs),
|
175
|
+
authorization: authorization_from(pairs, options),
|
176
176
|
test: test?
|
177
177
|
)
|
178
178
|
end
|
@@ -185,12 +185,12 @@ module ActiveMerchant #:nodoc:
|
|
185
185
|
if succeeded
|
186
186
|
'Succeeded'
|
187
187
|
else
|
188
|
-
response[:message] || "Error with ActionCode=#{response[:actioncode]}"
|
188
|
+
response[:message] || response[:status_errormessage] || "Error with ActionCode=#{response[:actioncode]}"
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
-
def authorization_from(response)
|
193
|
-
[
|
192
|
+
def authorization_from(response, options)
|
193
|
+
authorization = [
|
194
194
|
response[:dateandtime],
|
195
195
|
response[:batch],
|
196
196
|
response[:transaction],
|
@@ -200,6 +200,8 @@ module ActiveMerchant #:nodoc:
|
|
200
200
|
response[:tramount],
|
201
201
|
response[:trcurrency]
|
202
202
|
].join('|')
|
203
|
+
|
204
|
+
authorization == '|||||||' ? nil : authorization
|
203
205
|
end
|
204
206
|
|
205
207
|
def split_authorization(authorization)
|
@@ -363,9 +363,6 @@ module ActiveMerchant #:nodoc:
|
|
363
363
|
end
|
364
364
|
|
365
365
|
def response(action, succeeded, response, source_id = nil)
|
366
|
-
successful_response = succeeded && action == :purchase || action == :authorize
|
367
|
-
avs_result = successful_response ? avs_result(response) : nil
|
368
|
-
cvv_result = successful_response ? cvv_result(response) : nil
|
369
366
|
authorization = authorization_from(response) unless action == :unstore
|
370
367
|
body = action == :unstore ? { response_code: response.to_s } : response
|
371
368
|
Response.new(
|
@@ -375,8 +372,8 @@ module ActiveMerchant #:nodoc:
|
|
375
372
|
authorization: authorization,
|
376
373
|
error_code: error_code_from(succeeded, body),
|
377
374
|
test: test?,
|
378
|
-
avs_result: avs_result,
|
379
|
-
cvv_result: cvv_result
|
375
|
+
avs_result: avs_result(response),
|
376
|
+
cvv_result: cvv_result(response)
|
380
377
|
)
|
381
378
|
end
|
382
379
|
|
@@ -427,11 +424,11 @@ module ActiveMerchant #:nodoc:
|
|
427
424
|
end
|
428
425
|
|
429
426
|
def avs_result(response)
|
430
|
-
response
|
427
|
+
response.respond_to?(:dig) && response.dig('source', 'avs_check') ? AVSResult.new(code: response['source']['avs_check']) : nil
|
431
428
|
end
|
432
429
|
|
433
430
|
def cvv_result(response)
|
434
|
-
response
|
431
|
+
response.respond_to?(:dig) && response.dig('source', 'cvv_check') ? CVVResult.new(response['source']['cvv_check']) : nil
|
435
432
|
end
|
436
433
|
|
437
434
|
def parse(body, error: nil)
|
@@ -120,7 +120,11 @@ module ActiveMerchant #:nodoc:
|
|
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)
|
@@ -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)
|
@@ -670,6 +677,12 @@ module ActiveMerchant #:nodoc:
|
|
670
677
|
end
|
671
678
|
end
|
672
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
|
+
|
673
686
|
def add_issuer_additional_data(xml, options)
|
674
687
|
return unless options[:issuer_additional_data]
|
675
688
|
|
@@ -2,7 +2,7 @@ module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class IpgGateway < Gateway
|
4
4
|
self.test_url = 'https://test.ipg-online.com/ipgapi/services'
|
5
|
-
self.live_url = 'https://www5.ipg-online.com'
|
5
|
+
self.live_url = 'https://www5.ipg-online.com/ipgapi/services'
|
6
6
|
|
7
7
|
self.supported_countries = %w(AR)
|
8
8
|
self.default_currency = 'ARS'
|
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
|
|
7
7
|
self.test_url = 'https://api-uat.kushkipagos.com/'
|
8
8
|
self.live_url = 'https://api.kushkipagos.com/'
|
9
9
|
|
10
|
-
self.supported_countries = %w[CL CO EC MX PE]
|
10
|
+
self.supported_countries = %w[BR CL CO EC MX PE]
|
11
11
|
self.default_currency = 'USD'
|
12
12
|
self.money_format = :dollars
|
13
13
|
self.supported_cardtypes = %i[visa master american_express discover diners_club alia]
|
@@ -93,8 +93,7 @@ module ActiveMerchant #:nodoc:
|
|
93
93
|
post_to_json_encrypt = encrypt(post_to_json, @options[:key_session])
|
94
94
|
|
95
95
|
final_post = '<authorization>' + post_to_json_encrypt + '</authorization><dataID>' + @options[:user] + '</dataID>'
|
96
|
-
json_post =
|
97
|
-
json_post[:payload] = final_post
|
96
|
+
json_post = final_post
|
98
97
|
commit('sale', json_post)
|
99
98
|
end
|
100
99
|
|
@@ -114,8 +113,7 @@ module ActiveMerchant #:nodoc:
|
|
114
113
|
post_to_json_encrypt = encrypt(post_to_json, @options[:key_session])
|
115
114
|
|
116
115
|
final_post = '<capture>' + post_to_json_encrypt + '</capture><dataID>' + @options[:user] + '</dataID>'
|
117
|
-
json_post =
|
118
|
-
json_post[:payload] = final_post
|
116
|
+
json_post = final_post
|
119
117
|
commit('capture', json_post)
|
120
118
|
end
|
121
119
|
|
@@ -136,8 +134,7 @@ module ActiveMerchant #:nodoc:
|
|
136
134
|
post_to_json_encrypt = encrypt(post_to_json, @options[:key_session])
|
137
135
|
|
138
136
|
final_post = '<refund>' + post_to_json_encrypt + '</refund><dataID>' + @options[:user] + '</dataID>'
|
139
|
-
json_post =
|
140
|
-
json_post[:payload] = final_post
|
137
|
+
json_post = final_post
|
141
138
|
commit('refund', json_post)
|
142
139
|
end
|
143
140
|
|
@@ -145,10 +142,18 @@ module ActiveMerchant #:nodoc:
|
|
145
142
|
true
|
146
143
|
end
|
147
144
|
|
145
|
+
def extract_mit_responses_from_transcript(transcript)
|
146
|
+
groups = transcript.scan(/reading \d+ bytes(.*?)read \d+ bytes/m)
|
147
|
+
groups.map do |group|
|
148
|
+
group.first.scan(/-> "(.*?)"/).flatten.map(&:strip).join('')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
148
152
|
def scrub(transcript)
|
149
153
|
ret_transcript = transcript
|
150
154
|
auth_origin = ret_transcript[/<authorization>(.*?)<\/authorization>/, 1]
|
151
155
|
unless auth_origin.nil?
|
156
|
+
auth_origin = auth_origin.gsub('\n', '')
|
152
157
|
auth_decrypted = decrypt(auth_origin, @options[:key_session])
|
153
158
|
auth_json = JSON.parse(auth_decrypted)
|
154
159
|
auth_json['card'] = '[FILTERED]'
|
@@ -162,6 +167,7 @@ module ActiveMerchant #:nodoc:
|
|
162
167
|
|
163
168
|
cap_origin = ret_transcript[/<capture>(.*?)<\/capture>/, 1]
|
164
169
|
unless cap_origin.nil?
|
170
|
+
cap_origin = cap_origin.gsub('\n', '')
|
165
171
|
cap_decrypted = decrypt(cap_origin, @options[:key_session])
|
166
172
|
cap_json = JSON.parse(cap_decrypted)
|
167
173
|
cap_json['apikey'] = '[FILTERED]'
|
@@ -173,6 +179,7 @@ module ActiveMerchant #:nodoc:
|
|
173
179
|
|
174
180
|
ref_origin = ret_transcript[/<refund>(.*?)<\/refund>/, 1]
|
175
181
|
unless ref_origin.nil?
|
182
|
+
ref_origin = ref_origin.gsub('\n', '')
|
176
183
|
ref_decrypted = decrypt(ref_origin, @options[:key_session])
|
177
184
|
ref_json = JSON.parse(ref_decrypted)
|
178
185
|
ref_json['apikey'] = '[FILTERED]'
|
@@ -182,15 +189,10 @@ module ActiveMerchant #:nodoc:
|
|
182
189
|
ret_transcript = ret_transcript.gsub(/<refund>(.*?)<\/refund>/, ref_tagged)
|
183
190
|
end
|
184
191
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
resp_origin = res_origin[/#{Regexp.escape('"')}(.*?)#{Regexp.escape('"')}/m, 1]
|
190
|
-
resp_decrypted = decrypt(resp_origin, @options[:key_session])
|
191
|
-
ret_transcript[/#{Regexp.escape('reading ')}(.*?)#{Regexp.escape('read')}/m, 1] = resp_decrypted
|
192
|
-
ret_transcript = ret_transcript.sub('reading ', 'response: ')
|
193
|
-
res_origin = ret_transcript[/#{Regexp.escape('reading ')}(.*?)#{Regexp.escape('read')}/m, 1]
|
192
|
+
groups = extract_mit_responses_from_transcript(transcript)
|
193
|
+
groups.each do |group|
|
194
|
+
group_decrypted = decrypt(group, @options[:key_session])
|
195
|
+
ret_transcript = ret_transcript.gsub('Conn close', "\n" + group_decrypted + "\nConn close")
|
194
196
|
end
|
195
197
|
|
196
198
|
ret_transcript
|
@@ -219,9 +221,7 @@ module ActiveMerchant #:nodoc:
|
|
219
221
|
end
|
220
222
|
|
221
223
|
def commit(action, parameters)
|
222
|
-
|
223
|
-
cleaned_str = json_str.gsub('\n', '')
|
224
|
-
raw_response = ssl_post(live_url, cleaned_str, { 'Content-type' => 'application/json' })
|
224
|
+
raw_response = ssl_post(live_url, parameters, { 'Content-type' => 'text/plain' })
|
225
225
|
response = JSON.parse(decrypt(raw_response, @options[:key_session]))
|
226
226
|
|
227
227
|
Response.new(
|
@@ -149,6 +149,7 @@ module ActiveMerchant #:nodoc:
|
|
149
149
|
|
150
150
|
def add_invoice(post, money, options)
|
151
151
|
post[:amount] = amount(money)
|
152
|
+
post[:surcharge] = options[:surcharge] if options[:surcharge]
|
152
153
|
post[:orderid] = options[:order_id]
|
153
154
|
post[:orderdescription] = options[:description]
|
154
155
|
post[:currency] = options[:currency] || currency(money)
|
@@ -232,6 +233,9 @@ module ActiveMerchant #:nodoc:
|
|
232
233
|
end
|
233
234
|
|
234
235
|
if (shipping_address = options[:shipping_address])
|
236
|
+
first_name, last_name = split_names(shipping_address[:name])
|
237
|
+
post[:shipping_firstname] = first_name if first_name
|
238
|
+
post[:shipping_lastname] = last_name if last_name
|
235
239
|
post[:shipping_company] = shipping_address[:company]
|
236
240
|
post[:shipping_address1] = shipping_address[:address1]
|
237
241
|
post[:shipping_address2] = shipping_address[:address2]
|
@@ -240,6 +244,7 @@ module ActiveMerchant #:nodoc:
|
|
240
244
|
post[:shipping_country] = shipping_address[:country]
|
241
245
|
post[:shipping_zip] = shipping_address[:zip]
|
242
246
|
post[:shipping_phone] = shipping_address[:phone]
|
247
|
+
post[:shipping_email] = options[:shipping_email] if options[:shipping_email]
|
243
248
|
end
|
244
249
|
|
245
250
|
if (descriptor = options[:descriptors])
|
@@ -2,7 +2,7 @@ module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class PaywayDotComGateway < Gateway
|
4
4
|
self.test_url = 'https://paywaywsdev.com/PaywayWS/Payment/CreditCard'
|
5
|
-
self.live_url = 'https://paywayws.
|
5
|
+
self.live_url = 'https://paywayws.net/PaywayWS/Payment/CreditCard'
|
6
6
|
|
7
7
|
self.supported_countries = %w[US CA]
|
8
8
|
self.default_currency = 'USD'
|
@@ -73,10 +73,10 @@ module ActiveMerchant #:nodoc:
|
|
73
73
|
add_transaction_data('Credit', post, money, options.merge!({ currency: original_currency }))
|
74
74
|
post[:sg_CreditType] = 2
|
75
75
|
post[:sg_AuthCode] = auth
|
76
|
-
post[:sg_TransactionID] = transaction_id
|
77
76
|
post[:sg_CCToken] = token
|
78
77
|
post[:sg_ExpMonth] = exp_month
|
79
78
|
post[:sg_ExpYear] = exp_year
|
79
|
+
post[:sg_TransactionID] = transaction_id unless options[:unreferenced_refund]
|
80
80
|
|
81
81
|
commit(post)
|
82
82
|
end
|
@@ -86,6 +86,7 @@ module ActiveMerchant #:nodoc:
|
|
86
86
|
|
87
87
|
add_payment(post, payment, options)
|
88
88
|
add_transaction_data('Credit', post, money, options)
|
89
|
+
add_customer_details(post, payment, options)
|
89
90
|
|
90
91
|
post[:sg_CreditType] = 1
|
91
92
|
|
@@ -696,7 +696,7 @@ module ActiveMerchant #:nodoc:
|
|
696
696
|
def commit(method, url, parameters = nil, options = {})
|
697
697
|
add_expand_parameters(parameters, options) if parameters
|
698
698
|
|
699
|
-
return Response.new(false, 'Invalid API Key provided')
|
699
|
+
return Response.new(false, 'Invalid API Key provided') unless key_valid?(options)
|
700
700
|
|
701
701
|
response = api_request(method, url, parameters, options)
|
702
702
|
response['webhook_id'] = options[:webhook_id] if options[:webhook_id]
|
@@ -716,6 +716,18 @@ module ActiveMerchant #:nodoc:
|
|
716
716
|
error_code: success ? nil : error_code_from(response))
|
717
717
|
end
|
718
718
|
|
719
|
+
def key_valid?(options)
|
720
|
+
return true unless test?
|
721
|
+
|
722
|
+
%w(sk rk).each do |k|
|
723
|
+
if key(options).start_with?(k)
|
724
|
+
return false unless key(options).start_with?("#{k}_test")
|
725
|
+
end
|
726
|
+
end
|
727
|
+
|
728
|
+
true
|
729
|
+
end
|
730
|
+
|
719
731
|
def authorization_from(success, url, method, response)
|
720
732
|
return response.fetch('error', {})['charge'] unless success
|
721
733
|
|
@@ -34,9 +34,9 @@ module ActiveMerchant #:nodoc:
|
|
34
34
|
add_connected_account(post, options)
|
35
35
|
add_radar_data(post, options)
|
36
36
|
add_shipping_address(post, options)
|
37
|
+
add_stored_credentials(post, options)
|
37
38
|
setup_future_usage(post, options)
|
38
39
|
add_exemption(post, options)
|
39
|
-
add_stored_credentials(post, options)
|
40
40
|
add_ntid(post, options)
|
41
41
|
add_claim_without_transaction_id(post, options)
|
42
42
|
add_error_on_requires_action(post, options)
|
@@ -76,22 +76,27 @@ module ActiveMerchant #:nodoc:
|
|
76
76
|
|
77
77
|
def create_payment_method(payment_method, options = {})
|
78
78
|
post_data = add_payment_method_data(payment_method, options)
|
79
|
-
|
80
79
|
options = format_idempotency_key(options, 'pm')
|
81
80
|
commit(:post, 'payment_methods', post_data, options)
|
82
81
|
end
|
83
82
|
|
84
83
|
def add_payment_method_data(payment_method, options = {})
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
84
|
+
post = {
|
85
|
+
type: 'card',
|
86
|
+
card: {
|
87
|
+
number: payment_method.number,
|
88
|
+
exp_month: payment_method.month,
|
89
|
+
exp_year: payment_method.year
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
post[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
|
94
|
+
if billing = options[:billing_address] || options[:address]
|
95
|
+
post[:billing_details] = add_address(billing, options)
|
96
|
+
end
|
97
|
+
|
98
|
+
add_name_only(post, payment_method) if post[:billing_details].nil?
|
99
|
+
post
|
95
100
|
end
|
96
101
|
|
97
102
|
def add_payment_method_card_data_token(post_data, payment_method)
|
@@ -212,16 +217,7 @@ module ActiveMerchant #:nodoc:
|
|
212
217
|
result = add_payment_method_token(params, payment_method, options)
|
213
218
|
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
214
219
|
|
215
|
-
|
216
|
-
customer_id = options[:customer]
|
217
|
-
else
|
218
|
-
post[:description] = options[:description] if options[:description]
|
219
|
-
post[:email] = options[:email] if options[:email]
|
220
|
-
options = format_idempotency_key(options, 'customer')
|
221
|
-
post[:expand] = [:sources]
|
222
|
-
customer = commit(:post, 'customers', post, options)
|
223
|
-
customer_id = customer.params['id']
|
224
|
-
end
|
220
|
+
customer_id = options[:customer] || customer(post, payment_method, options).params['id']
|
225
221
|
options = format_idempotency_key(options, 'attach')
|
226
222
|
attach_parameters = { customer: customer_id }
|
227
223
|
attach_parameters[:validate] = options[:validate] unless options[:validate].nil?
|
@@ -231,6 +227,23 @@ module ActiveMerchant #:nodoc:
|
|
231
227
|
end
|
232
228
|
end
|
233
229
|
|
230
|
+
def customer(post, payment, options)
|
231
|
+
post[:description] = options[:description] if options[:description]
|
232
|
+
post[:expand] = [:sources]
|
233
|
+
post[:email] = options[:email]
|
234
|
+
|
235
|
+
if billing = options[:billing_address] || options[:address]
|
236
|
+
post.merge!(add_address(billing, options))
|
237
|
+
end
|
238
|
+
|
239
|
+
if shipping = options[:shipping_address]
|
240
|
+
post[:shipping] = add_address(shipping, options).except(:email)
|
241
|
+
end
|
242
|
+
|
243
|
+
options = format_idempotency_key(options, 'customer')
|
244
|
+
commit(:post, 'customers', post, options)
|
245
|
+
end
|
246
|
+
|
234
247
|
def unstore(identification, options = {}, deprecated_options = {})
|
235
248
|
if identification.include?('pm_')
|
236
249
|
_, payment_method = identification.split('|')
|
@@ -399,17 +412,19 @@ module ActiveMerchant #:nodoc:
|
|
399
412
|
post[:payment_method_options][:card][:moto] = true if options[:moto]
|
400
413
|
end
|
401
414
|
|
402
|
-
# Stripe Payment Intents
|
403
|
-
#
|
404
|
-
#
|
405
|
-
#
|
415
|
+
# Stripe Payment Intents now supports specifying on a transaction level basis stored credential information.
|
416
|
+
# The feature is currently gated but is listed as `stored_credential_transaction_type` inside the
|
417
|
+
# `post[:payment_method_options][:card]` hash. Since this is a beta field adding an extra check to use
|
418
|
+
# the existing logic by default. To be able to utilize this field, you must reach out to Stripe.
|
406
419
|
|
407
420
|
def add_stored_credentials(post, options = {})
|
408
421
|
return unless options[:stored_credential] && !options[:stored_credential].values.all?(&:nil?)
|
409
422
|
|
410
|
-
stored_credential = options[:stored_credential]
|
411
423
|
post[:payment_method_options] ||= {}
|
412
424
|
post[:payment_method_options][:card] ||= {}
|
425
|
+
add_stored_credential_transaction_type(post, options) if options[:stored_credential_transaction_type]
|
426
|
+
|
427
|
+
stored_credential = options[:stored_credential]
|
413
428
|
post[:payment_method_options][:card][:mit_exemption] = {}
|
414
429
|
|
415
430
|
# Stripe PI accepts network_transaction_id and ds_transaction_id via mit field under card.
|
@@ -419,6 +434,50 @@ module ActiveMerchant #:nodoc:
|
|
419
434
|
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
420
435
|
end
|
421
436
|
|
437
|
+
def add_stored_credential_transaction_type(post, options = {})
|
438
|
+
stored_credential = options[:stored_credential]
|
439
|
+
# Do not add anything unless these are present.
|
440
|
+
return unless stored_credential[:reason_type] && stored_credential[:initiator]
|
441
|
+
|
442
|
+
# Not compatible with off_session parameter.
|
443
|
+
options.delete(:off_session)
|
444
|
+
if stored_credential[:initial_transaction]
|
445
|
+
# Initial transactions must by CIT
|
446
|
+
return unless stored_credential[:initiator] == 'cardholder'
|
447
|
+
|
448
|
+
initial_transaction_stored_credential(post, stored_credential[:reason_type])
|
449
|
+
else
|
450
|
+
# Subsequent transaction
|
451
|
+
subsequent_transaction_stored_credential(post, stored_credential[:initiator], stored_credential[:reason_type])
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def initial_transaction_stored_credential(post, reason_type)
|
456
|
+
if reason_type == 'unscheduled'
|
457
|
+
# Charge on-session and store card for future one-off payment use
|
458
|
+
post[:payment_method_options][:card][:stored_credential_transaction_type] = 'setup_off_session_unscheduled'
|
459
|
+
elsif reason_type == 'recurring'
|
460
|
+
# Charge on-session and store card for future recurring payment use
|
461
|
+
post[:payment_method_options][:card][:stored_credential_transaction_type] = 'setup_off_session_recurring'
|
462
|
+
else
|
463
|
+
# Charge on-session and store card for future on-session payment use.
|
464
|
+
post[:payment_method_options][:card][:stored_credential_transaction_type] = 'setup_on_session'
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
def subsequent_transaction_stored_credential(post, initiator, reason_type)
|
469
|
+
if initiator == 'cardholder'
|
470
|
+
# Charge on-session customer using previously stored card.
|
471
|
+
post[:payment_method_options][:card][:stored_credential_transaction_type] = 'stored_on_session'
|
472
|
+
elsif reason_type == 'recurring'
|
473
|
+
# Charge off-session customer using previously stored card for recurring transaction
|
474
|
+
post[:payment_method_options][:card][:stored_credential_transaction_type] = 'stored_off_session_recurring'
|
475
|
+
else
|
476
|
+
# Charge off-session customer using previously stored card for one-off transaction
|
477
|
+
post[:payment_method_options][:card][:stored_credential_transaction_type] = 'stored_off_session_unscheduled'
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
422
481
|
def add_ntid(post, options = {})
|
423
482
|
return unless options[:network_transaction_id]
|
424
483
|
|
@@ -478,30 +537,35 @@ module ActiveMerchant #:nodoc:
|
|
478
537
|
def add_billing_address_for_card_tokenization(post, options = {})
|
479
538
|
return unless (billing = options[:billing_address] || options[:address])
|
480
539
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
post[:card][:
|
485
|
-
post[:card]
|
486
|
-
post[:card][:address_state] = billing[:state] if billing[:state]
|
540
|
+
billing = add_address(billing, options)
|
541
|
+
billing[:address].transform_keys! { |k| k == :postal_code ? :address_zip : k.to_s.prepend('address_').to_sym }
|
542
|
+
|
543
|
+
post[:card][:name] = billing[:name]
|
544
|
+
post[:card].merge!(billing[:address])
|
487
545
|
end
|
488
546
|
|
489
|
-
def
|
490
|
-
return unless
|
547
|
+
def add_shipping_address(post, options = {})
|
548
|
+
return unless shipping = options[:shipping_address]
|
491
549
|
|
492
|
-
|
550
|
+
post[:shipping] = add_address(shipping, options).except(:email)
|
551
|
+
post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
|
552
|
+
post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
|
553
|
+
end
|
493
554
|
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
555
|
+
def add_address(address, options)
|
556
|
+
{
|
557
|
+
address: {
|
558
|
+
city: address[:city],
|
559
|
+
country: address[:country],
|
560
|
+
line1: address[:address1],
|
561
|
+
line2: address[:address2],
|
562
|
+
postal_code: address[:zip],
|
563
|
+
state: address[:state]
|
564
|
+
}.compact,
|
565
|
+
email: address[:email] || options[:email],
|
566
|
+
phone: address[:phone] || address[:phone_number],
|
567
|
+
name: address[:name]
|
568
|
+
}.compact
|
505
569
|
end
|
506
570
|
|
507
571
|
def add_name_only(post, payment_method)
|
@@ -511,27 +575,6 @@ module ActiveMerchant #:nodoc:
|
|
511
575
|
post[:billing_details][:name] = name
|
512
576
|
end
|
513
577
|
|
514
|
-
def add_shipping_address(post, options = {})
|
515
|
-
return unless shipping = options[:shipping_address]
|
516
|
-
|
517
|
-
post[:shipping] = {}
|
518
|
-
|
519
|
-
# fields required by Stripe PI
|
520
|
-
post[:shipping][:address] = {}
|
521
|
-
post[:shipping][:address][:line1] = shipping[:address1]
|
522
|
-
post[:shipping][:name] = shipping[:name]
|
523
|
-
|
524
|
-
# fields considered optional by Stripe PI
|
525
|
-
post[:shipping][:address][:city] = shipping[:city] if shipping[:city]
|
526
|
-
post[:shipping][:address][:country] = shipping[:country] if shipping[:country]
|
527
|
-
post[:shipping][:address][:line2] = shipping[:address2] if shipping[:address2]
|
528
|
-
post[:shipping][:address][:postal_code] = shipping[:zip] if shipping[:zip]
|
529
|
-
post[:shipping][:address][:state] = shipping[:state] if shipping[:state]
|
530
|
-
post[:shipping][:phone] = shipping[:phone_number] if shipping[:phone_number]
|
531
|
-
post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
|
532
|
-
post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
|
533
|
-
end
|
534
|
-
|
535
578
|
def format_idempotency_key(options, suffix)
|
536
579
|
return options unless options[:idempotency_key]
|
537
580
|
|
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
|
|
9
9
|
|
10
10
|
self.supported_countries = ['PY']
|
11
11
|
self.default_currency = 'PYG'
|
12
|
-
self.supported_cardtypes = %i[visa master]
|
12
|
+
self.supported_cardtypes = %i[visa master panal]
|
13
13
|
|
14
14
|
self.homepage_url = 'https://comercios.bancard.com.py'
|
15
15
|
self.display_name = 'vPOS'
|
@@ -28,21 +28,6 @@ module ActiveMerchant #:nodoc:
|
|
28
28
|
network_token: 'NETWORKTOKEN'
|
29
29
|
}
|
30
30
|
|
31
|
-
CARD_CODES = {
|
32
|
-
'visa' => 'VISA-SSL',
|
33
|
-
'master' => 'ECMC-SSL',
|
34
|
-
'discover' => 'DISCOVER-SSL',
|
35
|
-
'american_express' => 'AMEX-SSL',
|
36
|
-
'jcb' => 'JCB-SSL',
|
37
|
-
'maestro' => 'MAESTRO-SSL',
|
38
|
-
'diners_club' => 'DINERS-SSL',
|
39
|
-
'elo' => 'ELO-SSL',
|
40
|
-
'naranja' => 'NARANJA-SSL',
|
41
|
-
'cabal' => 'CABAL-SSL',
|
42
|
-
'unionpay' => 'CHINAUNIONPAY-SSL',
|
43
|
-
'unknown' => 'CARD-SSL'
|
44
|
-
}
|
45
|
-
|
46
31
|
AVS_CODE_MAP = {
|
47
32
|
'A' => 'M', # Match
|
48
33
|
'B' => 'P', # Postcode matches, address not verified
|
@@ -646,7 +631,7 @@ module ActiveMerchant #:nodoc:
|
|
646
631
|
end
|
647
632
|
|
648
633
|
def add_card_details(xml, payment_method, options)
|
649
|
-
xml.tag!
|
634
|
+
xml.tag! 'CARD-SSL' do
|
650
635
|
add_card(xml, payment_method, options)
|
651
636
|
end
|
652
637
|
end
|
@@ -1034,10 +1019,6 @@ module ActiveMerchant #:nodoc:
|
|
1034
1019
|
return 2
|
1035
1020
|
end
|
1036
1021
|
|
1037
|
-
def card_code_for(payment_method)
|
1038
|
-
CARD_CODES[card_brand(payment_method)] || CARD_CODES['unknown']
|
1039
|
-
end
|
1040
|
-
|
1041
1022
|
def eligible_for_0_auth?(payment_method, options = {})
|
1042
1023
|
payment_method.is_a?(CreditCard) && %w(visa master).include?(payment_method.brand) && options[:zero_dollar_auth]
|
1043
1024
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activemerchant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.133.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -480,7 +480,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
480
480
|
- !ruby/object:Gem::Version
|
481
481
|
version: '0'
|
482
482
|
requirements: []
|
483
|
-
rubygems_version: 3.4.
|
483
|
+
rubygems_version: 3.4.16
|
484
484
|
signing_key:
|
485
485
|
specification_version: 4
|
486
486
|
summary: Framework and tools for dealing with credit card transactions.
|