activemerchant 1.90.0 → 1.99.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 +202 -0
- data/README.md +6 -2
- data/lib/active_merchant/billing/avs_result.rb +4 -5
- data/lib/active_merchant/billing/credit_card.rb +8 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +81 -5
- data/lib/active_merchant/billing/gateway.rb +10 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +206 -54
- data/lib/active_merchant/billing/gateways/bambora_apac.rb +226 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +3 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +11 -6
- data/lib/active_merchant/billing/gateways/blue_pay.rb +10 -8
- data/lib/active_merchant/billing/gateways/blue_snap.rb +211 -36
- data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +79 -18
- data/lib/active_merchant/billing/gateways/card_connect.rb +6 -1
- data/lib/active_merchant/billing/gateways/cecabank.rb +20 -9
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +98 -61
- data/lib/active_merchant/billing/gateways/credorax.rb +69 -4
- data/lib/active_merchant/billing/gateways/cyber_source.rb +85 -14
- data/lib/active_merchant/billing/gateways/d_local.rb +3 -3
- data/lib/active_merchant/billing/gateways/decidir.rb +245 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +9 -0
- data/lib/active_merchant/billing/gateways/epay.rb +13 -2
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +42 -12
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +26 -7
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +42 -3
- data/lib/active_merchant/billing/gateways/global_collect.rb +3 -7
- data/lib/active_merchant/billing/gateways/hps.rb +46 -1
- data/lib/active_merchant/billing/gateways/ipp.rb +1 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
- data/lib/active_merchant/billing/gateways/litle.rb +61 -3
- data/lib/active_merchant/billing/gateways/mastercard.rb +30 -5
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
- data/lib/active_merchant/billing/gateways/migs.rb +8 -0
- data/lib/active_merchant/billing/gateways/monei.rb +31 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +3 -4
- data/lib/active_merchant/billing/gateways/mundipagg.rb +37 -9
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/netbanx.rb +4 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +45 -5
- data/lib/active_merchant/billing/gateways/openpay.rb +1 -1
- data/lib/active_merchant/billing/gateways/opp.rb +20 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +92 -11
- data/lib/active_merchant/billing/gateways/payflow.rb +64 -14
- data/lib/active_merchant/billing/gateways/payment_express.rb +7 -0
- data/lib/active_merchant/billing/gateways/paymentez.rb +7 -11
- data/lib/active_merchant/billing/gateways/paymill.rb +5 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +14 -1
- data/lib/active_merchant/billing/gateways/paypal_express.rb +3 -1
- data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -2
- data/lib/active_merchant/billing/gateways/pin.rb +19 -6
- data/lib/active_merchant/billing/gateways/pro_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -1
- data/lib/active_merchant/billing/gateways/qvalent.rb +54 -1
- data/lib/active_merchant/billing/gateways/realex.rb +42 -5
- data/lib/active_merchant/billing/gateways/redsys.rb +113 -30
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +43 -29
- data/lib/active_merchant/billing/gateways/stripe.rb +66 -34
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +271 -0
- data/lib/active_merchant/billing/gateways/tns.rb +10 -5
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +5 -5
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +46 -6
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +19 -8
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +22 -10
- data/lib/active_merchant/billing/gateways/worldpay.rb +237 -34
- data/lib/active_merchant/country.rb +2 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +20 -4
|
@@ -133,6 +133,7 @@ module ActiveMerchant #:nodoc:
|
|
|
133
133
|
add_payment(xml, action, money, options)
|
|
134
134
|
add_account(xml, credit_card)
|
|
135
135
|
add_customer(xml, credit_card, options)
|
|
136
|
+
add_three_d_secure(xml, options)
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
commit(request)
|
|
@@ -225,6 +226,36 @@ module ActiveMerchant #:nodoc:
|
|
|
225
226
|
end
|
|
226
227
|
end
|
|
227
228
|
|
|
229
|
+
# Private : Convert ECI to ResultIndicator
|
|
230
|
+
# Possible ECI values:
|
|
231
|
+
# 02 or 05 - Fully Authenticated Transaction
|
|
232
|
+
# 00 or 07 - Non 3D Secure Transaction
|
|
233
|
+
# Possible ResultIndicator values:
|
|
234
|
+
# 01 = MASTER_3D_ATTEMPT
|
|
235
|
+
# 02 = MASTER_3D_SUCCESS
|
|
236
|
+
# 05 = VISA_3D_SUCCESS
|
|
237
|
+
# 06 = VISA_3D_ATTEMPT
|
|
238
|
+
# 07 = DEFAULT_E_COMMERCE
|
|
239
|
+
def eci_to_result_indicator(eci)
|
|
240
|
+
case eci
|
|
241
|
+
when '02', '05'
|
|
242
|
+
return eci
|
|
243
|
+
else
|
|
244
|
+
return '07'
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Private : Add the 3DSecure infos to XML
|
|
249
|
+
def add_three_d_secure(xml, options)
|
|
250
|
+
if options[:three_d_secure]
|
|
251
|
+
xml.Authentication(:type => '3DSecure') do
|
|
252
|
+
xml.ResultIndicator eci_to_result_indicator options[:three_d_secure][:eci]
|
|
253
|
+
xml.Parameter(:name => 'VERIFICATION_ID') { xml.text options[:three_d_secure][:cavv] }
|
|
254
|
+
xml.Parameter(:name => 'XID') { xml.text options[:three_d_secure][:xid] }
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
228
259
|
# Private: Parse XML response from Monei servers
|
|
229
260
|
def parse(body)
|
|
230
261
|
xml = Nokogiri::XML(body)
|
|
@@ -33,7 +33,6 @@ module ActiveMerchant #:nodoc:
|
|
|
33
33
|
requires!(options, :login, :password)
|
|
34
34
|
@cvv_enabled = options[:cvv_enabled]
|
|
35
35
|
@avs_enabled = options[:avs_enabled]
|
|
36
|
-
@cof_enabled = options[:cof_enabled]
|
|
37
36
|
options[:crypt_type] = 7 unless options.has_key?(:crypt_type)
|
|
38
37
|
super
|
|
39
38
|
end
|
|
@@ -51,7 +50,7 @@ module ActiveMerchant #:nodoc:
|
|
|
51
50
|
post[:order_id] = options[:order_id]
|
|
52
51
|
post[:address] = options[:billing_address] || options[:address]
|
|
53
52
|
post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
|
|
54
|
-
add_cof(post, options)
|
|
53
|
+
add_cof(post, options)
|
|
55
54
|
action = if post[:cavv]
|
|
56
55
|
'cavv_preauth'
|
|
57
56
|
elsif post[:data_key].blank?
|
|
@@ -74,7 +73,7 @@ module ActiveMerchant #:nodoc:
|
|
|
74
73
|
post[:order_id] = options[:order_id]
|
|
75
74
|
post[:address] = options[:billing_address] || options[:address]
|
|
76
75
|
post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
|
|
77
|
-
add_cof(post, options)
|
|
76
|
+
add_cof(post, options)
|
|
78
77
|
action = if post[:cavv]
|
|
79
78
|
'cavv_purchase'
|
|
80
79
|
elsif post[:data_key].blank?
|
|
@@ -293,7 +292,7 @@ module ActiveMerchant #:nodoc:
|
|
|
293
292
|
when :cvd_info
|
|
294
293
|
transaction.add_element(cvd_element(parameters[:cvd_value])) if @cvv_enabled
|
|
295
294
|
when :cof_info
|
|
296
|
-
transaction.add_element(credential_on_file(parameters)) if
|
|
295
|
+
transaction.add_element(credential_on_file(parameters)) if cof_details_present?(parameters)
|
|
297
296
|
else
|
|
298
297
|
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
|
|
299
298
|
end
|
|
@@ -5,7 +5,7 @@ module ActiveMerchant #:nodoc:
|
|
|
5
5
|
|
|
6
6
|
self.supported_countries = ['US']
|
|
7
7
|
self.default_currency = 'USD'
|
|
8
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
|
8
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :alelo]
|
|
9
9
|
|
|
10
10
|
self.homepage_url = 'https://www.mundipagg.com/'
|
|
11
11
|
self.display_name = 'Mundipagg'
|
|
@@ -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]
|
|
@@ -155,7 +155,8 @@ module ActiveMerchant #:nodoc:
|
|
|
155
155
|
post[:customer][:name] = payment.name if post[:customer]
|
|
156
156
|
post[:customer_id] = parse_auth(payment)[0] if payment.is_a?(String)
|
|
157
157
|
post[:payment] = {}
|
|
158
|
-
|
|
158
|
+
affiliation = options[:gateway_affiliation_id] || @options[:gateway_id]
|
|
159
|
+
post[:payment][:gateway_affiliation_id] = affiliation if affiliation
|
|
159
160
|
post[:payment][:metadata] = { mundipagg_payment_method_code: '1' } if test?
|
|
160
161
|
if voucher?(payment)
|
|
161
162
|
add_voucher(post, payment, options)
|
|
@@ -248,7 +249,8 @@ module ActiveMerchant #:nodoc:
|
|
|
248
249
|
error_code: error_code_from(response)
|
|
249
250
|
)
|
|
250
251
|
rescue ResponseError => e
|
|
251
|
-
message =
|
|
252
|
+
message = get_error_messages(e)
|
|
253
|
+
|
|
252
254
|
return Response.new(
|
|
253
255
|
false,
|
|
254
256
|
"#{STANDARD_ERROR_MESSAGE_MAPPING[e.response.code]} #{message}",
|
|
@@ -262,15 +264,41 @@ module ActiveMerchant #:nodoc:
|
|
|
262
264
|
%w[pending paid processing canceled active].include? response['status']
|
|
263
265
|
end
|
|
264
266
|
|
|
265
|
-
def get_error_message(error)
|
|
266
|
-
JSON.parse(error.response.body)['message']
|
|
267
|
-
end
|
|
268
|
-
|
|
269
267
|
def message_from(response)
|
|
268
|
+
return gateway_response_errors(response) if gateway_response_errors?(response)
|
|
270
269
|
return response['message'] if response['message']
|
|
271
270
|
return response['last_transaction']['acquirer_message'] if response['last_transaction']
|
|
272
271
|
end
|
|
273
272
|
|
|
273
|
+
def get_error_messages(error)
|
|
274
|
+
parsed_response_body = parse(error.response.body)
|
|
275
|
+
message = parsed_response_body['message']
|
|
276
|
+
|
|
277
|
+
parsed_response_body['errors']&.each do |type, descriptions|
|
|
278
|
+
message += ' | '
|
|
279
|
+
message += descriptions.join(', ')
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
message
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def gateway_response_errors?(response)
|
|
286
|
+
response.try(:[], 'last_transaction').try(:[], 'gateway_response').try(:[], 'errors').present?
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def gateway_response_errors(response)
|
|
290
|
+
error_string = ''
|
|
291
|
+
|
|
292
|
+
response['last_transaction']['gateway_response']['errors']&.each do |error|
|
|
293
|
+
error.each do |key, value|
|
|
294
|
+
error_string += ' | ' unless error_string.blank?
|
|
295
|
+
error_string += value
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
error_string
|
|
300
|
+
end
|
|
301
|
+
|
|
274
302
|
def authorization_from(response, action)
|
|
275
303
|
return "#{response['customer']['id']}|#{response['id']}" if action == 'store'
|
|
276
304
|
response['id']
|
|
@@ -12,7 +12,7 @@ module ActiveMerchant #:nodoc:
|
|
|
12
12
|
|
|
13
13
|
self.test_url = 'https://demo.transact.nab.com.au/xmlapi/payment'
|
|
14
14
|
self.live_url = 'https://transact.nab.com.au/live/xmlapi/payment'
|
|
15
|
-
self.test_periodic_url = 'https://transact.nab.com.au/
|
|
15
|
+
self.test_periodic_url = 'https://demo.transact.nab.com.au/xmlapi/periodic'
|
|
16
16
|
self.live_periodic_url = 'https://transact.nab.com.au/xmlapi/periodic'
|
|
17
17
|
|
|
18
18
|
self.supported_countries = ['AU']
|
|
@@ -55,6 +55,10 @@ module ActiveMerchant #:nodoc:
|
|
|
55
55
|
post = {}
|
|
56
56
|
add_invoice(post, money, options)
|
|
57
57
|
|
|
58
|
+
# Setting merchantRefNumber to a unique id for each refund
|
|
59
|
+
# This is to support multiple partial refunds for the same order
|
|
60
|
+
post[:merchantRefNum] = SecureRandom.uuid
|
|
61
|
+
|
|
58
62
|
commit(:post, "settlements/#{authorization}/refunds", post)
|
|
59
63
|
end
|
|
60
64
|
|
|
@@ -31,9 +31,11 @@ module ActiveMerchant #:nodoc:
|
|
|
31
31
|
post = {}
|
|
32
32
|
add_invoice(post, amount, options)
|
|
33
33
|
add_payment_method(post, payment_method, options)
|
|
34
|
+
add_stored_credential(post, options)
|
|
34
35
|
add_customer_data(post, options)
|
|
35
36
|
add_vendor_data(post, options)
|
|
36
37
|
add_merchant_defined_fields(post, options)
|
|
38
|
+
add_level3_fields(post, options)
|
|
37
39
|
|
|
38
40
|
commit('sale', post)
|
|
39
41
|
end
|
|
@@ -42,9 +44,11 @@ module ActiveMerchant #:nodoc:
|
|
|
42
44
|
post = {}
|
|
43
45
|
add_invoice(post, amount, options)
|
|
44
46
|
add_payment_method(post, payment_method, options)
|
|
47
|
+
add_stored_credential(post, options)
|
|
45
48
|
add_customer_data(post, options)
|
|
46
49
|
add_vendor_data(post, options)
|
|
47
50
|
add_merchant_defined_fields(post, options)
|
|
51
|
+
add_level3_fields(post, options)
|
|
48
52
|
|
|
49
53
|
commit('auth', post)
|
|
50
54
|
end
|
|
@@ -81,6 +85,7 @@ module ActiveMerchant #:nodoc:
|
|
|
81
85
|
add_payment_method(post, payment_method, options)
|
|
82
86
|
add_customer_data(post, options)
|
|
83
87
|
add_vendor_data(post, options)
|
|
88
|
+
add_level3_fields(post, options)
|
|
84
89
|
|
|
85
90
|
commit('credit', post)
|
|
86
91
|
end
|
|
@@ -91,6 +96,7 @@ module ActiveMerchant #:nodoc:
|
|
|
91
96
|
add_customer_data(post, options)
|
|
92
97
|
add_vendor_data(post, options)
|
|
93
98
|
add_merchant_defined_fields(post, options)
|
|
99
|
+
add_level3_fields(post, options)
|
|
94
100
|
|
|
95
101
|
commit('validate', post)
|
|
96
102
|
end
|
|
@@ -117,7 +123,7 @@ module ActiveMerchant #:nodoc:
|
|
|
117
123
|
|
|
118
124
|
def scrub(transcript)
|
|
119
125
|
transcript.
|
|
120
|
-
gsub(%r((password=)
|
|
126
|
+
gsub(%r((password=)[^&\n]*), '\1[FILTERED]').
|
|
121
127
|
gsub(%r((ccnumber=)\d+), '\1[FILTERED]').
|
|
122
128
|
gsub(%r((cvv=)\d+), '\1[FILTERED]').
|
|
123
129
|
gsub(%r((checkaba=)\d+), '\1[FILTERED]').
|
|
@@ -131,6 +137,10 @@ module ActiveMerchant #:nodoc:
|
|
|
131
137
|
|
|
132
138
|
private
|
|
133
139
|
|
|
140
|
+
def add_level3_fields(post, options)
|
|
141
|
+
add_fields_to_post_if_present(post, options, [:tax, :shipping, :ponumber])
|
|
142
|
+
end
|
|
143
|
+
|
|
134
144
|
def add_invoice(post, money, options)
|
|
135
145
|
post[:amount] = amount(money)
|
|
136
146
|
post[:orderid] = options[:order_id]
|
|
@@ -144,7 +154,8 @@ module ActiveMerchant #:nodoc:
|
|
|
144
154
|
|
|
145
155
|
def add_payment_method(post, payment_method, options)
|
|
146
156
|
if(payment_method.is_a?(String))
|
|
147
|
-
|
|
157
|
+
customer_vault_id, _ = split_authorization(payment_method)
|
|
158
|
+
post[:customer_vault_id] = customer_vault_id
|
|
148
159
|
elsif payment_method.is_a?(NetworkTokenizationCreditCard)
|
|
149
160
|
post[:ccnumber] = payment_method.number
|
|
150
161
|
post[:ccexp] = exp_date(payment_method)
|
|
@@ -169,6 +180,34 @@ module ActiveMerchant #:nodoc:
|
|
|
169
180
|
end
|
|
170
181
|
end
|
|
171
182
|
|
|
183
|
+
def add_stored_credential(post, options)
|
|
184
|
+
return unless (stored_credential = options[:stored_credential])
|
|
185
|
+
|
|
186
|
+
if stored_credential[:initiator] == 'cardholder'
|
|
187
|
+
post[:initiated_by] = 'customer'
|
|
188
|
+
else
|
|
189
|
+
post[:initiated_by] = 'merchant'
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# :reason_type, when provided, overrides anything previously set in
|
|
193
|
+
# post[:billing_method] (see `add_invoice` and the :recurring) option
|
|
194
|
+
case stored_credential[:reason_type]
|
|
195
|
+
when 'recurring'
|
|
196
|
+
post[:billing_method] = 'recurring'
|
|
197
|
+
when 'installment'
|
|
198
|
+
post[:billing_method] = 'installment'
|
|
199
|
+
when 'unscheduled'
|
|
200
|
+
post.delete(:billing_method)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
if stored_credential[:initial_transaction]
|
|
204
|
+
post[:stored_credential_indicator] = 'stored'
|
|
205
|
+
else
|
|
206
|
+
post[:stored_credential_indicator] = 'used'
|
|
207
|
+
post[:initial_transaction_id] = stored_credential[:network_transaction_id]
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
172
211
|
def add_customer_data(post, options)
|
|
173
212
|
post[:email] = options[:email]
|
|
174
213
|
post[:ipaddress] = options[:ip]
|
|
@@ -236,15 +275,16 @@ module ActiveMerchant #:nodoc:
|
|
|
236
275
|
succeeded,
|
|
237
276
|
message_from(succeeded, response),
|
|
238
277
|
response,
|
|
239
|
-
authorization: authorization_from(response, params[:payment]),
|
|
278
|
+
authorization: authorization_from(response, params[:payment], action),
|
|
240
279
|
avs_result: AVSResult.new(code: response[:avsresponse]),
|
|
241
280
|
cvv_result: CVVResult.new(response[:cvvresponse]),
|
|
242
281
|
test: test?
|
|
243
282
|
)
|
|
244
283
|
end
|
|
245
284
|
|
|
246
|
-
def authorization_from(response, payment_type)
|
|
247
|
-
|
|
285
|
+
def authorization_from(response, payment_type, action)
|
|
286
|
+
authorization = (action == 'add_customer' ? response[:customer_vault_id] : response[:transactionid])
|
|
287
|
+
[ authorization, payment_type ].join('#')
|
|
248
288
|
end
|
|
249
289
|
|
|
250
290
|
def split_authorization(authorization)
|
|
@@ -125,6 +125,9 @@ module ActiveMerchant #:nodoc:
|
|
|
125
125
|
|
|
126
126
|
def purchase(money, payment, options={})
|
|
127
127
|
# debit
|
|
128
|
+
if payment.is_a?(String)
|
|
129
|
+
options[:registrationId] = payment
|
|
130
|
+
end
|
|
128
131
|
execute_dbpa(options[:risk_workflow] ? 'PA.CP': 'DB',
|
|
129
132
|
money, payment, options)
|
|
130
133
|
end
|
|
@@ -156,6 +159,10 @@ module ActiveMerchant #:nodoc:
|
|
|
156
159
|
end
|
|
157
160
|
end
|
|
158
161
|
|
|
162
|
+
def store(credit_card, options = {})
|
|
163
|
+
execute_store(credit_card, options.merge(store: true))
|
|
164
|
+
end
|
|
165
|
+
|
|
159
166
|
def supports_scrubbing?
|
|
160
167
|
true
|
|
161
168
|
end
|
|
@@ -169,6 +176,15 @@ module ActiveMerchant #:nodoc:
|
|
|
169
176
|
|
|
170
177
|
private
|
|
171
178
|
|
|
179
|
+
def execute_store(payment, options)
|
|
180
|
+
post = {}
|
|
181
|
+
add_payment_method(post, payment, options)
|
|
182
|
+
add_address(post, options)
|
|
183
|
+
add_options(post, options)
|
|
184
|
+
add_3d_secure(post, options)
|
|
185
|
+
commit(post, nil, options)
|
|
186
|
+
end
|
|
187
|
+
|
|
172
188
|
def execute_dbpa(txtype, money, payment, options)
|
|
173
189
|
post = {}
|
|
174
190
|
post[:paymentType] = txtype
|
|
@@ -243,6 +259,7 @@ module ActiveMerchant #:nodoc:
|
|
|
243
259
|
end
|
|
244
260
|
|
|
245
261
|
def add_payment_method(post, payment, options)
|
|
262
|
+
return if payment.is_a?(String)
|
|
246
263
|
if options[:registrationId]
|
|
247
264
|
post[:card] = {
|
|
248
265
|
cvv: payment.verification_value,
|
|
@@ -278,7 +295,9 @@ module ActiveMerchant #:nodoc:
|
|
|
278
295
|
end
|
|
279
296
|
|
|
280
297
|
def build_url(url, authorization, options)
|
|
281
|
-
if options[:
|
|
298
|
+
if options[:store]
|
|
299
|
+
url.gsub(/payments/, 'registrations')
|
|
300
|
+
elsif options[:registrationId]
|
|
282
301
|
"#{url.gsub(/payments/, 'registrations')}/#{options[:registrationId]}/payments"
|
|
283
302
|
elsif authorization
|
|
284
303
|
"#{url}/#{authorization}"
|
|
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
|
|
|
30
30
|
class OrbitalGateway < Gateway
|
|
31
31
|
include Empty
|
|
32
32
|
|
|
33
|
-
API_VERSION = '7.
|
|
33
|
+
API_VERSION = '7.7'
|
|
34
34
|
|
|
35
35
|
POST_HEADERS = {
|
|
36
36
|
'MIME-Version' => '1.1',
|
|
@@ -465,16 +465,62 @@ module ActiveMerchant #:nodoc:
|
|
|
465
465
|
end
|
|
466
466
|
end
|
|
467
467
|
|
|
468
|
-
def
|
|
469
|
-
|
|
470
|
-
|
|
468
|
+
def add_eci(xml, creditcard, three_d_secure)
|
|
469
|
+
eci = if three_d_secure
|
|
470
|
+
three_d_secure[:eci]
|
|
471
|
+
elsif creditcard.is_a?(NetworkTokenizationCreditCard)
|
|
472
|
+
creditcard.eci
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
xml.tag!(:AuthenticationECIInd, eci) if eci
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def add_xid(xml, creditcard, three_d_secure)
|
|
479
|
+
xid = if three_d_secure && creditcard.brand == 'visa'
|
|
480
|
+
three_d_secure[:xid]
|
|
481
|
+
elsif creditcard.is_a?(NetworkTokenizationCreditCard)
|
|
482
|
+
creditcard.transaction_id
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
xml.tag!(:XID, xid) if xid
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def add_cavv(xml, creditcard, three_d_secure)
|
|
489
|
+
return unless three_d_secure && creditcard.brand == 'visa'
|
|
490
|
+
|
|
491
|
+
xml.tag!(:CAVV, three_d_secure[:cavv])
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
def add_aav(xml, creditcard, three_d_secure)
|
|
495
|
+
return unless three_d_secure && creditcard.brand == 'master'
|
|
496
|
+
|
|
497
|
+
xml.tag!(:AAV, three_d_secure[:cavv])
|
|
471
498
|
end
|
|
472
499
|
|
|
473
|
-
def
|
|
500
|
+
def add_dpanind(xml, creditcard)
|
|
501
|
+
return unless creditcard.is_a?(NetworkTokenizationCreditCard)
|
|
502
|
+
|
|
474
503
|
xml.tag! :DPANInd, 'Y'
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def add_digital_token_cryptogram(xml, creditcard)
|
|
507
|
+
return unless creditcard.is_a?(NetworkTokenizationCreditCard)
|
|
508
|
+
|
|
475
509
|
xml.tag! :DigitalTokenCryptogram, creditcard.payment_cryptogram
|
|
476
510
|
end
|
|
477
511
|
|
|
512
|
+
def add_aevv(xml, creditcard, three_d_secure)
|
|
513
|
+
return unless three_d_secure && creditcard.brand == 'american_express'
|
|
514
|
+
|
|
515
|
+
xml.tag!(:AEVV, three_d_secure[:cavv])
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
def add_pymt_brand_program_code(xml, creditcard, three_d_secure)
|
|
519
|
+
return unless three_d_secure && creditcard.brand == 'american_express'
|
|
520
|
+
|
|
521
|
+
xml.tag!(:PymtBrandProgramCode, 'ASK')
|
|
522
|
+
end
|
|
523
|
+
|
|
478
524
|
def add_refund(xml, currency=nil)
|
|
479
525
|
xml.tag! :AccountNum, nil
|
|
480
526
|
|
|
@@ -506,6 +552,36 @@ module ActiveMerchant #:nodoc:
|
|
|
506
552
|
end
|
|
507
553
|
end
|
|
508
554
|
|
|
555
|
+
def add_stored_credentials(xml, parameters)
|
|
556
|
+
return unless parameters[:mit_stored_credential_ind] == 'Y' || parameters[:stored_credential] && !parameters[:stored_credential].values.all?(&:nil?)
|
|
557
|
+
if msg_type = get_msg_type(parameters)
|
|
558
|
+
xml.tag! :MITMsgType, msg_type
|
|
559
|
+
end
|
|
560
|
+
xml.tag! :MITStoredCredentialInd, 'Y'
|
|
561
|
+
if parameters[:mit_submitted_transaction_id]
|
|
562
|
+
xml.tag! :MITSubmittedTransactionID, parameters[:mit_submitted_transaction_id]
|
|
563
|
+
elsif parameters.dig(:stored_credential, :network_transaction_id) && parameters.dig(:stored_credential, :initiator) == 'merchant'
|
|
564
|
+
xml.tag! :MITSubmittedTransactionID, parameters[:stored_credential][:network_transaction_id]
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def get_msg_type(parameters)
|
|
569
|
+
return parameters[:mit_msg_type] if parameters[:mit_msg_type]
|
|
570
|
+
return 'CSTO' if parameters[:stored_credential][:initial_transaction]
|
|
571
|
+
return unless parameters[:stored_credential][:initiator] && parameters[:stored_credential][:reason_type]
|
|
572
|
+
initiator = case parameters[:stored_credential][:initiator]
|
|
573
|
+
when 'customer' then 'C'
|
|
574
|
+
when 'merchant' then 'M'
|
|
575
|
+
end
|
|
576
|
+
reason = case parameters[:stored_credential][:reason_type]
|
|
577
|
+
when 'recurring' then 'REC'
|
|
578
|
+
when 'installment' then 'INS'
|
|
579
|
+
when 'unscheduled' then 'USE'
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
"#{initiator}#{reason}"
|
|
583
|
+
end
|
|
584
|
+
|
|
509
585
|
def parse(body)
|
|
510
586
|
response = {}
|
|
511
587
|
xml = REXML::Document.new(body)
|
|
@@ -603,9 +679,11 @@ module ActiveMerchant #:nodoc:
|
|
|
603
679
|
|
|
604
680
|
yield xml if block_given?
|
|
605
681
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
682
|
+
three_d_secure = parameters[:three_d_secure]
|
|
683
|
+
|
|
684
|
+
add_eci(xml, creditcard, three_d_secure)
|
|
685
|
+
add_cavv(xml, creditcard, three_d_secure)
|
|
686
|
+
add_xid(xml, creditcard, three_d_secure)
|
|
609
687
|
|
|
610
688
|
xml.tag! :OrderID, format_order_id(parameters[:order_id])
|
|
611
689
|
xml.tag! :Amount, amount(money)
|
|
@@ -614,11 +692,12 @@ module ActiveMerchant #:nodoc:
|
|
|
614
692
|
add_level_2_tax(xml, parameters)
|
|
615
693
|
add_level_2_advice_addendum(xml, parameters)
|
|
616
694
|
|
|
695
|
+
add_aav(xml, creditcard, three_d_secure)
|
|
617
696
|
# CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
|
|
618
697
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
698
|
+
add_dpanind(xml, creditcard)
|
|
699
|
+
add_aevv(xml, creditcard, three_d_secure)
|
|
700
|
+
add_digital_token_cryptogram(xml, creditcard)
|
|
622
701
|
|
|
623
702
|
if parameters[:soft_descriptors].is_a?(OrbitalSoftDescriptors)
|
|
624
703
|
add_soft_descriptors(xml, parameters[:soft_descriptors])
|
|
@@ -635,6 +714,8 @@ module ActiveMerchant #:nodoc:
|
|
|
635
714
|
end
|
|
636
715
|
|
|
637
716
|
add_level_2_purchase(xml, parameters)
|
|
717
|
+
add_stored_credentials(xml, parameters)
|
|
718
|
+
add_pymt_brand_program_code(xml, creditcard, three_d_secure)
|
|
638
719
|
end
|
|
639
720
|
end
|
|
640
721
|
xml.target!
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
1
2
|
require 'active_merchant/billing/gateways/payflow/payflow_common_api'
|
|
2
3
|
require 'active_merchant/billing/gateways/payflow/payflow_response'
|
|
3
4
|
require 'active_merchant/billing/gateways/payflow_express'
|
|
@@ -187,7 +188,44 @@ module ActiveMerchant #:nodoc:
|
|
|
187
188
|
end
|
|
188
189
|
end
|
|
189
190
|
end
|
|
190
|
-
xml.target
|
|
191
|
+
add_level_two_three_fields(xml.target!, options)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def add_level_two_three_fields(xml_string, options)
|
|
195
|
+
if options[:level_two_fields] || options[:level_three_fields]
|
|
196
|
+
xml_doc = Nokogiri::XML.parse(xml_string)
|
|
197
|
+
%i[level_two_fields level_three_fields].each do |fields|
|
|
198
|
+
xml_string = add_fields(xml_doc, options[fields]) if options[fields]
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
xml_string
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def check_fields(parent, fields, xml_doc)
|
|
205
|
+
fields.each do |k, v|
|
|
206
|
+
if v.is_a? String
|
|
207
|
+
new_node = Nokogiri::XML::Node.new(k, xml_doc)
|
|
208
|
+
new_node.add_child(v)
|
|
209
|
+
xml_doc.at_css(parent).add_child(new_node)
|
|
210
|
+
else
|
|
211
|
+
check_subparent_before_continuing(parent, k, xml_doc)
|
|
212
|
+
check_fields(k, v, xml_doc)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
xml_doc
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def check_subparent_before_continuing(parent, subparent, xml_doc)
|
|
219
|
+
unless xml_doc.at_css(subparent)
|
|
220
|
+
subparent_node = Nokogiri::XML::Node.new(subparent, xml_doc)
|
|
221
|
+
xml_doc.at_css(parent).add_child(subparent_node)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def add_fields(xml_doc, options_fields)
|
|
226
|
+
fields_to_add = JSON.parse(options_fields)
|
|
227
|
+
check_fields('Invoice', fields_to_add, xml_doc)
|
|
228
|
+
xml_doc.root.to_s
|
|
191
229
|
end
|
|
192
230
|
|
|
193
231
|
def build_check_request(action, money, check, options)
|
|
@@ -213,7 +251,7 @@ module ActiveMerchant #:nodoc:
|
|
|
213
251
|
end
|
|
214
252
|
end
|
|
215
253
|
end
|
|
216
|
-
xml.target
|
|
254
|
+
add_level_two_three_fields(xml.target!, options)
|
|
217
255
|
end
|
|
218
256
|
|
|
219
257
|
def add_credit_card(xml, credit_card, options = {})
|
|
@@ -224,23 +262,35 @@ module ActiveMerchant #:nodoc:
|
|
|
224
262
|
xml.tag! 'NameOnCard', credit_card.first_name
|
|
225
263
|
xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value?
|
|
226
264
|
|
|
227
|
-
|
|
228
|
-
three_d_secure = options[:three_d_secure]
|
|
229
|
-
xml.tag! 'BuyerAuthResult' do
|
|
230
|
-
xml.tag! 'Status', three_d_secure[:status] unless three_d_secure[:status].blank?
|
|
231
|
-
xml.tag! 'AuthenticationId', three_d_secure[:authentication_id] unless three_d_secure[:authentication_id].blank?
|
|
232
|
-
xml.tag! 'PAReq', three_d_secure[:pareq] unless three_d_secure[:pareq].blank?
|
|
233
|
-
xml.tag! 'ACSUrl', three_d_secure[:acs_url] unless three_d_secure[:acs_url].blank?
|
|
234
|
-
xml.tag! 'ECI', three_d_secure[:eci] unless three_d_secure[:eci].blank?
|
|
235
|
-
xml.tag! 'CAVV', three_d_secure[:cavv] unless three_d_secure[:cavv].blank?
|
|
236
|
-
xml.tag! 'XID', three_d_secure[:xid] unless three_d_secure[:xid].blank?
|
|
237
|
-
end
|
|
238
|
-
end
|
|
265
|
+
add_three_d_secure(options, xml)
|
|
239
266
|
|
|
240
267
|
xml.tag! 'ExtData', 'Name' => 'LASTNAME', 'Value' => credit_card.last_name
|
|
241
268
|
end
|
|
242
269
|
end
|
|
243
270
|
|
|
271
|
+
def add_three_d_secure(options, xml)
|
|
272
|
+
if options[:three_d_secure]
|
|
273
|
+
three_d_secure = options[:three_d_secure]
|
|
274
|
+
xml.tag! 'BuyerAuthResult' do
|
|
275
|
+
authentication_status(three_d_secure, xml)
|
|
276
|
+
xml.tag! 'AuthenticationId', three_d_secure[:authentication_id] unless three_d_secure[:authentication_id].blank?
|
|
277
|
+
xml.tag! 'PAReq', three_d_secure[:pareq] unless three_d_secure[:pareq].blank?
|
|
278
|
+
xml.tag! 'ACSUrl', three_d_secure[:acs_url] unless three_d_secure[:acs_url].blank?
|
|
279
|
+
xml.tag! 'ECI', three_d_secure[:eci] unless three_d_secure[:eci].blank?
|
|
280
|
+
xml.tag! 'CAVV', three_d_secure[:cavv] unless three_d_secure[:cavv].blank?
|
|
281
|
+
xml.tag! 'XID', three_d_secure[:xid] unless three_d_secure[:xid].blank?
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def authentication_status(three_d_secure, xml)
|
|
287
|
+
if three_d_secure[:authentication_response_status].present?
|
|
288
|
+
xml.tag! 'Status', three_d_secure[:authentication_response_status]
|
|
289
|
+
elsif three_d_secure[:directory_response_status].present?
|
|
290
|
+
xml.tag! 'Status', three_d_secure[:directory_response_status]
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
244
294
|
def credit_card_type(credit_card)
|
|
245
295
|
return '' if card_brand(credit_card).blank?
|
|
246
296
|
|
|
@@ -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:
|