activemerchant 1.91.0 → 1.92.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/lib/active_merchant/billing/credit_card.rb +2 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +13 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +52 -18
- data/lib/active_merchant/billing/gateways/bambora_apac.rb +54 -14
- data/lib/active_merchant/billing/gateways/blue_pay.rb +10 -8
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +12 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +32 -2
- data/lib/active_merchant/billing/gateways/d_local.rb +2 -2
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +42 -3
- data/lib/active_merchant/billing/gateways/litle.rb +61 -3
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
- data/lib/active_merchant/billing/gateways/mundipagg.rb +2 -2
- data/lib/active_merchant/billing/gateways/orbital.rb +27 -3
- data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
- data/lib/active_merchant/billing/gateways/paymentez.rb +3 -2
- data/lib/active_merchant/billing/gateways/paypal_express.rb +3 -1
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -1
- data/lib/active_merchant/billing/gateways/realex.rb +15 -1
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +22 -10
- data/lib/active_merchant/billing/gateways/worldpay.rb +13 -2
- data/lib/active_merchant/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7269c204ea4aba074e22b8d23828116e472e5537bee163e0e60159192609cc27
|
4
|
+
data.tar.gz: 4b42091ca8a875d56f2bd1cc53d8440e63733930143ee662d9ca5ef87ff3cd00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a4cf32bc3055e7f8f6663a024f26424a498ec66f746a703f504723275f969f67fbfbd1cb4b7824245deef9dc7769dd94451a0d7a182491a19439a9df258f624
|
7
|
+
data.tar.gz: 847b1508be32ccd72185dc2e6d58075e4e6fecf693e069a068ab34dee1c8fd848e6dc760bf44708a9e4d97ca00fbcec9955b6612311555194d3bb5ee9e6351a2
|
data/CHANGELOG
CHANGED
@@ -2,6 +2,30 @@
|
|
2
2
|
|
3
3
|
== HEAD
|
4
4
|
|
5
|
+
== Version 1.91.0 (April 8, 2019)
|
6
|
+
* BluePay: Send customer IP address when provided [jknipp] #3149
|
7
|
+
* PaymentExpress: Use ip field for client_info field [jknipp] #3150
|
8
|
+
* Bambora Asia-Pacific: Adds Store [molbrown] #3147
|
9
|
+
* Orbital: Pass normalized stored credential fields [curiousepic] #3148
|
10
|
+
* Adds Elo card type in general and specifically to Adyen [deedeelavinder] #3153
|
11
|
+
* Mercado Pago: Adds Elo card type [deedeelavinder] #3156
|
12
|
+
* Litle: Add support for stored credentials [bayprogrammer] #3155
|
13
|
+
* Adyen: Correctly process risk_data option [bayprogrammer] #3161
|
14
|
+
* Paymentez: Adds Elo card type [deedeelavinder] #3162
|
15
|
+
* WorldPay: Adds Elo card type [deedeelavinder] #3163
|
16
|
+
* Adyen: Idempotency for non-purchase requests [molbrown] #3164
|
17
|
+
* FirstData e4 v27: Support v28 url and stored creds [curiousepic] #3165
|
18
|
+
* WorldPay: Fix element order for 3DS + stored cred [bayprogrammer] #3172
|
19
|
+
* Braintree: Add risk data to returned response [jknipp] #3169
|
20
|
+
* Adyen: Support idempotency on purchase [molbrown] #3168
|
21
|
+
* Adyen: Pass phone, statement, device_fingerprint [curiousepic] #3178
|
22
|
+
* Adyen: Fix adding phone from billing address [curiousepic] #3179
|
23
|
+
* Fix partial or missing address exceptions [molbrown] #3180
|
24
|
+
* Adyen: Update to support normalized stored credential fields [molbrown] #3182
|
25
|
+
* VisaNet Peru: Always include DSC_COD_ACCION [bayprogrammer] #3174
|
26
|
+
* Adyen: Support adjust action [curiousepic] #3190
|
27
|
+
* CyberSource: Add support for stored credentials [therufs] #3185
|
28
|
+
|
5
29
|
== Version 1.91.0 (February 22, 2019)
|
6
30
|
* WorldPay: Pull CVC and AVS Result from Response [nfarve] #3106
|
7
31
|
* Worldpay: Add AVS and CVC Mapping [nfarve] #3107
|
@@ -18,6 +18,7 @@ module ActiveMerchant #:nodoc:
|
|
18
18
|
# * Dankort
|
19
19
|
# * Maestro
|
20
20
|
# * Forbrugsforeningen
|
21
|
+
# * Elo
|
21
22
|
#
|
22
23
|
# For testing purposes, use the 'bogus' credit card brand. This skips the vast majority of
|
23
24
|
# validations, allowing you to focus on your core concerns until you're ready to be more concerned
|
@@ -88,6 +89,7 @@ module ActiveMerchant #:nodoc:
|
|
88
89
|
# * +'dankort'+
|
89
90
|
# * +'maestro'+
|
90
91
|
# * +'forbrugsforeningen'+
|
92
|
+
# * +'elo'+
|
91
93
|
#
|
92
94
|
# Or, if you wish to test your implementation, +'bogus'+.
|
93
95
|
#
|
@@ -5,6 +5,7 @@ module ActiveMerchant #:nodoc:
|
|
5
5
|
CARD_COMPANY_DETECTORS = {
|
6
6
|
'visa' => ->(num) { num =~ /^4\d{12}(\d{3})?(\d{3})?$/ },
|
7
7
|
'master' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), MASTERCARD_RANGES) },
|
8
|
+
'elo' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), ELO_RANGES) },
|
8
9
|
'discover' => ->(num) { num =~ /^(6011|65\d{2}|64[4-9]\d)\d{12,15}|(62\d{14,17})$/ },
|
9
10
|
'american_express' => ->(num) { num =~ /^3[47]\d{13}$/ },
|
10
11
|
'diners_club' => ->(num) { num =~ /^3(0[0-5]|[68]\d)\d{11}$/ },
|
@@ -66,6 +67,18 @@ module ActiveMerchant #:nodoc:
|
|
66
67
|
(670000..679999),
|
67
68
|
]
|
68
69
|
|
70
|
+
# https://dev.elo.com.br/apis/tabela-de-bins, download csv from left sidebar
|
71
|
+
ELO_RANGES = [
|
72
|
+
506707..506708, 506715..506715, 506718..506722, 506724..506724, 506726..506736, 506739..506739, 506741..506743,
|
73
|
+
506745..506747, 506753..506753, 506774..506776, 506778..506778, 509000..509001, 509003..509003, 509007..509007,
|
74
|
+
509020..509022, 509035..509035, 509039..509042, 509045..509045, 509048..509048, 509051..509071, 509073..509074,
|
75
|
+
509077..509080, 509084..509084, 509091..509094, 509098..509098, 509100..509100, 509104..509104, 509106..509109,
|
76
|
+
627780..627780, 636368..636368, 650031..650033, 650035..650045, 650047..650047, 650406..650410, 650434..650436,
|
77
|
+
650439..650439, 650485..650504, 650506..650530, 650577..650580, 650582..650591, 650721..650727, 650901..650922,
|
78
|
+
650928..650928, 650938..650939, 650946..650948, 650954..650955, 650962..650963, 650967..650967, 650971..650971,
|
79
|
+
651652..651667, 651675..651678, 655000..655010, 655012..655015, 655051..655052, 655056..655057
|
80
|
+
]
|
81
|
+
|
69
82
|
def self.included(base)
|
70
83
|
base.extend(ClassMethods)
|
71
84
|
end
|
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
|
|
9
9
|
|
10
10
|
self.supported_countries = ['AT', 'AU', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GI', 'GR', 'HK', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SG', 'SK', 'SI', 'US']
|
11
11
|
self.default_currency = 'USD'
|
12
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover]
|
12
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover, :elo]
|
13
13
|
|
14
14
|
self.money_format = :cents
|
15
15
|
|
@@ -38,7 +38,7 @@ module ActiveMerchant #:nodoc:
|
|
38
38
|
else
|
39
39
|
MultiResponse.run do |r|
|
40
40
|
r.process { authorize(money, payment, options) }
|
41
|
-
r.process { capture(money, r.authorization, options) }
|
41
|
+
r.process { capture(money, r.authorization, capture_options(options)) }
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -49,31 +49,38 @@ module ActiveMerchant #:nodoc:
|
|
49
49
|
add_invoice(post, money, options)
|
50
50
|
add_payment(post, payment)
|
51
51
|
add_extra_data(post, payment, options)
|
52
|
-
|
52
|
+
add_stored_credentials(post, payment, options)
|
53
53
|
add_address(post, options)
|
54
54
|
add_installments(post, options) if options[:installments]
|
55
55
|
add_3ds(post, options)
|
56
|
-
commit('authorise', post)
|
56
|
+
commit('authorise', post, options)
|
57
57
|
end
|
58
58
|
|
59
59
|
def capture(money, authorization, options={})
|
60
60
|
post = init_post(options)
|
61
61
|
add_invoice_for_modification(post, money, options)
|
62
62
|
add_reference(post, authorization, options)
|
63
|
-
commit('capture', post)
|
63
|
+
commit('capture', post, options)
|
64
64
|
end
|
65
65
|
|
66
66
|
def refund(money, authorization, options={})
|
67
67
|
post = init_post(options)
|
68
68
|
add_invoice_for_modification(post, money, options)
|
69
69
|
add_original_reference(post, authorization, options)
|
70
|
-
commit('refund', post)
|
70
|
+
commit('refund', post, options)
|
71
71
|
end
|
72
72
|
|
73
73
|
def void(authorization, options={})
|
74
74
|
post = init_post(options)
|
75
75
|
add_reference(post, authorization, options)
|
76
|
-
commit('cancel', post)
|
76
|
+
commit('cancel', post, options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def adjust(money, authorization, options={})
|
80
|
+
post = init_post(options)
|
81
|
+
add_invoice_for_modification(post, money, options)
|
82
|
+
add_reference(post, authorization, options)
|
83
|
+
commit('adjustAuthorisation', post, options)
|
77
84
|
end
|
78
85
|
|
79
86
|
def store(credit_card, options={})
|
@@ -82,14 +89,16 @@ module ActiveMerchant #:nodoc:
|
|
82
89
|
add_invoice(post, 0, options)
|
83
90
|
add_payment(post, credit_card)
|
84
91
|
add_extra_data(post, credit_card, options)
|
92
|
+
add_stored_credentials(post, credit_card, options)
|
85
93
|
add_recurring_contract(post, options)
|
86
94
|
add_address(post, options)
|
87
|
-
commit('authorise', post)
|
95
|
+
commit('authorise', post, options)
|
88
96
|
end
|
89
97
|
|
90
98
|
def verify(credit_card, options={})
|
91
99
|
MultiResponse.run(:use_first_response) do |r|
|
92
100
|
r.process { authorize(0, credit_card, options) }
|
101
|
+
options[:idempotency_key] = nil
|
93
102
|
r.process(:ignore_result) { void(r.authorization, options) }
|
94
103
|
end
|
95
104
|
end
|
@@ -151,9 +160,11 @@ module ActiveMerchant #:nodoc:
|
|
151
160
|
}
|
152
161
|
|
153
162
|
def add_extra_data(post, payment, options)
|
163
|
+
post[:telephoneNumber] = options[:billing_address][:phone] if options.dig(:billing_address, :phone)
|
154
164
|
post[:shopperEmail] = options[:shopper_email] if options[:shopper_email]
|
155
165
|
post[:shopperIP] = options[:shopper_ip] if options[:shopper_ip]
|
156
166
|
post[:shopperReference] = options[:shopper_reference] if options[:shopper_reference]
|
167
|
+
post[:shopperStatement] = options[:shopper_statement] if options[:shopper_statement]
|
157
168
|
post[:fraudOffset] = options[:fraud_offset] if options[:fraud_offset]
|
158
169
|
post[:selectedBrand] = options[:selected_brand] if options[:selected_brand]
|
159
170
|
post[:selectedBrand] ||= NETWORK_TOKENIZATION_CARD_SOURCE[payment.source.to_s] if payment.is_a?(NetworkTokenizationCreditCard)
|
@@ -163,18 +174,24 @@ module ActiveMerchant #:nodoc:
|
|
163
174
|
post[:additionalData][:overwriteBrand] = normalize(options[:overwrite_brand]) if options[:overwrite_brand]
|
164
175
|
post[:additionalData][:customRoutingFlag] = options[:custom_routing_flag] if options[:custom_routing_flag]
|
165
176
|
post[:additionalData]['paymentdatasource.type'] = NETWORK_TOKENIZATION_CARD_SOURCE[payment.source.to_s] if payment.is_a?(NetworkTokenizationCreditCard)
|
177
|
+
post[:deviceFingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
|
166
178
|
add_risk_data(post, options)
|
167
179
|
end
|
168
180
|
|
169
181
|
def add_risk_data(post, options)
|
170
|
-
risk_data =
|
171
|
-
|
182
|
+
if (risk_data = options[:risk_data])
|
183
|
+
risk_data = Hash[risk_data.map { |k, v| ["riskdata.#{k}", v] }]
|
184
|
+
post[:additionalData].merge!(risk_data)
|
185
|
+
end
|
186
|
+
end
|
172
187
|
|
173
|
-
|
188
|
+
def add_stored_credentials(post, payment, options)
|
189
|
+
add_shopper_interaction(post, payment, options)
|
190
|
+
add_recurring_processing_model(post, options)
|
174
191
|
end
|
175
192
|
|
176
193
|
def add_shopper_interaction(post, payment, options={})
|
177
|
-
if (payment.respond_to?(:verification_value) && payment.verification_value) || payment.is_a?(NetworkTokenizationCreditCard)
|
194
|
+
if options.dig(:stored_credential, :initial_transaction) || (payment.respond_to?(:verification_value) && payment.verification_value) || payment.is_a?(NetworkTokenizationCreditCard)
|
178
195
|
shopper_interaction = 'Ecommerce'
|
179
196
|
else
|
180
197
|
shopper_interaction = 'ContAuth'
|
@@ -183,6 +200,17 @@ module ActiveMerchant #:nodoc:
|
|
183
200
|
post[:shopperInteraction] = options[:shopper_interaction] || shopper_interaction
|
184
201
|
end
|
185
202
|
|
203
|
+
def add_recurring_processing_model(post, options)
|
204
|
+
return unless options.dig(:stored_credential, :reason_type) || options[:recurring_processing_model]
|
205
|
+
if options.dig(:stored_credential, :reason_type) && options[:stored_credential][:reason_type] == 'unscheduled'
|
206
|
+
recurring_processing_model = 'CardOnFile'
|
207
|
+
else
|
208
|
+
recurring_processing_model = 'Subscription'
|
209
|
+
end
|
210
|
+
|
211
|
+
post[:recurringProcessingModel] = options[:recurring_processing_model] || recurring_processing_model
|
212
|
+
end
|
213
|
+
|
186
214
|
def add_address(post, options)
|
187
215
|
return unless post[:card]&.kind_of?(Hash)
|
188
216
|
if (address = options[:billing_address] || options[:address]) && address[:country]
|
@@ -202,7 +230,6 @@ module ActiveMerchant #:nodoc:
|
|
202
230
|
currency: options[:currency] || currency(money)
|
203
231
|
}
|
204
232
|
post[:amount] = amount
|
205
|
-
post[:recurringProcessingModel] = options[:recurring_processing_model] if options[:recurring_processing_model]
|
206
233
|
end
|
207
234
|
|
208
235
|
def add_invoice_for_modification(post, money, options)
|
@@ -239,6 +266,11 @@ module ActiveMerchant #:nodoc:
|
|
239
266
|
post[:card] = card
|
240
267
|
end
|
241
268
|
|
269
|
+
def capture_options(options)
|
270
|
+
return options.merge(idempotency_key: "#{options[:idempotency_key]}-cap") if options[:idempotency_key]
|
271
|
+
options
|
272
|
+
end
|
273
|
+
|
242
274
|
def add_reference(post, authorization, options = {})
|
243
275
|
_, psp_reference, _ = authorization.split('#')
|
244
276
|
post[:originalReference] = single_reference(authorization) || psp_reference
|
@@ -286,9 +318,9 @@ module ActiveMerchant #:nodoc:
|
|
286
318
|
JSON.parse(body)
|
287
319
|
end
|
288
320
|
|
289
|
-
def commit(action, parameters)
|
321
|
+
def commit(action, parameters, options)
|
290
322
|
begin
|
291
|
-
raw_response = ssl_post("#{url}/#{action}", post_data(action, parameters), request_headers)
|
323
|
+
raw_response = ssl_post("#{url}/#{action}", post_data(action, parameters), request_headers(options))
|
292
324
|
response = parse(raw_response)
|
293
325
|
rescue ResponseError => e
|
294
326
|
raw_response = e.response.body
|
@@ -329,18 +361,20 @@ module ActiveMerchant #:nodoc:
|
|
329
361
|
Base64.strict_encode64("#{@username}:#{@password}")
|
330
362
|
end
|
331
363
|
|
332
|
-
def request_headers
|
333
|
-
{
|
364
|
+
def request_headers(options)
|
365
|
+
headers = {
|
334
366
|
'Content-Type' => 'application/json',
|
335
367
|
'Authorization' => "Basic #{basic_auth}"
|
336
368
|
}
|
369
|
+
headers['Idempotency-Key'] = options[:idempotency_key] if options[:idempotency_key]
|
370
|
+
headers
|
337
371
|
end
|
338
372
|
|
339
373
|
def success_from(action, response)
|
340
374
|
case action.to_s
|
341
375
|
when 'authorise', 'authorise3d'
|
342
376
|
['Authorised', 'Received', 'RedirectShopper'].include?(response['resultCode'])
|
343
|
-
when 'capture', 'refund', 'cancel'
|
377
|
+
when 'capture', 'refund', 'cancel', 'adjustAuthorisation'
|
344
378
|
response['response'] == "[#{action}-received]"
|
345
379
|
else
|
346
380
|
false
|
@@ -3,8 +3,8 @@ require 'nokogiri'
|
|
3
3
|
module ActiveMerchant #:nodoc:
|
4
4
|
module Billing #:nodoc:
|
5
5
|
class BamboraApacGateway < Gateway
|
6
|
-
self.live_url = 'https://www.bambora.co.nz/interface/api
|
7
|
-
self.test_url = 'https://demo.bambora.co.nz/interface/api
|
6
|
+
self.live_url = 'https://www.bambora.co.nz/interface/api'
|
7
|
+
self.test_url = 'https://demo.bambora.co.nz/interface/api'
|
8
8
|
|
9
9
|
self.supported_countries = ['AU', 'NZ']
|
10
10
|
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
|
@@ -32,7 +32,7 @@ module ActiveMerchant #:nodoc:
|
|
32
32
|
xml.CustRef options[:order_id]
|
33
33
|
add_amount(xml, money)
|
34
34
|
xml.TrnType '1'
|
35
|
-
|
35
|
+
add_payment(xml, payment)
|
36
36
|
add_credentials(xml, options)
|
37
37
|
xml.TrnSource options[:ip]
|
38
38
|
end
|
@@ -45,7 +45,7 @@ module ActiveMerchant #:nodoc:
|
|
45
45
|
xml.CustRef options[:order_id]
|
46
46
|
add_amount(xml, money)
|
47
47
|
xml.TrnType '2'
|
48
|
-
|
48
|
+
add_payment(xml, payment)
|
49
49
|
add_credentials(xml, options)
|
50
50
|
xml.TrnSource options[:ip]
|
51
51
|
end
|
@@ -82,6 +82,19 @@ module ActiveMerchant #:nodoc:
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
def store(payment, options={})
|
86
|
+
commit('TokeniseCreditCard') do |xml|
|
87
|
+
xml.TokeniseCreditCard do
|
88
|
+
xml.CardNumber payment.number
|
89
|
+
xml.ExpM format(payment.month, :two_digits)
|
90
|
+
xml.ExpY format(payment.year, :four_digits)
|
91
|
+
xml.TokeniseAlgorithmID options[:tokenise_algorithm_id] || 2
|
92
|
+
xml.UserName @options[:username]
|
93
|
+
xml.Password @options[:password]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
85
98
|
def supports_scrubbing?
|
86
99
|
true
|
87
100
|
end
|
@@ -107,6 +120,21 @@ module ActiveMerchant #:nodoc:
|
|
107
120
|
xml.Amount amount(money)
|
108
121
|
end
|
109
122
|
|
123
|
+
def add_payment(xml, payment)
|
124
|
+
if payment.is_a?(String)
|
125
|
+
add_token(xml, payment)
|
126
|
+
else
|
127
|
+
add_credit_card(xml, payment)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def add_token(xml, payment)
|
132
|
+
xml.CreditCard do
|
133
|
+
xml.TokeniseAlgorithmID options[:tokenise_algorithm_id] || 2
|
134
|
+
xml.CardNumber payment
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
110
138
|
def add_credit_card(xml, payment)
|
111
139
|
xml.CreditCard :Registered => 'False' do
|
112
140
|
xml.CardNumber payment.number
|
@@ -131,9 +159,9 @@ module ActiveMerchant #:nodoc:
|
|
131
159
|
def commit(action, &block)
|
132
160
|
headers = {
|
133
161
|
'Content-Type' => 'text/xml; charset=utf-8',
|
134
|
-
'SOAPAction' => "http://www.ippayments.com.au/interface/api
|
162
|
+
'SOAPAction' => "http://www.ippayments.com.au/interface/api/#{endpoint(action)}/#{action}"
|
135
163
|
}
|
136
|
-
response = parse(ssl_post(commit_url, new_submit_xml(action, &block), headers))
|
164
|
+
response = parse(ssl_post("#{commit_url}/#{endpoint(action)}.asmx", new_submit_xml(action, &block), headers))
|
137
165
|
|
138
166
|
Response.new(
|
139
167
|
success_from(response),
|
@@ -150,11 +178,19 @@ module ActiveMerchant #:nodoc:
|
|
150
178
|
xml.instruct!
|
151
179
|
xml.soap :Envelope, 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/' do
|
152
180
|
xml.soap :Body do
|
153
|
-
xml.__send__(action, 'xmlns' =>
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
181
|
+
xml.__send__(action, 'xmlns' => "http://www.ippayments.com.au/interface/api/#{endpoint(action)}") do
|
182
|
+
if action == 'TokeniseCreditCard'
|
183
|
+
xml.tokeniseCreditCardXML do
|
184
|
+
inner_xml = Builder::XmlMarkup.new(indent: 2)
|
185
|
+
yield(inner_xml)
|
186
|
+
xml.cdata!(inner_xml.target!)
|
187
|
+
end
|
188
|
+
else
|
189
|
+
xml.trnXML do
|
190
|
+
inner_xml = Builder::XmlMarkup.new(indent: 2)
|
191
|
+
yield(inner_xml)
|
192
|
+
xml.cdata!(inner_xml.target!)
|
193
|
+
end
|
158
194
|
end
|
159
195
|
end
|
160
196
|
end
|
@@ -162,12 +198,16 @@ module ActiveMerchant #:nodoc:
|
|
162
198
|
xml.target!
|
163
199
|
end
|
164
200
|
|
201
|
+
def endpoint(action)
|
202
|
+
action == 'TokeniseCreditCard' ? 'sipp' : 'dts'
|
203
|
+
end
|
204
|
+
|
165
205
|
def commit_url
|
166
206
|
test? ? test_url : live_url
|
167
207
|
end
|
168
208
|
|
169
209
|
def success_from(response)
|
170
|
-
response[:response_code] == '0'
|
210
|
+
response[:response_code] == '0' || response[:return_value] == '0'
|
171
211
|
end
|
172
212
|
|
173
213
|
def error_code_from(response)
|
@@ -175,11 +215,11 @@ module ActiveMerchant #:nodoc:
|
|
175
215
|
end
|
176
216
|
|
177
217
|
def message_from(response)
|
178
|
-
response[:declined_message]
|
218
|
+
success_from(response) ? 'Succeeded' : response[:declined_message]
|
179
219
|
end
|
180
220
|
|
181
221
|
def authorization_from(response)
|
182
|
-
response[:receipt]
|
222
|
+
response[:receipt] || response[:token]
|
183
223
|
end
|
184
224
|
end
|
185
225
|
end
|
@@ -24,7 +24,7 @@ module ActiveMerchant #:nodoc:
|
|
24
24
|
'REBID' => :rebid,
|
25
25
|
'TRANS_TYPE' => :trans_type,
|
26
26
|
'PAYMENT_ACCOUNT_MASK' => :acct_mask,
|
27
|
-
'CARD_TYPE' => :card_type
|
27
|
+
'CARD_TYPE' => :card_type
|
28
28
|
}
|
29
29
|
|
30
30
|
REBILL_FIELD_MAP = {
|
@@ -41,6 +41,7 @@ module ActiveMerchant #:nodoc:
|
|
41
41
|
'REB_AMOUNT' => :rebill_amount,
|
42
42
|
'NEXT_AMOUNT' => :next_amount,
|
43
43
|
'USUAL_DATE' => :undoc_usual_date, # Not found in the bp20rebadmin API doc.
|
44
|
+
'CUST_TOKEN' => :cust_token
|
44
45
|
}
|
45
46
|
|
46
47
|
self.supported_countries = ['US', 'CA']
|
@@ -84,7 +85,7 @@ module ActiveMerchant #:nodoc:
|
|
84
85
|
add_rebill(post, options) if options[:rebill]
|
85
86
|
add_duplicate_override(post, options)
|
86
87
|
post[:TRANS_TYPE] = 'AUTH'
|
87
|
-
commit('AUTH_ONLY', money, post)
|
88
|
+
commit('AUTH_ONLY', money, post, options)
|
88
89
|
end
|
89
90
|
|
90
91
|
# Perform a purchase, which is essentially an authorization and capture in a single operation.
|
@@ -107,7 +108,7 @@ module ActiveMerchant #:nodoc:
|
|
107
108
|
add_rebill(post, options) if options[:rebill]
|
108
109
|
add_duplicate_override(post, options)
|
109
110
|
post[:TRANS_TYPE] = 'SALE'
|
110
|
-
commit('AUTH_CAPTURE', money, post)
|
111
|
+
commit('AUTH_CAPTURE', money, post, options)
|
111
112
|
end
|
112
113
|
|
113
114
|
# Captures the funds from an authorize transaction.
|
@@ -123,7 +124,7 @@ module ActiveMerchant #:nodoc:
|
|
123
124
|
add_customer_data(post, options)
|
124
125
|
post[:MASTER_ID] = identification
|
125
126
|
post[:TRANS_TYPE] = 'CAPTURE'
|
126
|
-
commit('PRIOR_AUTH_CAPTURE', money, post)
|
127
|
+
commit('PRIOR_AUTH_CAPTURE', money, post, options)
|
127
128
|
end
|
128
129
|
|
129
130
|
# Void a previous transaction
|
@@ -136,7 +137,7 @@ module ActiveMerchant #:nodoc:
|
|
136
137
|
post = {}
|
137
138
|
post[:MASTER_ID] = identification
|
138
139
|
post[:TRANS_TYPE] = 'VOID'
|
139
|
-
commit('VOID', nil, post)
|
140
|
+
commit('VOID', nil, post, options)
|
140
141
|
end
|
141
142
|
|
142
143
|
# Performs a credit.
|
@@ -169,7 +170,7 @@ module ActiveMerchant #:nodoc:
|
|
169
170
|
add_invoice(post, options)
|
170
171
|
add_address(post, options)
|
171
172
|
add_customer_data(post, options)
|
172
|
-
commit('CREDIT', money, post)
|
173
|
+
commit('CREDIT', money, post, options)
|
173
174
|
end
|
174
175
|
|
175
176
|
def credit(money, payment_object, options = {})
|
@@ -189,7 +190,7 @@ module ActiveMerchant #:nodoc:
|
|
189
190
|
add_invoice(post, options)
|
190
191
|
add_address(post, options)
|
191
192
|
add_customer_data(post, options)
|
192
|
-
commit('CREDIT', money, post)
|
193
|
+
commit('CREDIT', money, post, options)
|
193
194
|
end
|
194
195
|
|
195
196
|
# Create a new recurring payment.
|
@@ -313,10 +314,11 @@ module ActiveMerchant #:nodoc:
|
|
313
314
|
|
314
315
|
private
|
315
316
|
|
316
|
-
def commit(action, money, fields)
|
317
|
+
def commit(action, money, fields, options = {})
|
317
318
|
fields[:AMOUNT] = amount(money) unless(fields[:TRANS_TYPE] == 'VOID' || action == 'rebill')
|
318
319
|
fields[:MODE] = (test? ? 'TEST' : 'LIVE')
|
319
320
|
fields[:ACCOUNT_ID] = @options[:login]
|
321
|
+
fields[:CUSTOMER_IP] = options[:ip] if options[:ip]
|
320
322
|
|
321
323
|
if action == 'rebill'
|
322
324
|
url = rebilling_url
|
@@ -543,6 +543,17 @@ module ActiveMerchant #:nodoc:
|
|
543
543
|
'token' => transaction.credit_card_details.token
|
544
544
|
}
|
545
545
|
|
546
|
+
if transaction.risk_data
|
547
|
+
risk_data = {
|
548
|
+
'id' => transaction.risk_data.id,
|
549
|
+
'decision' => transaction.risk_data.decision,
|
550
|
+
'device_data_captured' => transaction.risk_data.device_data_captured,
|
551
|
+
'fraud_service_provider' => transaction.risk_data.fraud_service_provider
|
552
|
+
}
|
553
|
+
else
|
554
|
+
risk_data = nil
|
555
|
+
end
|
556
|
+
|
546
557
|
{
|
547
558
|
'order_id' => transaction.order_id,
|
548
559
|
'amount' => transaction.amount.to_s,
|
@@ -553,6 +564,7 @@ module ActiveMerchant #:nodoc:
|
|
553
564
|
'shipping_details' => shipping_details,
|
554
565
|
'vault_customer' => vault_customer,
|
555
566
|
'merchant_account_id' => transaction.merchant_account_id,
|
567
|
+
'risk_data' => risk_data,
|
556
568
|
'processor_response_code' => response_code_from_result(result)
|
557
569
|
}
|
558
570
|
end
|
@@ -24,7 +24,7 @@ module ActiveMerchant #:nodoc:
|
|
24
24
|
self.test_url = 'https://ics2wstesta.ic3.com/commerce/1.x/transactionProcessor'
|
25
25
|
self.live_url = 'https://ics2wsa.ic3.com/commerce/1.x/transactionProcessor'
|
26
26
|
|
27
|
-
XSD_VERSION = '1.
|
27
|
+
XSD_VERSION = '1.153'
|
28
28
|
|
29
29
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro]
|
30
30
|
self.supported_countries = %w(US BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB)
|
@@ -260,6 +260,7 @@ module ActiveMerchant #:nodoc:
|
|
260
260
|
add_threeds_services(xml, options)
|
261
261
|
add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
|
262
262
|
add_business_rules_data(xml, creditcard_or_reference, options)
|
263
|
+
add_stored_credential_options(xml, options)
|
263
264
|
xml.target!
|
264
265
|
end
|
265
266
|
|
@@ -513,7 +514,24 @@ module ActiveMerchant #:nodoc:
|
|
513
514
|
if network_tokenization?(payment_method)
|
514
515
|
add_auth_network_tokenization(xml, payment_method, options)
|
515
516
|
else
|
516
|
-
xml.tag! 'ccAuthService', {'run' => 'true'}
|
517
|
+
xml.tag! 'ccAuthService', {'run' => 'true'} do
|
518
|
+
check_for_stored_cred_commerce_indicator(xml, options)
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
def check_for_stored_cred_commerce_indicator(xml, options)
|
524
|
+
return unless options[:stored_credential]
|
525
|
+
if commerce_indicator(options)
|
526
|
+
xml.tag!('commerceIndicator', commerce_indicator(options))
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
def commerce_indicator(options)
|
531
|
+
return if options[:stored_credential][:initial_transaction]
|
532
|
+
case options[:stored_credential][:reason_type]
|
533
|
+
when 'installment' then 'install'
|
534
|
+
when 'recurring' then 'recurring'
|
517
535
|
end
|
518
536
|
end
|
519
537
|
|
@@ -680,6 +698,18 @@ module ActiveMerchant #:nodoc:
|
|
680
698
|
country_code&.code(:alpha2)
|
681
699
|
end
|
682
700
|
|
701
|
+
def add_stored_credential_options(xml, options={})
|
702
|
+
return unless options[:stored_credential]
|
703
|
+
if options[:stored_credential][:initial_transaction]
|
704
|
+
xml.tag! 'subsequentAuthFirst', 'true'
|
705
|
+
elsif options[:stored_credential][:reason_type] == 'unscheduled'
|
706
|
+
xml.tag! 'subsequentAuth', 'true'
|
707
|
+
xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
|
708
|
+
else
|
709
|
+
xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
683
713
|
# Where we actually build the full SOAP request using builder
|
684
714
|
def build_request(body, options)
|
685
715
|
xml = Builder::XmlMarkup.new :indent => 2
|
@@ -93,7 +93,7 @@ module ActiveMerchant #:nodoc:
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def lookup_country_code(country)
|
96
|
-
Country.find(country).code(:alpha2)
|
96
|
+
Country.find(country).code(:alpha2).value
|
97
97
|
end
|
98
98
|
|
99
99
|
def add_payer(post, card, options)
|
@@ -102,7 +102,7 @@ module ActiveMerchant #:nodoc:
|
|
102
102
|
post[:payer][:name] = card.name
|
103
103
|
post[:payer][:email] = options[:email] if options[:email]
|
104
104
|
post[:payer][:birth_date] = options[:birth_date] if options[:birth_date]
|
105
|
-
post[:payer][:phone] = address[:phone] if address[:phone]
|
105
|
+
post[:payer][:phone] = address[:phone] if address && address[:phone]
|
106
106
|
post[:payer][:document] = options[:document] if options[:document]
|
107
107
|
post[:payer][:document2] = options[:document2] if options[:document2]
|
108
108
|
post[:payer][:user_reference] = options[:user_reference] if options[:user_reference]
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class FirstdataE4V27Gateway < Gateway
|
4
|
-
self.test_url = 'https://api.demo.globalgatewaye4.firstdata.com/transaction/
|
5
|
-
self.live_url = 'https://api.globalgatewaye4.firstdata.com/transaction/
|
4
|
+
self.test_url = 'https://api.demo.globalgatewaye4.firstdata.com/transaction/v28'
|
5
|
+
self.live_url = 'https://api.globalgatewaye4.firstdata.com/transaction/v28'
|
6
6
|
|
7
7
|
TRANSACTIONS = {
|
8
8
|
sale: '00',
|
@@ -148,6 +148,7 @@ module ActiveMerchant #:nodoc:
|
|
148
148
|
add_credit_card_token(xml, credit_card_or_store_authorization, options)
|
149
149
|
else
|
150
150
|
add_credit_card(xml, credit_card_or_store_authorization, options)
|
151
|
+
add_stored_credentials(xml, credit_card_or_store_authorization, options)
|
151
152
|
end
|
152
153
|
|
153
154
|
add_address(xml, options)
|
@@ -312,6 +313,35 @@ module ActiveMerchant #:nodoc:
|
|
312
313
|
xml.tag!('Level3') { |x| x << options[:level_3] } if options[:level_3]
|
313
314
|
end
|
314
315
|
|
316
|
+
def add_stored_credentials(xml, card, options)
|
317
|
+
return unless options[:stored_credential]
|
318
|
+
xml.tag! 'StoredCredentials' do
|
319
|
+
xml.tag! 'Indicator', stored_credential_indicator(xml, card, options)
|
320
|
+
if initiator = options.dig(:stored_credential, :initiator)
|
321
|
+
xml.tag! initiator == 'merchant' ? 'M' : 'C'
|
322
|
+
end
|
323
|
+
if reason_type = options.dig(:stored_credential, :reason_type)
|
324
|
+
xml.tag! 'Schedule', reason_type == 'unscheduled' ? 'U' : 'S'
|
325
|
+
end
|
326
|
+
xml.tag! 'AuthorizationTypeOverride', options[:authorization_type_override] if options[:authorization_type_override]
|
327
|
+
if network_transaction_id = options[:stored_credential][:network_transaction_id]
|
328
|
+
xml.tag! 'TransactionId', network_transaction_id
|
329
|
+
else
|
330
|
+
xml.tag! 'TransactionId', 'new'
|
331
|
+
end
|
332
|
+
xml.tag! 'OriginalAmount', options[:original_amount] if options[:original_amount]
|
333
|
+
xml.tag! 'ProtectbuyIndicator', options[:protectbuy_indicator] if options[:protectbuy_indicator]
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def stored_credential_indicator(xml, card, options)
|
338
|
+
if card.brand == 'master' || options.dig(:stored_credential, :initial_transaction) == false
|
339
|
+
'S'
|
340
|
+
else
|
341
|
+
'1'
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
315
345
|
def expdate(credit_card)
|
316
346
|
"#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
|
317
347
|
end
|
@@ -438,9 +468,18 @@ module ActiveMerchant #:nodoc:
|
|
438
468
|
|
439
469
|
def parse_elements(response, root)
|
440
470
|
root.elements.to_a.each do |node|
|
441
|
-
|
471
|
+
if node.has_elements?
|
472
|
+
parse_elements(response, node)
|
473
|
+
else
|
474
|
+
response[name_node(root, node)] = (node.text || '').strip
|
475
|
+
end
|
442
476
|
end
|
443
477
|
end
|
478
|
+
|
479
|
+
def name_node(root, node)
|
480
|
+
parent = root.name unless root.name == 'TransactionResult'
|
481
|
+
"#{parent}#{node.name}".gsub(/EXact/, 'Exact').underscore.to_sym
|
482
|
+
end
|
444
483
|
end
|
445
484
|
end
|
446
485
|
end
|
@@ -3,7 +3,7 @@ require 'nokogiri'
|
|
3
3
|
module ActiveMerchant #:nodoc:
|
4
4
|
module Billing #:nodoc:
|
5
5
|
class LitleGateway < Gateway
|
6
|
-
SCHEMA_VERSION = '9.
|
6
|
+
SCHEMA_VERSION = '9.14'
|
7
7
|
|
8
8
|
self.test_url = 'https://www.testvantivcnp.com/sandbox/communicator/online'
|
9
9
|
self.live_url = 'https://payments.vantivcnp.com/vap/communicator/online'
|
@@ -223,6 +223,7 @@ module ActiveMerchant #:nodoc:
|
|
223
223
|
add_descriptor(doc, options)
|
224
224
|
add_merchant_data(doc, options)
|
225
225
|
add_debt_repayment(doc, options)
|
226
|
+
add_stored_credential_params(doc, options)
|
226
227
|
end
|
227
228
|
|
228
229
|
def add_merchant_data(doc, options={})
|
@@ -293,6 +294,38 @@ module ActiveMerchant #:nodoc:
|
|
293
294
|
end
|
294
295
|
end
|
295
296
|
|
297
|
+
def add_stored_credential_params(doc, options={})
|
298
|
+
return unless options[:stored_credential]
|
299
|
+
|
300
|
+
if options[:stored_credential][:initial_transaction]
|
301
|
+
add_stored_credential_params_initial(doc, options)
|
302
|
+
else
|
303
|
+
add_stored_credential_params_used(doc, options)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def add_stored_credential_params_initial(doc, options)
|
308
|
+
case options[:stored_credential][:reason_type]
|
309
|
+
when 'unscheduled'
|
310
|
+
doc.processingType('initialCOF')
|
311
|
+
when 'installment'
|
312
|
+
doc.processingType('initialInstallment')
|
313
|
+
when 'recurring'
|
314
|
+
doc.processingType('initialRecurring')
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def add_stored_credential_params_used(doc, options)
|
319
|
+
if options[:stored_credential][:reason_type] == 'unscheduled'
|
320
|
+
if options[:stored_credential][:initiator] == 'merchant'
|
321
|
+
doc.processingType('merchantInitiatedCOF')
|
322
|
+
else
|
323
|
+
doc.processingType('cardholderInitiatedCOF')
|
324
|
+
end
|
325
|
+
end
|
326
|
+
doc.originalNetworkTransactionId(options[:stored_credential][:network_transaction_id])
|
327
|
+
end
|
328
|
+
|
296
329
|
def add_billing_address(doc, payment_method, options)
|
297
330
|
return if payment_method.is_a?(String)
|
298
331
|
|
@@ -332,8 +365,9 @@ module ActiveMerchant #:nodoc:
|
|
332
365
|
end
|
333
366
|
|
334
367
|
def add_order_source(doc, payment_method, options)
|
335
|
-
|
336
|
-
|
368
|
+
order_source = order_source(options)
|
369
|
+
if order_source
|
370
|
+
doc.orderSource(order_source)
|
337
371
|
elsif payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :apple_pay
|
338
372
|
doc.orderSource('applepay')
|
339
373
|
elsif payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :android_pay
|
@@ -345,6 +379,30 @@ module ActiveMerchant #:nodoc:
|
|
345
379
|
end
|
346
380
|
end
|
347
381
|
|
382
|
+
def order_source(options={})
|
383
|
+
return options[:order_source] unless options[:stored_credential]
|
384
|
+
order_source = nil
|
385
|
+
|
386
|
+
case options[:stored_credential][:reason_type]
|
387
|
+
when 'unscheduled'
|
388
|
+
if options[:stored_credential][:initiator] == 'merchant'
|
389
|
+
# For merchant-initiated, we should always set order source to
|
390
|
+
# 'ecommerce'
|
391
|
+
order_source = 'ecommerce'
|
392
|
+
else
|
393
|
+
# For cardholder-initiated, we rely on #add_order_source's
|
394
|
+
# default logic to set orderSource appropriately
|
395
|
+
order_source = options[:order_source]
|
396
|
+
end
|
397
|
+
when 'installment'
|
398
|
+
order_source = 'installment'
|
399
|
+
when 'recurring'
|
400
|
+
order_source = 'recurring'
|
401
|
+
end
|
402
|
+
|
403
|
+
order_source
|
404
|
+
end
|
405
|
+
|
348
406
|
def add_pos(doc, payment_method)
|
349
407
|
return unless payment_method.respond_to?(:track_data) && payment_method.track_data.present?
|
350
408
|
|
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.live_url = self.test_url = 'https://api.mercadopago.com/v1'
|
5
5
|
|
6
6
|
self.supported_countries = ['AR', 'BR', 'CL', 'CO', 'MX', 'PE', 'UY']
|
7
|
-
self.supported_cardtypes = [:visa, :master, :american_express]
|
7
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :elo]
|
8
8
|
|
9
9
|
self.homepage_url = 'https://www.mercadopago.com/'
|
10
10
|
self.display_name = 'Mercado Pago'
|
@@ -128,8 +128,8 @@ module ActiveMerchant #:nodoc:
|
|
128
128
|
def add_shipping_address(post, options)
|
129
129
|
if address = options[:shipping_address]
|
130
130
|
post[:address] = {}
|
131
|
-
post[:address][:street] = address[:address1].match(/\D+/)[0].strip if address[:address1]
|
132
|
-
post[:address][:number] = address[:address1].match(/\d+/)[0] if address[:address1]
|
131
|
+
post[:address][:street] = address[:address1].match(/\D+/)[0].strip if address[:address1]&.match(/\D+/)
|
132
|
+
post[:address][:number] = address[:address1].match(/\d+/)[0] if address[:address1]&.match(/\d+/)
|
133
133
|
post[:address][:compliment] = address[:address2] if address[:address2]
|
134
134
|
post[:address][:city] = address[:city] if address[:city]
|
135
135
|
post[:address][:state] = address[:state] if address[:state]
|
@@ -507,9 +507,33 @@ module ActiveMerchant #:nodoc:
|
|
507
507
|
end
|
508
508
|
|
509
509
|
def add_stored_credentials(xml, parameters)
|
510
|
-
|
511
|
-
|
512
|
-
|
510
|
+
return unless parameters[:mit_stored_credential_ind] == 'Y' || parameters[:stored_credential] && !parameters[:stored_credential].values.all?(&:nil?)
|
511
|
+
if msg_type = get_msg_type(parameters)
|
512
|
+
xml.tag! :MITMsgType, msg_type
|
513
|
+
end
|
514
|
+
xml.tag! :MITStoredCredentialInd, 'Y'
|
515
|
+
if parameters[:mit_submitted_transaction_id]
|
516
|
+
xml.tag! :MITSubmittedTransactionID, parameters[:mit_submitted_transaction_id]
|
517
|
+
elsif parameters.dig(:stored_credential, :network_transaction_id) && parameters.dig(:stored_credential, :initiator) == 'merchant'
|
518
|
+
xml.tag! :MITSubmittedTransactionID, parameters[:stored_credential][:network_transaction_id]
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
def get_msg_type(parameters)
|
523
|
+
return parameters[:mit_msg_type] if parameters[:mit_msg_type]
|
524
|
+
return 'CSTO' if parameters[:stored_credential][:initial_transaction]
|
525
|
+
return unless parameters[:stored_credential][:initiator] && parameters[:stored_credential][:reason_type]
|
526
|
+
initiator = case parameters[:stored_credential][:initiator]
|
527
|
+
when 'customer' then 'C'
|
528
|
+
when 'merchant' then 'M'
|
529
|
+
end
|
530
|
+
reason = case parameters[:stored_credential][:reason_type]
|
531
|
+
when 'recurring' then 'REC'
|
532
|
+
when 'installment' then 'INS'
|
533
|
+
when 'unscheduled' then 'USE'
|
534
|
+
end
|
535
|
+
|
536
|
+
"#{initiator}#{reason}"
|
513
537
|
end
|
514
538
|
|
515
539
|
def parse(body)
|
@@ -153,6 +153,7 @@ module ActiveMerchant #:nodoc:
|
|
153
153
|
add_invoice(result, options)
|
154
154
|
add_address_verification_data(result, options)
|
155
155
|
add_optional_elements(result, options)
|
156
|
+
add_ip(result, options)
|
156
157
|
result
|
157
158
|
end
|
158
159
|
|
@@ -163,6 +164,7 @@ module ActiveMerchant #:nodoc:
|
|
163
164
|
add_invoice(result, options)
|
164
165
|
add_reference(result, identification)
|
165
166
|
add_optional_elements(result, options)
|
167
|
+
add_ip(result, options)
|
166
168
|
result
|
167
169
|
end
|
168
170
|
|
@@ -172,6 +174,7 @@ module ActiveMerchant #:nodoc:
|
|
172
174
|
add_amount(result, 100, options) # need to make an auth request for $1
|
173
175
|
add_token_request(result, options)
|
174
176
|
add_optional_elements(result, options)
|
177
|
+
add_ip(result, options)
|
175
178
|
result
|
176
179
|
end
|
177
180
|
|
@@ -233,6 +236,10 @@ module ActiveMerchant #:nodoc:
|
|
233
236
|
xml.add_element('AvsPostCode').text = address[:zip]
|
234
237
|
end
|
235
238
|
|
239
|
+
def add_ip(xml, options)
|
240
|
+
xml.add_element('ClientInfo').text = options[:ip] if options[:ip]
|
241
|
+
end
|
242
|
+
|
236
243
|
# The options hash may contain optional data which will be passed
|
237
244
|
# through the specialized optional fields at PaymentExpress
|
238
245
|
# as follows:
|
@@ -241,8 +248,7 @@ module ActiveMerchant #:nodoc:
|
|
241
248
|
# :client_type => :web, # Possible values are: :web, :ivr, :moto, :unattended, :internet, or :recurring
|
242
249
|
# :txn_data1 => "String up to 255 characters",
|
243
250
|
# :txn_data2 => "String up to 255 characters",
|
244
|
-
# :txn_data3 => "String up to 255 characters"
|
245
|
-
# :client_info => "String up to 15 characters. The IP address of the user who processed the transaction."
|
251
|
+
# :txn_data3 => "String up to 255 characters"
|
246
252
|
# }
|
247
253
|
#
|
248
254
|
# +:client_type+, while not documented for PxPost, will be sent as
|
@@ -278,8 +284,6 @@ module ActiveMerchant #:nodoc:
|
|
278
284
|
xml.add_element('TxnData1').text = options[:txn_data1].to_s.slice(0, 255) unless options[:txn_data1].blank?
|
279
285
|
xml.add_element('TxnData2').text = options[:txn_data2].to_s.slice(0, 255) unless options[:txn_data2].blank?
|
280
286
|
xml.add_element('TxnData3').text = options[:txn_data3].to_s.slice(0, 255) unless options[:txn_data3].blank?
|
281
|
-
|
282
|
-
xml.add_element('ClientInfo').text = options[:client_info] if options[:client_info]
|
283
287
|
end
|
284
288
|
|
285
289
|
def new_transaction
|
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
|
|
9
9
|
|
10
10
|
self.supported_countries = %w[MX EC VE CO BR CL]
|
11
11
|
self.default_currency = 'USD'
|
12
|
-
self.supported_cardtypes = %i[visa master american_express diners_club]
|
12
|
+
self.supported_cardtypes = %i[visa master american_express diners_club elo]
|
13
13
|
|
14
14
|
self.homepage_url = 'https://secure.paymentez.com/'
|
15
15
|
self.display_name = 'Paymentez'
|
@@ -38,7 +38,8 @@ module ActiveMerchant #:nodoc:
|
|
38
38
|
'visa' => 'vi',
|
39
39
|
'master' => 'mc',
|
40
40
|
'american_express' => 'ax',
|
41
|
-
'diners_club' => 'di'
|
41
|
+
'diners_club' => 'di',
|
42
|
+
'elo' => 'el'
|
42
43
|
}.freeze
|
43
44
|
|
44
45
|
def initialize(options = {})
|
@@ -146,7 +146,9 @@ module ActiveMerchant #:nodoc:
|
|
146
146
|
xml.tag! 'n2:cpp-payflow-color', options[:background_color] unless options[:background_color].blank?
|
147
147
|
if options[:allow_guest_checkout]
|
148
148
|
xml.tag! 'n2:SolutionType', 'Sole'
|
149
|
-
|
149
|
+
unless options[:paypal_chooses_landing_page]
|
150
|
+
xml.tag! 'n2:LandingPage', options[:landing_page] || 'Billing'
|
151
|
+
end
|
150
152
|
end
|
151
153
|
xml.tag! 'n2:BuyerEmail', options[:email] unless options[:email].blank?
|
152
154
|
|
@@ -103,7 +103,7 @@ module ActiveMerchant
|
|
103
103
|
post = {}
|
104
104
|
|
105
105
|
add_amount(post, money, options)
|
106
|
-
add_credit_card_or_reference(post, credit_card_or_reference)
|
106
|
+
add_credit_card_or_reference(post, credit_card_or_reference, options)
|
107
107
|
add_additional_params(:authorize, post, options)
|
108
108
|
|
109
109
|
post
|
@@ -217,6 +217,12 @@ module ActiveMerchant
|
|
217
217
|
post[:card][:expiration] = expdate(credit_card_or_reference)
|
218
218
|
post[:card][:issued_to] = credit_card_or_reference.name
|
219
219
|
end
|
220
|
+
|
221
|
+
if options[:three_d_secure]
|
222
|
+
post[:card][:cavv]= options.dig(:three_d_secure, :cavv)
|
223
|
+
post[:card][:eci] = options.dig(:three_d_secure, :eci)
|
224
|
+
post[:card][:xav] = options.dig(:three_d_secure, :xid)
|
225
|
+
end
|
220
226
|
end
|
221
227
|
|
222
228
|
def parse(body)
|
@@ -145,7 +145,11 @@ module ActiveMerchant
|
|
145
145
|
add_card(xml, credit_card)
|
146
146
|
xml.tag! 'autosettle', 'flag' => auto_settle_flag(action)
|
147
147
|
add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), credit_card.number)
|
148
|
-
|
148
|
+
if credit_card.is_a?(NetworkTokenizationCreditCard)
|
149
|
+
add_network_tokenization_card(xml, credit_card)
|
150
|
+
else
|
151
|
+
add_three_d_secure(xml, options)
|
152
|
+
end
|
149
153
|
add_comments(xml, options)
|
150
154
|
add_address_and_customer_info(xml, options)
|
151
155
|
end
|
@@ -284,6 +288,16 @@ module ActiveMerchant
|
|
284
288
|
end
|
285
289
|
end
|
286
290
|
|
291
|
+
def add_three_d_secure(xml, options)
|
292
|
+
if options[:three_d_secure]
|
293
|
+
xml.tag! 'mpi' do
|
294
|
+
xml.tag! 'cavv', options[:three_d_secure][:cavv]
|
295
|
+
xml.tag! 'eci', options[:three_d_secure][:eci]
|
296
|
+
xml.tag! 'xid', options[:three_d_secure][:xid]
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
287
301
|
def format_address_code(address)
|
288
302
|
code = [address[:zip].to_s, address[:address1].to_s + address[:address2].to_s]
|
289
303
|
code.collect { |e| e.gsub(/\D/, '') }.reject(&:empty?).join('|')
|
@@ -57,7 +57,10 @@ module ActiveMerchant #:nodoc:
|
|
57
57
|
response = commit('cancelDeposit', params, options)
|
58
58
|
return response if response.success? || split_authorization(authorization).length == 1 || !options[:force_full_refund_if_unsettled]
|
59
59
|
|
60
|
-
# Attempt RefundSingleTransaction if unsettled
|
60
|
+
# Attempt RefundSingleTransaction if unsettled (and stash the original
|
61
|
+
# response message so it will be included it in the follow-up response
|
62
|
+
# message)
|
63
|
+
options[:error_message] = response.message
|
61
64
|
prepare_refund_data(params, authorization, options)
|
62
65
|
commit('refund', params, options)
|
63
66
|
end
|
@@ -197,15 +200,24 @@ module ActiveMerchant #:nodoc:
|
|
197
200
|
end
|
198
201
|
|
199
202
|
def message_from(response, options, action)
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
203
|
+
message_from_messages(
|
204
|
+
response['errorMessage'],
|
205
|
+
action_code_description(response),
|
206
|
+
options[:error_message]
|
207
|
+
)
|
208
|
+
end
|
209
|
+
|
210
|
+
def message_from_messages(*args)
|
211
|
+
args.reject { |m| error_message_empty?(m) }.join(' | ')
|
212
|
+
end
|
213
|
+
|
214
|
+
def action_code_description(response)
|
215
|
+
return nil unless response['data']
|
216
|
+
response['data']['DSC_COD_ACCION']
|
217
|
+
end
|
218
|
+
|
219
|
+
def error_message_empty?(error_message)
|
220
|
+
empty?(error_message) || error_message == '[ ]'
|
209
221
|
end
|
210
222
|
|
211
223
|
def response_error(raw_response, options, action)
|
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
|
|
7
7
|
self.default_currency = 'GBP'
|
8
8
|
self.money_format = :cents
|
9
9
|
self.supported_countries = %w(HK GB AU AD AR BE BR CA CH CN CO CR CY CZ DE DK ES FI FR GI GR HU IE IN IT JP LI LU MC MT MY MX NL NO NZ PA PE PL PT SE SG SI SM TR UM VA)
|
10
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro]
|
10
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :elo]
|
11
11
|
self.currencies_without_fractions = %w(HUF IDR ISK JPY KRW)
|
12
12
|
self.currencies_with_three_decimal_places = %w(BHD KWD OMR RSD TND)
|
13
13
|
self.homepage_url = 'http://www.worldpay.com/'
|
@@ -21,6 +21,7 @@ module ActiveMerchant #:nodoc:
|
|
21
21
|
'jcb' => 'JCB-SSL',
|
22
22
|
'maestro' => 'MAESTRO-SSL',
|
23
23
|
'diners_club' => 'DINERS-SSL',
|
24
|
+
'elo' => 'ELO-SSL'
|
24
25
|
}
|
25
26
|
|
26
27
|
AVS_CODE_MAP = {
|
@@ -262,13 +263,23 @@ module ActiveMerchant #:nodoc:
|
|
262
263
|
|
263
264
|
add_address(xml, (options[:billing_address] || options[:address]))
|
264
265
|
end
|
266
|
+
add_stored_credential_options(xml, options)
|
265
267
|
if options[:ip] && options[:session_id]
|
266
268
|
xml.tag! 'session', 'shopperIPAddress' => options[:ip], 'id' => options[:session_id]
|
267
269
|
else
|
268
270
|
xml.tag! 'session', 'shopperIPAddress' => options[:ip] if options[:ip]
|
269
271
|
xml.tag! 'session', 'id' => options[:session_id] if options[:session_id]
|
270
272
|
end
|
271
|
-
|
273
|
+
|
274
|
+
if three_d_secure = options[:three_d_secure]
|
275
|
+
xml.tag! 'info3DSecure' do
|
276
|
+
xml.tag! 'threeDSVersion', three_d_secure[:version]
|
277
|
+
xid_tag = three_d_secure[:version] =~ /^2/ ? 'dsTransactionId' : 'xid'
|
278
|
+
xml.tag! xid_tag, three_d_secure[:xid]
|
279
|
+
xml.tag! 'cavv', three_d_secure[:cavv]
|
280
|
+
xml.tag! 'eci', three_d_secure[:eci]
|
281
|
+
end
|
282
|
+
end
|
272
283
|
end
|
273
284
|
end
|
274
285
|
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.92.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: 2019-
|
11
|
+
date: 2019-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|