activemerchant 1.126.0 → 1.129.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 +241 -0
- data/lib/active_merchant/billing/check.rb +40 -8
- data/lib/active_merchant/billing/credit_card.rb +28 -1
- data/lib/active_merchant/billing/credit_card_methods.rb +79 -23
- data/lib/active_merchant/billing/gateways/adyen.rb +67 -8
- data/lib/active_merchant/billing/gateways/airwallex.rb +40 -11
- data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -4
- data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -1
- data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +56 -16
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +64 -17
- data/lib/active_merchant/billing/gateways/card_connect.rb +27 -9
- data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +228 -57
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
- data/lib/active_merchant/billing/gateways/credorax.rb +47 -27
- data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +100 -26
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
- data/lib/active_merchant/billing/gateways/d_local.rb +44 -5
- data/lib/active_merchant/billing/gateways/decidir.rb +15 -4
- data/lib/active_merchant/billing/gateways/ebanx.rb +36 -24
- data/lib/active_merchant/billing/gateways/element.rb +21 -1
- data/lib/active_merchant/billing/gateways/global_collect.rb +73 -22
- data/lib/active_merchant/billing/gateways/ipg.rb +13 -8
- data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
- data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
- data/lib/active_merchant/billing/gateways/litle.rb +25 -5
- data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
- data/lib/active_merchant/billing/gateways/monei.rb +2 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +20 -5
- data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
- data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
- data/lib/active_merchant/billing/gateways/orbital.rb +43 -22
- data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
- data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
- data/lib/active_merchant/billing/gateways/paymentez.rb +18 -6
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +22 -14
- data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -0
- data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
- data/lib/active_merchant/billing/gateways/priority.rb +29 -6
- data/lib/active_merchant/billing/gateways/rapyd.rb +110 -49
- data/lib/active_merchant/billing/gateways/reach.rb +277 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +9 -5
- data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
- data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
- data/lib/active_merchant/billing/gateways/simetrik.rb +28 -22
- data/lib/active_merchant/billing/gateways/stripe.rb +21 -1
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +62 -22
- data/lib/active_merchant/billing/gateways/tns.rb +2 -5
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
- data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +1 -1
- data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
- data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
- data/lib/active_merchant/billing/gateways/worldpay.rb +117 -9
- data/lib/active_merchant/billing/response.rb +15 -1
- data/lib/active_merchant/connection.rb +0 -2
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/errors.rb +4 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +24 -3
@@ -0,0 +1,361 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class CommerceHubGateway < Gateway
|
4
|
+
self.test_url = 'https://cert.api.fiservapps.com/ch'
|
5
|
+
self.live_url = 'https://prod.api.fiservapps.com/ch'
|
6
|
+
|
7
|
+
self.supported_countries = ['US']
|
8
|
+
self.default_currency = 'USD'
|
9
|
+
self.supported_cardtypes = %i[visa master american_express discover]
|
10
|
+
|
11
|
+
self.homepage_url = 'https://developer.fiserv.com/product/CommerceHub'
|
12
|
+
self.display_name = 'CommerceHub'
|
13
|
+
|
14
|
+
STANDARD_ERROR_CODE_MAPPING = {}
|
15
|
+
|
16
|
+
SCHEDULED_REASON_TYPES = %w(recurring installment)
|
17
|
+
ENDPOINTS = {
|
18
|
+
'sale' => '/payments/v1/charges',
|
19
|
+
'void' => '/payments/v1/cancels',
|
20
|
+
'refund' => '/payments/v1/refunds',
|
21
|
+
'vault' => '/payments-vas/v1/tokens',
|
22
|
+
'verify' => '/payments-vas/v1/accounts/verification'
|
23
|
+
}
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
requires!(options, :api_key, :api_secret, :merchant_id, :terminal_id)
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def purchase(money, payment, options = {})
|
31
|
+
post = {}
|
32
|
+
options[:capture_flag] = true
|
33
|
+
options[:create_token] = false
|
34
|
+
|
35
|
+
add_transaction_details(post, options, 'sale')
|
36
|
+
build_purchase_and_auth_request(post, money, payment, options)
|
37
|
+
|
38
|
+
commit('sale', post, options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def authorize(money, payment, options = {})
|
42
|
+
post = {}
|
43
|
+
options[:capture_flag] = false
|
44
|
+
options[:create_token] = false
|
45
|
+
|
46
|
+
add_transaction_details(post, options, 'sale')
|
47
|
+
build_purchase_and_auth_request(post, money, payment, options)
|
48
|
+
|
49
|
+
commit('sale', post, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def capture(money, authorization, options = {})
|
53
|
+
post = {}
|
54
|
+
options[:capture_flag] = true
|
55
|
+
add_invoice(post, money, options)
|
56
|
+
add_transaction_details(post, options, 'capture')
|
57
|
+
add_reference_transaction_details(post, authorization, options, :capture)
|
58
|
+
|
59
|
+
commit('sale', post, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def refund(money, authorization, options = {})
|
63
|
+
post = {}
|
64
|
+
add_invoice(post, money, options) if money
|
65
|
+
add_transaction_details(post, options)
|
66
|
+
add_reference_transaction_details(post, authorization, options, :refund)
|
67
|
+
|
68
|
+
commit('refund', post, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def void(authorization, options = {})
|
72
|
+
post = {}
|
73
|
+
add_transaction_details(post, options)
|
74
|
+
add_reference_transaction_details(post, authorization, options, :void)
|
75
|
+
|
76
|
+
commit('void', post, options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def store(credit_card, options = {})
|
80
|
+
post = {}
|
81
|
+
add_payment(post, credit_card, options)
|
82
|
+
add_billing_address(post, credit_card, options)
|
83
|
+
add_transaction_details(post, options)
|
84
|
+
add_transaction_interaction(post, options)
|
85
|
+
|
86
|
+
commit('vault', post, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def verify(credit_card, options = {})
|
90
|
+
post = {}
|
91
|
+
add_payment(post, credit_card, options)
|
92
|
+
add_billing_address(post, credit_card, options)
|
93
|
+
|
94
|
+
commit('verify', post, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
def supports_scrubbing?
|
98
|
+
true
|
99
|
+
end
|
100
|
+
|
101
|
+
def scrub(transcript)
|
102
|
+
transcript.
|
103
|
+
gsub(%r((Authorization: )[a-zA-Z0-9+./=]+), '\1[FILTERED]').
|
104
|
+
gsub(%r((Api-Key: )\w+), '\1[FILTERED]').
|
105
|
+
gsub(%r(("cardData\\?":\\?")\d+), '\1[FILTERED]').
|
106
|
+
gsub(%r(("securityCode\\?":\\?")\d+), '\1[FILTERED]').
|
107
|
+
gsub(%r(("cavv\\?":\\?")\w+), '\1[FILTERED]')
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def add_transaction_interaction(post, options)
|
113
|
+
post[:transactionInteraction] = {}
|
114
|
+
post[:transactionInteraction][:origin] = options[:origin] || 'ECOM'
|
115
|
+
post[:transactionInteraction][:eciIndicator] = options[:eci_indicator] || 'CHANNEL_ENCRYPTED'
|
116
|
+
post[:transactionInteraction][:posConditionCode] = options[:pos_condition_code] || 'CARD_NOT_PRESENT_ECOM'
|
117
|
+
post[:transactionInteraction][:posEntryMode] = options[:pos_entry_mode] || 'MANUAL'
|
118
|
+
post[:transactionInteraction][:additionalPosInformation] = {}
|
119
|
+
post[:transactionInteraction][:additionalPosInformation][:dataEntrySource] = options[:data_entry_source] || 'UNSPECIFIED'
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_transaction_details(post, options, action = nil)
|
123
|
+
details = { captureFlag: options[:capture_flag], createToken: options[:create_token] }
|
124
|
+
|
125
|
+
if options[:order_id].present? && action == 'sale'
|
126
|
+
details[:merchantOrderId] = options[:order_id]
|
127
|
+
details[:merchantTransactionId] = options[:order_id]
|
128
|
+
end
|
129
|
+
|
130
|
+
if action != 'capture'
|
131
|
+
details[:merchantInvoiceNumber] = options[:merchant_invoice_number] || rand.to_s[2..13]
|
132
|
+
details[:primaryTransactionType] = options[:primary_transaction_type]
|
133
|
+
details[:accountVerification] = options[:account_verification]
|
134
|
+
end
|
135
|
+
|
136
|
+
post[:transactionDetails] = details.compact
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_billing_address(post, payment, options)
|
140
|
+
return unless billing = options[:billing_address]
|
141
|
+
|
142
|
+
billing_address = {}
|
143
|
+
if payment.is_a?(CreditCard)
|
144
|
+
billing_address[:firstName] = payment.first_name if payment.first_name
|
145
|
+
billing_address[:lastName] = payment.last_name if payment.last_name
|
146
|
+
end
|
147
|
+
address = {}
|
148
|
+
address[:street] = billing[:address1] if billing[:address1]
|
149
|
+
address[:houseNumberOrName] = billing[:address2] if billing[:address2]
|
150
|
+
address[:recipientNameOrAddress] = billing[:name] if billing[:name]
|
151
|
+
address[:city] = billing[:city] if billing[:city]
|
152
|
+
address[:stateOrProvince] = billing[:state] if billing[:state]
|
153
|
+
address[:postalCode] = billing[:zip] if billing[:zip]
|
154
|
+
address[:country] = billing[:country] if billing[:country]
|
155
|
+
|
156
|
+
billing_address[:address] = address unless address.empty?
|
157
|
+
if billing[:phone_number]
|
158
|
+
billing_address[:phone] = {}
|
159
|
+
billing_address[:phone][:phoneNumber] = billing[:phone_number]
|
160
|
+
end
|
161
|
+
post[:billingAddress] = billing_address
|
162
|
+
end
|
163
|
+
|
164
|
+
def add_shipping_address(post, options)
|
165
|
+
return unless shipping = options[:shipping_address]
|
166
|
+
|
167
|
+
shipping_address = {}
|
168
|
+
address = {}
|
169
|
+
address[:street] = shipping[:address1] if shipping[:address1]
|
170
|
+
address[:houseNumberOrName] = shipping[:address2] if shipping[:address2]
|
171
|
+
address[:recipientNameOrAddress] = shipping[:name] if shipping[:name]
|
172
|
+
address[:city] = shipping[:city] if shipping[:city]
|
173
|
+
address[:stateOrProvince] = shipping[:state] if shipping[:state]
|
174
|
+
address[:postalCode] = shipping[:zip] if shipping[:zip]
|
175
|
+
address[:country] = shipping[:country] if shipping[:country]
|
176
|
+
|
177
|
+
shipping_address[:address] = address unless address.empty?
|
178
|
+
if shipping[:phone_number]
|
179
|
+
shipping_address[:phone] = {}
|
180
|
+
shipping_address[:phone][:phoneNumber] = shipping[:phone_number]
|
181
|
+
end
|
182
|
+
post[:shippingAddress] = shipping_address
|
183
|
+
end
|
184
|
+
|
185
|
+
def build_purchase_and_auth_request(post, money, payment, options)
|
186
|
+
add_invoice(post, money, options)
|
187
|
+
add_payment(post, payment, options)
|
188
|
+
add_stored_credentials(post, options)
|
189
|
+
add_transaction_interaction(post, options)
|
190
|
+
add_billing_address(post, payment, options)
|
191
|
+
add_shipping_address(post, options)
|
192
|
+
end
|
193
|
+
|
194
|
+
def add_reference_transaction_details(post, authorization, options, action = nil)
|
195
|
+
reference_details = {}
|
196
|
+
_merchant_reference, transaction_id = authorization.include?('|') ? authorization.split('|') : [nil, authorization]
|
197
|
+
|
198
|
+
reference_details[:referenceTransactionId] = transaction_id
|
199
|
+
reference_details[:referenceTransactionType] = (options[:reference_transaction_type] || 'CHARGES') unless action == :capture
|
200
|
+
post[:referenceTransactionDetails] = reference_details.compact
|
201
|
+
end
|
202
|
+
|
203
|
+
def add_invoice(post, money, options)
|
204
|
+
post[:amount] = {
|
205
|
+
total: amount(money).to_f,
|
206
|
+
currency: options[:currency] || self.default_currency
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
def add_stored_credentials(post, options)
|
211
|
+
return unless stored_credential = options[:stored_credential]
|
212
|
+
|
213
|
+
post[:storedCredentials] = {}
|
214
|
+
post[:storedCredentials][:sequence] = stored_credential[:initial_transaction] ? 'FIRST' : 'SUBSEQUENT'
|
215
|
+
post[:storedCredentials][:initiator] = stored_credential[:initiator] == 'merchant' ? 'MERCHANT' : 'CARD_HOLDER'
|
216
|
+
post[:storedCredentials][:scheduled] = SCHEDULED_REASON_TYPES.include?(stored_credential[:reason_type])
|
217
|
+
post[:storedCredentials][:schemeReferenceTransactionId] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_credit_card(source, payment, options)
|
221
|
+
source[:sourceType] = 'PaymentCard'
|
222
|
+
source[:card] = {}
|
223
|
+
source[:card][:cardData] = payment.number
|
224
|
+
source[:card][:expirationMonth] = format(payment.month, :two_digits) if payment.month
|
225
|
+
source[:card][:expirationYear] = format(payment.year, :four_digits) if payment.year
|
226
|
+
if payment.verification_value
|
227
|
+
source[:card][:securityCode] = payment.verification_value
|
228
|
+
source[:card][:securityCodeIndicator] = 'PROVIDED'
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def add_payment_token(source, payment, options)
|
233
|
+
source[:sourceType] = 'PaymentToken'
|
234
|
+
source[:tokenData] = payment
|
235
|
+
source[:tokenSource] = options[:token_source] if options[:token_source]
|
236
|
+
if options[:card_expiration_month] || options[:card_expiration_year]
|
237
|
+
source[:card] = {}
|
238
|
+
source[:card][:expirationMonth] = options[:card_expiration_month] if options[:card_expiration_month]
|
239
|
+
source[:card][:expirationYear] = options[:card_expiration_year] if options[:card_expiration_year]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def add_decrypted_wallet(source, payment, options)
|
244
|
+
source[:sourceType] = 'DecryptedWallet'
|
245
|
+
source[:card] = {}
|
246
|
+
source[:card][:cardData] = payment.number
|
247
|
+
source[:card][:expirationMonth] = format(payment.month, :two_digits)
|
248
|
+
source[:card][:expirationYear] = format(payment.year, :four_digits)
|
249
|
+
source[:cavv] = payment.payment_cryptogram
|
250
|
+
source[:walletType] = payment.source.to_s.upcase
|
251
|
+
end
|
252
|
+
|
253
|
+
def add_payment(post, payment, options = {})
|
254
|
+
source = {}
|
255
|
+
case payment
|
256
|
+
when NetworkTokenizationCreditCard
|
257
|
+
add_decrypted_wallet(source, payment, options)
|
258
|
+
when CreditCard
|
259
|
+
add_credit_card(source, payment, options)
|
260
|
+
when String
|
261
|
+
add_payment_token(source, payment, options)
|
262
|
+
end
|
263
|
+
post[:source] = source
|
264
|
+
end
|
265
|
+
|
266
|
+
def parse(body)
|
267
|
+
JSON.parse(body)
|
268
|
+
end
|
269
|
+
|
270
|
+
def headers(request, options)
|
271
|
+
time = DateTime.now.strftime('%Q').to_s
|
272
|
+
client_request_id = options[:client_request_id] || rand.to_s[2..8]
|
273
|
+
raw_signature = @options[:api_key] + client_request_id.to_s + time + request
|
274
|
+
hmac = OpenSSL::HMAC.digest('sha256', @options[:api_secret], raw_signature)
|
275
|
+
signature = Base64.strict_encode64(hmac.to_s).to_s
|
276
|
+
|
277
|
+
{
|
278
|
+
'Client-Request-Id' => client_request_id,
|
279
|
+
'Api-Key' => @options[:api_key],
|
280
|
+
'Timestamp' => time,
|
281
|
+
'Accept-Language' => 'application/json',
|
282
|
+
'Auth-Token-Type' => 'HMAC',
|
283
|
+
'Content-Type' => 'application/json',
|
284
|
+
'Accept' => 'application/json',
|
285
|
+
'Authorization' => signature
|
286
|
+
}
|
287
|
+
end
|
288
|
+
|
289
|
+
def add_merchant_details(post)
|
290
|
+
post[:merchantDetails] = {}
|
291
|
+
post[:merchantDetails][:terminalId] = @options[:terminal_id]
|
292
|
+
post[:merchantDetails][:merchantId] = @options[:merchant_id]
|
293
|
+
end
|
294
|
+
|
295
|
+
def commit(action, parameters, options)
|
296
|
+
url = (test? ? test_url : live_url) + ENDPOINTS[action]
|
297
|
+
add_merchant_details(parameters)
|
298
|
+
response = parse(ssl_post(url, parameters.to_json, headers(parameters.to_json, options)))
|
299
|
+
|
300
|
+
Response.new(
|
301
|
+
success_from(response, action),
|
302
|
+
message_from(response, action),
|
303
|
+
response,
|
304
|
+
authorization: authorization_from(action, response, options),
|
305
|
+
test: test?,
|
306
|
+
error_code: error_code_from(response, action),
|
307
|
+
avs_result: AVSResult.new(code: get_avs_cvv(response, 'avs')),
|
308
|
+
cvv_result: CVVResult.new(get_avs_cvv(response, 'cvv'))
|
309
|
+
)
|
310
|
+
end
|
311
|
+
|
312
|
+
def get_avs_cvv(response, type = 'avs')
|
313
|
+
response.dig(
|
314
|
+
'paymentReceipt',
|
315
|
+
'processorResponseDetails',
|
316
|
+
'bankAssociationDetails',
|
317
|
+
'avsSecurityCodeResponse',
|
318
|
+
'association',
|
319
|
+
type == 'avs' ? 'avsCode' : 'securityCodeResponse'
|
320
|
+
)
|
321
|
+
end
|
322
|
+
|
323
|
+
def handle_response(response)
|
324
|
+
case response.code.to_i
|
325
|
+
when 200...300, 400, 401, 429
|
326
|
+
response.body
|
327
|
+
else
|
328
|
+
raise ResponseError.new(response)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def success_from(response, action = nil)
|
333
|
+
return message_from(response, action) == 'VERIFIED' if action == 'verify'
|
334
|
+
|
335
|
+
(response.dig('paymentReceipt', 'processorResponseDetails', 'responseCode') || response.dig('paymentTokens', 0, 'tokenResponseCode')) == '000'
|
336
|
+
end
|
337
|
+
|
338
|
+
def message_from(response, action = nil)
|
339
|
+
return response.dig('error', 0, 'message') if response['error'].present?
|
340
|
+
return response.dig('gatewayResponse', 'transactionState') if action == 'verify'
|
341
|
+
|
342
|
+
response.dig('paymentReceipt', 'processorResponseDetails', 'responseMessage') || response.dig('gatewayResponse', 'transactionType')
|
343
|
+
end
|
344
|
+
|
345
|
+
def authorization_from(action, response, options)
|
346
|
+
case action
|
347
|
+
when 'vault'
|
348
|
+
response.dig('paymentTokens', 0, 'tokenData')
|
349
|
+
when 'sale'
|
350
|
+
[options[:order_id] || '', response.dig('gatewayResponse', 'transactionProcessingDetails', 'transactionId')].join('|')
|
351
|
+
else
|
352
|
+
response.dig('gatewayResponse', 'transactionProcessingDetails', 'transactionId')
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def error_code_from(response, action)
|
357
|
+
response.dig('error', 0, 'code') unless success_from(response, action)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
class_attribute :test_url, :live_na_url, :live_eu_url
|
5
5
|
|
6
6
|
self.display_name = 'Credorax Gateway'
|
7
|
-
self.homepage_url = 'https://www.
|
7
|
+
self.homepage_url = 'https://www.finaro.com/'
|
8
8
|
|
9
9
|
# NOTE: the IP address you run the remote tests from will need to be
|
10
10
|
# whitelisted by Credorax; contact support@credorax.com as necessary to
|
@@ -26,7 +26,13 @@ module ActiveMerchant #:nodoc:
|
|
26
26
|
self.currencies_with_three_decimal_places = %w(BHD IQD JOD KWD LYD OMR TND)
|
27
27
|
|
28
28
|
self.money_format = :cents
|
29
|
-
self.supported_cardtypes = %i[visa master maestro american_express]
|
29
|
+
self.supported_cardtypes = %i[visa master maestro american_express jcb discover diners_club]
|
30
|
+
|
31
|
+
NETWORK_TOKENIZATION_CARD_SOURCE = {
|
32
|
+
'apple_pay' => 'applepay',
|
33
|
+
'google_pay' => 'googlepay',
|
34
|
+
'network_token' => 'vts_mdes_token'
|
35
|
+
}
|
30
36
|
|
31
37
|
RESPONSE_MESSAGES = {
|
32
38
|
'00' => 'Approved or completed successfully',
|
@@ -63,26 +69,27 @@ module ActiveMerchant #:nodoc:
|
|
63
69
|
'31' => 'Issuer signed-off',
|
64
70
|
'32' => 'Completed partially',
|
65
71
|
'33' => 'Pick-up, expired card',
|
66
|
-
'34' => '
|
72
|
+
'34' => 'Implausible card data',
|
67
73
|
'35' => 'Pick-up, card acceptor contact acquirer',
|
68
74
|
'36' => 'Pick up, card restricted',
|
69
75
|
'37' => 'Pick up, call acquirer security',
|
70
76
|
'38' => 'Pick up, Allowable PIN tries exceeded',
|
71
|
-
'39' => '
|
77
|
+
'39' => 'No credit account',
|
72
78
|
'40' => 'Requested function not supported',
|
73
79
|
'41' => 'Lost Card, Pickup',
|
74
80
|
'42' => 'No universal account',
|
75
81
|
'43' => 'Pick up, stolen card',
|
76
82
|
'44' => 'No investment account',
|
83
|
+
'46' => 'Closed account',
|
77
84
|
'50' => 'Do not renew',
|
78
|
-
'51' => '
|
85
|
+
'51' => 'Insufficient funds',
|
79
86
|
'52' => 'No checking Account',
|
80
87
|
'53' => 'No savings account',
|
81
88
|
'54' => 'Expired card',
|
82
|
-
'55' => '
|
89
|
+
'55' => 'Incorrect PIN',
|
83
90
|
'56' => 'No card record',
|
84
91
|
'57' => 'Transaction not allowed for cardholder',
|
85
|
-
'58' => 'Transaction not
|
92
|
+
'58' => 'Transaction not permitted to terminal',
|
86
93
|
'59' => 'Suspected Fraud',
|
87
94
|
'60' => 'Card acceptor contact acquirer',
|
88
95
|
'61' => 'Exceeds withdrawal amount limit',
|
@@ -93,22 +100,22 @@ module ActiveMerchant #:nodoc:
|
|
93
100
|
'66' => 'Call acquirers security department',
|
94
101
|
'67' => 'Card to be picked up at ATM',
|
95
102
|
'68' => 'Response received too late.',
|
96
|
-
'70' => '
|
103
|
+
'70' => 'PIN data required',
|
97
104
|
'71' => 'Decline PIN not changed',
|
98
105
|
'75' => 'Pin tries exceeded',
|
99
106
|
'76' => 'Wrong PIN, number of PIN tries exceeded',
|
100
107
|
'77' => 'Wrong Reference No.',
|
101
|
-
'78' => 'Record
|
102
|
-
'79' => '
|
108
|
+
'78' => 'Blocked, first used/ Record not found',
|
109
|
+
'79' => 'Declined due to lifecycle event',
|
103
110
|
'80' => 'Network error',
|
104
|
-
'81' => '
|
105
|
-
'82' => '
|
111
|
+
'81' => 'PIN cryptographic error',
|
112
|
+
'82' => 'Bad CVV/ Declined due to policy event',
|
106
113
|
'83' => 'Transaction failed',
|
107
114
|
'84' => 'Pre-authorization timed out',
|
108
115
|
'85' => 'No reason to decline',
|
109
116
|
'86' => 'Cannot verify pin',
|
110
117
|
'87' => 'Purchase amount only, no cashback allowed',
|
111
|
-
'88' => '
|
118
|
+
'88' => 'Cryptographic failure',
|
112
119
|
'89' => 'Authentication failure',
|
113
120
|
'91' => 'Issuer not available',
|
114
121
|
'92' => 'Unable to route at acquirer Module',
|
@@ -116,9 +123,13 @@ module ActiveMerchant #:nodoc:
|
|
116
123
|
'94' => 'Duplicate Transmission',
|
117
124
|
'95' => 'Reconcile error / Auth Not found',
|
118
125
|
'96' => 'System malfunction',
|
126
|
+
'97' => 'Transaction has been declined by the processor',
|
127
|
+
'N3' => 'Cash service not available',
|
128
|
+
'N4' => 'Cash request exceeds issuer or approved limit',
|
129
|
+
'N7' => 'CVV2 failure',
|
119
130
|
'R0' => 'Stop Payment Order',
|
120
131
|
'R1' => 'Revocation of Authorisation Order',
|
121
|
-
'R3' => 'Revocation of all
|
132
|
+
'R3' => 'Revocation of all Authorisation Orders',
|
122
133
|
'1A' => 'Strong Customer Authentication required'
|
123
134
|
}
|
124
135
|
|
@@ -130,7 +141,7 @@ module ActiveMerchant #:nodoc:
|
|
130
141
|
def purchase(amount, payment_method, options = {})
|
131
142
|
post = {}
|
132
143
|
add_invoice(post, amount, options)
|
133
|
-
add_payment_method(post, payment_method)
|
144
|
+
add_payment_method(post, payment_method, options)
|
134
145
|
add_customer_data(post, options)
|
135
146
|
add_email(post, options)
|
136
147
|
add_3d_secure(post, options)
|
@@ -146,7 +157,7 @@ module ActiveMerchant #:nodoc:
|
|
146
157
|
def authorize(amount, payment_method, options = {})
|
147
158
|
post = {}
|
148
159
|
add_invoice(post, amount, options)
|
149
|
-
add_payment_method(post, payment_method)
|
160
|
+
add_payment_method(post, payment_method, options)
|
150
161
|
add_customer_data(post, options)
|
151
162
|
add_email(post, options)
|
152
163
|
add_3d_secure(post, options)
|
@@ -206,13 +217,14 @@ module ActiveMerchant #:nodoc:
|
|
206
217
|
def credit(amount, payment_method, options = {})
|
207
218
|
post = {}
|
208
219
|
add_invoice(post, amount, options)
|
209
|
-
add_payment_method(post, payment_method)
|
220
|
+
add_payment_method(post, payment_method, options)
|
210
221
|
add_customer_data(post, options)
|
211
222
|
add_email(post, options)
|
212
223
|
add_echo(post, options)
|
213
224
|
add_submerchant_id(post, options)
|
214
225
|
add_transaction_type(post, options)
|
215
226
|
add_processor(post, options)
|
227
|
+
add_customer_name(post, options)
|
216
228
|
|
217
229
|
commit(:credit, post)
|
218
230
|
end
|
@@ -271,8 +283,9 @@ module ActiveMerchant #:nodoc:
|
|
271
283
|
'maestro' => '9'
|
272
284
|
}
|
273
285
|
|
274
|
-
def add_payment_method(post, payment_method)
|
275
|
-
post[:c1] = payment_method
|
286
|
+
def add_payment_method(post, payment_method, options)
|
287
|
+
post[:c1] = payment_method&.name || ''
|
288
|
+
add_network_tokenization_card(post, payment_method, options) if payment_method.is_a? NetworkTokenizationCreditCard
|
276
289
|
post[:b2] = CARD_TYPES[payment_method.brand] || ''
|
277
290
|
post[:b1] = payment_method.number
|
278
291
|
post[:b5] = payment_method.verification_value
|
@@ -280,6 +293,13 @@ module ActiveMerchant #:nodoc:
|
|
280
293
|
post[:b3] = format(payment_method.month, :two_digits)
|
281
294
|
end
|
282
295
|
|
296
|
+
def add_network_tokenization_card(post, payment_method, options)
|
297
|
+
post[:b21] = NETWORK_TOKENIZATION_CARD_SOURCE[payment_method.source.to_s]
|
298
|
+
post[:token_eci] = post[:b21] == 'vts_mdes_token' ? '07' : nil
|
299
|
+
post[:token_eci] = options[:eci] || payment_method&.eci || (payment_method.brand.to_s == 'master' ? '00' : '07')
|
300
|
+
post[:token_crypto] = payment_method&.payment_cryptogram if payment_method.source.to_s == 'network_token'
|
301
|
+
end
|
302
|
+
|
283
303
|
def add_stored_credential(post, options)
|
284
304
|
add_transaction_type(post, options)
|
285
305
|
# if :transaction_type option is not passed, then check for :stored_credential options
|
@@ -288,10 +308,11 @@ module ActiveMerchant #:nodoc:
|
|
288
308
|
if stored_credential[:initiator] == 'merchant'
|
289
309
|
case stored_credential[:reason_type]
|
290
310
|
when 'recurring'
|
291
|
-
|
311
|
+
post[:a9] = stored_credential[:initial_transaction] ? '1' : '2'
|
292
312
|
when 'installment', 'unscheduled'
|
293
313
|
post[:a9] = '8'
|
294
314
|
end
|
315
|
+
post[:g6] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
295
316
|
else
|
296
317
|
post[:a9] = '9'
|
297
318
|
end
|
@@ -324,10 +345,11 @@ module ActiveMerchant #:nodoc:
|
|
324
345
|
def add_recipient(post, options)
|
325
346
|
return unless options[:recipient_street_address] || options[:recipient_city] || options[:recipient_province_code] || options[:recipient_country_code]
|
326
347
|
|
348
|
+
recipient_country_code = options[:recipient_country_code]&.length == 3 ? options[:recipient_country_code] : Country.find(options[:recipient_country_code]).code(:alpha3).value if options[:recipient_country_code]
|
327
349
|
post[:j6] = options[:recipient_street_address] if options[:recipient_street_address]
|
328
350
|
post[:j7] = options[:recipient_city] if options[:recipient_city]
|
329
351
|
post[:j8] = options[:recipient_province_code] if options[:recipient_province_code]
|
330
|
-
post[:j9] =
|
352
|
+
post[:j9] = recipient_country_code
|
331
353
|
end
|
332
354
|
|
333
355
|
def add_customer_name(post, options)
|
@@ -434,7 +456,7 @@ module ActiveMerchant #:nodoc:
|
|
434
456
|
capture: '3',
|
435
457
|
authorize_void: '4',
|
436
458
|
refund: '5',
|
437
|
-
credit: '
|
459
|
+
credit: '35',
|
438
460
|
purchase_void: '7',
|
439
461
|
refund_void: '8',
|
440
462
|
capture_void: '9',
|
@@ -475,11 +497,9 @@ module ActiveMerchant #:nodoc:
|
|
475
497
|
end
|
476
498
|
|
477
499
|
def request_action(action, reference_action)
|
478
|
-
if reference_action
|
479
|
-
|
480
|
-
|
481
|
-
ACTIONS[action]
|
482
|
-
end
|
500
|
+
return ACTIONS["#{reference_action}_#{action}".to_sym] if reference_action
|
501
|
+
|
502
|
+
ACTIONS[action]
|
483
503
|
end
|
484
504
|
|
485
505
|
def url
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module CyberSourceCommon
|
4
|
+
def check_billing_field_value(default, submitted)
|
5
|
+
if submitted.nil?
|
6
|
+
nil
|
7
|
+
elsif submitted.blank?
|
8
|
+
default
|
9
|
+
else
|
10
|
+
submitted
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def address_names(address_name, payment_method)
|
15
|
+
names = split_names(address_name)
|
16
|
+
return names if names.any?(&:present?)
|
17
|
+
|
18
|
+
[
|
19
|
+
payment_method&.first_name,
|
20
|
+
payment_method&.last_name
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
def lookup_country_code(country_field)
|
25
|
+
return unless country_field.present?
|
26
|
+
|
27
|
+
country_code = Country.find(country_field)
|
28
|
+
country_code&.code(:alpha2)
|
29
|
+
end
|
30
|
+
|
31
|
+
def eligible_for_zero_auth?(payment_method, options = {})
|
32
|
+
payment_method.is_a?(CreditCard) && options[:zero_amount_auth]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|