activemerchant 1.123.0 → 1.126.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 +206 -0
- data/lib/active_merchant/billing/check.rb +5 -8
- data/lib/active_merchant/billing/credit_card.rb +10 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +18 -3
- data/lib/active_merchant/billing/gateway.rb +3 -2
- data/lib/active_merchant/billing/gateways/adyen.rb +66 -11
- data/lib/active_merchant/billing/gateways/airwallex.rb +341 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
- data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/blue_snap.rb +31 -21
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +87 -15
- data/lib/active_merchant/billing/gateways/card_connect.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
- data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +34 -5
- data/lib/active_merchant/billing/gateways/credorax.rb +10 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +24 -36
- data/lib/active_merchant/billing/gateways/d_local.rb +61 -6
- data/lib/active_merchant/billing/gateways/decidir.rb +17 -1
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +19 -3
- data/lib/active_merchant/billing/gateways/elavon.rb +6 -3
- data/lib/active_merchant/billing/gateways/element.rb +20 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +137 -32
- data/lib/active_merchant/billing/gateways/ipg.rb +415 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +7 -0
- data/lib/active_merchant/billing/gateways/litle.rb +93 -1
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -1
- data/lib/active_merchant/billing/gateways/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/moka.rb +24 -11
- data/lib/active_merchant/billing/gateways/moneris.rb +35 -8
- data/lib/active_merchant/billing/gateways/mundipagg.rb +8 -6
- data/lib/active_merchant/billing/gateways/nmi.rb +27 -8
- data/lib/active_merchant/billing/gateways/orbital.rb +357 -319
- data/lib/active_merchant/billing/gateways/pay_arc.rb +9 -7
- data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
- data/lib/active_merchant/billing/gateways/pay_trace.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +76 -6
- data/lib/active_merchant/billing/gateways/paymentez.rb +35 -9
- data/lib/active_merchant/billing/gateways/paysafe.rb +155 -34
- data/lib/active_merchant/billing/gateways/payu_latam.rb +31 -16
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
- data/lib/active_merchant/billing/gateways/pin.rb +31 -4
- data/lib/active_merchant/billing/gateways/priority.rb +369 -0
- data/lib/active_merchant/billing/gateways/rapyd.rb +258 -0
- data/lib/active_merchant/billing/gateways/realex.rb +18 -0
- data/lib/active_merchant/billing/gateways/safe_charge.rb +7 -6
- data/lib/active_merchant/billing/gateways/simetrik.rb +362 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +30 -8
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +175 -72
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +20 -6
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
- data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +196 -64
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/billing/response.rb +4 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +11 -2
@@ -82,6 +82,7 @@ module ActiveMerchant #:nodoc:
|
|
82
82
|
add_invoice(action, post, amount, options)
|
83
83
|
add_payment_method(post, payment_method, options)
|
84
84
|
add_full_response(post, options)
|
85
|
+
add_metadata(post, options)
|
85
86
|
|
86
87
|
commit(action, post)
|
87
88
|
end
|
@@ -94,6 +95,7 @@ module ActiveMerchant #:nodoc:
|
|
94
95
|
add_invoice(action, post, amount, options)
|
95
96
|
add_contact_details(post, options[:contact_details]) if options[:contact_details]
|
96
97
|
add_full_response(post, options)
|
98
|
+
add_metadata(post, options)
|
97
99
|
|
98
100
|
commit(action, post)
|
99
101
|
end
|
@@ -105,6 +107,7 @@ module ActiveMerchant #:nodoc:
|
|
105
107
|
add_reference(post, authorization, options)
|
106
108
|
add_invoice(action, post, amount, options)
|
107
109
|
add_full_response(post, options)
|
110
|
+
add_metadata(post, options)
|
108
111
|
|
109
112
|
commit(action, post)
|
110
113
|
end
|
@@ -177,6 +180,10 @@ module ActiveMerchant #:nodoc:
|
|
177
180
|
post[:fullResponse] = options[:full_response].to_s.casecmp('true').zero? if options[:full_response]
|
178
181
|
end
|
179
182
|
|
183
|
+
def add_metadata(post, options)
|
184
|
+
post[:metadata] = options[:metadata] if options[:metadata]
|
185
|
+
end
|
186
|
+
|
180
187
|
ENDPOINT = {
|
181
188
|
'tokenize' => 'tokens',
|
182
189
|
'charge' => 'charges',
|
@@ -39,6 +39,96 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
check?(payment_method) ? commit(:echeckSales, request, money) : commit(:sale, request, money)
|
40
40
|
end
|
41
41
|
|
42
|
+
def add_level_two_data(doc, payment_method, options = {})
|
43
|
+
level_2_data = options[:level_2_data]
|
44
|
+
if level_2_data
|
45
|
+
doc.enhancedData do
|
46
|
+
case payment_method.brand
|
47
|
+
when 'visa'
|
48
|
+
doc.salesTax(level_2_data[:sales_tax]) if level_2_data[:sales_tax]
|
49
|
+
when 'master'
|
50
|
+
doc.customerReference(level_2_data[:customer_code]) if level_2_data[:customer_code]
|
51
|
+
doc.salesTax(level_2_data[:total_tax_amount]) if level_2_data[:total_tax_amount]
|
52
|
+
doc.detailTax do
|
53
|
+
doc.taxIncludedInTotal(level_2_data[:tax_included_in_total]) if level_2_data[:tax_included_in_total]
|
54
|
+
doc.taxAmount(level_2_data[:tax_amount]) if level_2_data[:tax_amount]
|
55
|
+
doc.cardAcceptorTaxId(level_2_data[:card_acceptor_tax_id]) if level_2_data[:card_acceptor_tax_id]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_level_three_data(doc, payment_method, options = {})
|
63
|
+
level_3_data = options[:level_3_data]
|
64
|
+
if level_3_data
|
65
|
+
doc.enhancedData do
|
66
|
+
case payment_method.brand
|
67
|
+
when 'visa'
|
68
|
+
add_level_three_information_tags_visa(doc, payment_method, level_3_data)
|
69
|
+
when 'master'
|
70
|
+
add_level_three_information_tags_master(doc, payment_method, level_3_data)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_level_three_information_tags_visa(doc, payment_method, level_3_data)
|
77
|
+
doc.discountAmount(level_3_data[:discount_amount]) if level_3_data[:discount_amount]
|
78
|
+
doc.shippingAmount(level_3_data[:shipping_amount]) if level_3_data[:shipping_amount]
|
79
|
+
doc.dutyAmount(level_3_data[:duty_amount]) if level_3_data[:duty_amount]
|
80
|
+
doc.detailTax do
|
81
|
+
doc.taxIncludedInTotal(level_3_data[:tax_included_in_total]) if level_3_data[:tax_included_in_total]
|
82
|
+
doc.taxAmount(level_3_data[:tax_amount]) if level_3_data[:tax_amount]
|
83
|
+
doc.taxRate(level_3_data[:tax_rate]) if level_3_data[:tax_rate]
|
84
|
+
doc.taxTypeIdentifier(level_3_data[:tax_type_identifier]) if level_3_data[:tax_type_identifier]
|
85
|
+
doc.cardAcceptorTaxId(level_3_data[:card_acceptor_tax_id]) if level_3_data[:card_acceptor_tax_id]
|
86
|
+
end
|
87
|
+
add_line_item_information_for_level_three_visa(doc, payment_method, level_3_data)
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_level_three_information_tags_master(doc, payment_method, level_3_data)
|
91
|
+
doc.customerReference :customerReference, level_3_data[:customer_code] if level_3_data[:customer_code]
|
92
|
+
doc.salesTax(level_3_data[:total_tax_amount]) if level_3_data[:total_tax_amount]
|
93
|
+
doc.detailTax do
|
94
|
+
doc.taxIncludedInTotal(level_3_data[:tax_included_in_total]) if level_3_data[:tax_included_in_total]
|
95
|
+
doc.taxAmount(level_3_data[:tax_amount]) if level_3_data[:tax_amount]
|
96
|
+
doc.cardAcceptorTaxId :cardAcceptorTaxId, level_3_data[:card_acceptor_tax_id] if level_3_data[:card_acceptor_tax_id]
|
97
|
+
end
|
98
|
+
doc.lineItemData do
|
99
|
+
level_3_data[:line_items].each do |line_item|
|
100
|
+
doc.itemDescription(line_item[:item_description]) if line_item[:item_description]
|
101
|
+
doc.productCode(line_item[:product_code]) if line_item[:product_code]
|
102
|
+
doc.quantity(line_item[:quantity]) if line_item[:quantity]
|
103
|
+
doc.unitOfMeasure(line_item[:unit_of_measure]) if line_item[:unit_of_measure]
|
104
|
+
doc.lineItemTotal(line_item[:line_item_total]) if line_item[:line_item_total]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def add_line_item_information_for_level_three_visa(doc, payment_method, level_3_data)
|
110
|
+
doc.lineItemData do
|
111
|
+
level_3_data[:line_items].each do |line_item|
|
112
|
+
doc.itemSequenceNumber(line_item[:item_sequence_number]) if line_item[:item_sequence_number]
|
113
|
+
doc.commodityCode(line_item[:commodity_code]) if line_item[:commodity_code]
|
114
|
+
doc.itemDescription(line_item[:item_description]) if line_item[:item_description]
|
115
|
+
doc.productCode(line_item[:product_code]) if line_item[:product_code]
|
116
|
+
doc.quantity(line_item[:quantity]) if line_item[:quantity]
|
117
|
+
doc.unitOfMeasure(line_item[:unit_of_measure]) if line_item[:unit_of_measure]
|
118
|
+
doc.taxAmount(line_item[:tax_amount]) if line_item[:tax_amount]
|
119
|
+
doc.itemDiscountAmount(line_item[:discount_per_line_item]) unless line_item[:discount_per_line_item] < 0
|
120
|
+
doc.unitCost(line_item[:unit_cost]) unless line_item[:unit_cost] < 0
|
121
|
+
doc.detailTax do
|
122
|
+
doc.taxIncludedInTotal(line_item[:tax_included_in_total]) if line_item[:tax_included_in_total]
|
123
|
+
doc.taxAmount(line_item[:tax_amount]) if line_item[:tax_amount]
|
124
|
+
doc.taxRate(line_item[:tax_rate]) if line_item[:tax_rate]
|
125
|
+
doc.taxTypeIdentifier(line_item[:tax_type_identifier]) if line_item[:tax_type_identifier]
|
126
|
+
doc.cardAcceptorTaxId(line_item[:card_acceptor_tax_id]) if line_item[:card_acceptor_tax_id]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
42
132
|
def authorize(money, payment_method, options = {})
|
43
133
|
request = build_xml_request do |doc|
|
44
134
|
add_authentication(doc)
|
@@ -225,6 +315,8 @@ module ActiveMerchant #:nodoc:
|
|
225
315
|
add_payment_method(doc, payment_method, options)
|
226
316
|
add_pos(doc, payment_method)
|
227
317
|
add_descriptor(doc, options)
|
318
|
+
add_level_two_data(doc, payment_method, options)
|
319
|
+
add_level_three_data(doc, payment_method, options)
|
228
320
|
add_merchant_data(doc, options)
|
229
321
|
add_debt_repayment(doc, options)
|
230
322
|
add_stored_credential_params(doc, options)
|
@@ -386,7 +478,7 @@ module ActiveMerchant #:nodoc:
|
|
386
478
|
doc.orderSource(order_source)
|
387
479
|
elsif payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :apple_pay
|
388
480
|
doc.orderSource('applepay')
|
389
|
-
elsif payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source
|
481
|
+
elsif payment_method.is_a?(NetworkTokenizationCreditCard) && %i[google_pay android_pay].include?(payment_method.source)
|
390
482
|
doc.orderSource('androidpay')
|
391
483
|
elsif payment_method.respond_to?(:track_data) && payment_method.track_data.present?
|
392
484
|
doc.orderSource('retail')
|
@@ -53,8 +53,10 @@ module ActiveMerchant #:nodoc:
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def verify(credit_card, options = {})
|
56
|
+
verify_amount = 100
|
57
|
+
verify_amount = options[:amount].to_i if options[:amount]
|
56
58
|
MultiResponse.run(:use_first_response) do |r|
|
57
|
-
r.process { authorize(
|
59
|
+
r.process { authorize(verify_amount, credit_card, options) }
|
58
60
|
r.process(:ignore_result) { void(r.authorization, options) }
|
59
61
|
end
|
60
62
|
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'openssl'
|
3
|
+
require 'digest'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
module ActiveMerchant #:nodoc:
|
7
|
+
module Billing #:nodoc:
|
8
|
+
class MitGateway < Gateway
|
9
|
+
self.live_url = 'https://wpy.mitec.com.mx/ModuloUtilWS/activeCDP.htm'
|
10
|
+
|
11
|
+
self.supported_countries = ['MX']
|
12
|
+
self.default_currency = 'MXN'
|
13
|
+
self.supported_cardtypes = %i[visa master]
|
14
|
+
|
15
|
+
self.homepage_url = 'http://www.centrodepagos.com.mx/'
|
16
|
+
self.display_name = 'MIT Centro de pagos'
|
17
|
+
|
18
|
+
self.money_format = :dollars
|
19
|
+
|
20
|
+
def initialize(options = {})
|
21
|
+
requires!(options, :commerce_id, :user, :api_key, :key_session)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def purchase(money, payment, options = {})
|
26
|
+
MultiResponse.run do |r|
|
27
|
+
r.process { authorize(money, payment, options) }
|
28
|
+
r.process { capture(money, r.authorization, options) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def cipher_key
|
33
|
+
@options[:key_session]
|
34
|
+
end
|
35
|
+
|
36
|
+
def decrypt(val, keyinhex)
|
37
|
+
# Splits the first 16 bytes (the IV bytes) in array format
|
38
|
+
unpacked = val.unpack('m')
|
39
|
+
iv_base64 = unpacked[0].bytes.slice(0, 16)
|
40
|
+
# Splits the second bytes (the encrypted text bytes) these would be the
|
41
|
+
# original message
|
42
|
+
full_data = unpacked[0].bytes.slice(16, unpacked[0].bytes.length)
|
43
|
+
# Creates the engine
|
44
|
+
engine = OpenSSL::Cipher::AES128.new(:CBC)
|
45
|
+
# Set engine as decrypt mode
|
46
|
+
engine.decrypt
|
47
|
+
# Converts the key from hex to bytes
|
48
|
+
engine.key = [keyinhex].pack('H*')
|
49
|
+
# Converts the ivBase64 array into bytes
|
50
|
+
engine.iv = iv_base64.pack('c*')
|
51
|
+
# Decrypts the texts and returns the original string
|
52
|
+
engine.update(full_data.pack('c*')) + engine.final
|
53
|
+
end
|
54
|
+
|
55
|
+
def encrypt(val, keyinhex)
|
56
|
+
# Creates the engine motor
|
57
|
+
engine = OpenSSL::Cipher::AES128.new(:CBC)
|
58
|
+
# Set engine as encrypt mode
|
59
|
+
engine.encrypt
|
60
|
+
# Converts the key from hex to bytes
|
61
|
+
engine.key = [keyinhex].pack('H*')
|
62
|
+
# Generates a random iv with this settings
|
63
|
+
iv_rand = engine.random_iv
|
64
|
+
# Packs IV as a Base64 string
|
65
|
+
iv_base64 = [iv_rand].pack('m')
|
66
|
+
# Converts the packed key into bytes
|
67
|
+
unpacked = iv_base64.unpack('m')
|
68
|
+
iv = unpacked[0]
|
69
|
+
# Sets the IV into the engine
|
70
|
+
engine.iv = iv
|
71
|
+
# Encrypts the texts and stores the bytes
|
72
|
+
encrypted_bytes = engine.update(val) + engine.final
|
73
|
+
# Concatenates the (a) IV bytes and (b) the encrypted bytes then returns a
|
74
|
+
# base64 representation
|
75
|
+
[iv << encrypted_bytes].pack('m')
|
76
|
+
end
|
77
|
+
|
78
|
+
def authorize(money, payment, options = {})
|
79
|
+
post = {
|
80
|
+
operation: 'Authorize',
|
81
|
+
commerce_id: @options[:commerce_id],
|
82
|
+
user: @options[:user],
|
83
|
+
apikey: @options[:api_key],
|
84
|
+
testMode: (test? ? 'YES' : 'NO')
|
85
|
+
}
|
86
|
+
add_invoice(post, money, options)
|
87
|
+
# Payments contains the card information
|
88
|
+
add_payment(post, payment)
|
89
|
+
add_customer_data(post, options)
|
90
|
+
post[:key_session] = @options[:key_session]
|
91
|
+
|
92
|
+
post_to_json = post.to_json
|
93
|
+
post_to_json_encrypt = encrypt(post_to_json, @options[:key_session])
|
94
|
+
|
95
|
+
final_post = '<authorization>' + post_to_json_encrypt + '</authorization><dataID>' + @options[:user] + '</dataID>'
|
96
|
+
json_post = {}
|
97
|
+
json_post[:payload] = final_post
|
98
|
+
commit('sale', json_post)
|
99
|
+
end
|
100
|
+
|
101
|
+
def capture(money, authorization, options = {})
|
102
|
+
post = {
|
103
|
+
operation: 'Capture',
|
104
|
+
commerce_id: @options[:commerce_id],
|
105
|
+
user: @options[:user],
|
106
|
+
apikey: @options[:api_key],
|
107
|
+
testMode: (test? ? 'YES' : 'NO'),
|
108
|
+
transaction_id: authorization,
|
109
|
+
amount: amount(money)
|
110
|
+
}
|
111
|
+
post[:key_session] = @options[:key_session]
|
112
|
+
|
113
|
+
post_to_json = post.to_json
|
114
|
+
post_to_json_encrypt = encrypt(post_to_json, @options[:key_session])
|
115
|
+
|
116
|
+
final_post = '<capture>' + post_to_json_encrypt + '</capture><dataID>' + @options[:user] + '</dataID>'
|
117
|
+
json_post = {}
|
118
|
+
json_post[:payload] = final_post
|
119
|
+
commit('capture', json_post)
|
120
|
+
end
|
121
|
+
|
122
|
+
def refund(money, authorization, options = {})
|
123
|
+
post = {
|
124
|
+
operation: 'Refund',
|
125
|
+
commerce_id: @options[:commerce_id],
|
126
|
+
user: @options[:user],
|
127
|
+
apikey: @options[:api_key],
|
128
|
+
testMode: (test? ? 'YES' : 'NO'),
|
129
|
+
transaction_id: authorization,
|
130
|
+
auth: authorization,
|
131
|
+
amount: amount(money)
|
132
|
+
}
|
133
|
+
post[:key_session] = @options[:key_session]
|
134
|
+
|
135
|
+
post_to_json = post.to_json
|
136
|
+
post_to_json_encrypt = encrypt(post_to_json, @options[:key_session])
|
137
|
+
|
138
|
+
final_post = '<refund>' + post_to_json_encrypt + '</refund><dataID>' + @options[:user] + '</dataID>'
|
139
|
+
json_post = {}
|
140
|
+
json_post[:payload] = final_post
|
141
|
+
commit('refund', json_post)
|
142
|
+
end
|
143
|
+
|
144
|
+
def supports_scrubbing?
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
def scrub(transcript)
|
149
|
+
ret_transcript = transcript
|
150
|
+
auth_origin = ret_transcript[/<authorization>(.*?)<\/authorization>/, 1]
|
151
|
+
unless auth_origin.nil?
|
152
|
+
auth_decrypted = decrypt(auth_origin, @options[:key_session])
|
153
|
+
auth_json = JSON.parse(auth_decrypted)
|
154
|
+
auth_json['card'] = '[FILTERED]'
|
155
|
+
auth_json['cvv'] = '[FILTERED]'
|
156
|
+
auth_json['apikey'] = '[FILTERED]'
|
157
|
+
auth_json['key_session'] = '[FILTERED]'
|
158
|
+
auth_to_json = auth_json.to_json
|
159
|
+
auth_tagged = '<authorization>' + auth_to_json + '</authorization>'
|
160
|
+
ret_transcript = ret_transcript.gsub(/<authorization>(.*?)<\/authorization>/, auth_tagged)
|
161
|
+
end
|
162
|
+
|
163
|
+
cap_origin = ret_transcript[/<capture>(.*?)<\/capture>/, 1]
|
164
|
+
unless cap_origin.nil?
|
165
|
+
cap_decrypted = decrypt(cap_origin, @options[:key_session])
|
166
|
+
cap_json = JSON.parse(cap_decrypted)
|
167
|
+
cap_json['apikey'] = '[FILTERED]'
|
168
|
+
cap_json['key_session'] = '[FILTERED]'
|
169
|
+
cap_to_json = cap_json.to_json
|
170
|
+
cap_tagged = '<capture>' + cap_to_json + '</capture>'
|
171
|
+
ret_transcript = ret_transcript.gsub(/<capture>(.*?)<\/capture>/, cap_tagged)
|
172
|
+
end
|
173
|
+
|
174
|
+
ref_origin = ret_transcript[/<refund>(.*?)<\/refund>/, 1]
|
175
|
+
unless ref_origin.nil?
|
176
|
+
ref_decrypted = decrypt(ref_origin, @options[:key_session])
|
177
|
+
ref_json = JSON.parse(ref_decrypted)
|
178
|
+
ref_json['apikey'] = '[FILTERED]'
|
179
|
+
ref_json['key_session'] = '[FILTERED]'
|
180
|
+
ref_to_json = ref_json.to_json
|
181
|
+
ref_tagged = '<refund>' + ref_to_json + '</refund>'
|
182
|
+
ret_transcript = ret_transcript.gsub(/<refund>(.*?)<\/refund>/, ref_tagged)
|
183
|
+
end
|
184
|
+
|
185
|
+
res_origin = ret_transcript[/#{Regexp.escape('reading ')}(.*?)#{Regexp.escape('read')}/m, 1]
|
186
|
+
loop do
|
187
|
+
break if res_origin.nil?
|
188
|
+
|
189
|
+
resp_origin = res_origin[/#{Regexp.escape('"')}(.*?)#{Regexp.escape('"')}/m, 1]
|
190
|
+
resp_decrypted = decrypt(resp_origin, @options[:key_session])
|
191
|
+
ret_transcript[/#{Regexp.escape('reading ')}(.*?)#{Regexp.escape('read')}/m, 1] = resp_decrypted
|
192
|
+
ret_transcript = ret_transcript.sub('reading ', 'response: ')
|
193
|
+
res_origin = ret_transcript[/#{Regexp.escape('reading ')}(.*?)#{Regexp.escape('read')}/m, 1]
|
194
|
+
end
|
195
|
+
|
196
|
+
ret_transcript
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def add_customer_data(post, options)
|
202
|
+
post[:email] = options[:email] || 'nadie@mit.test'
|
203
|
+
end
|
204
|
+
|
205
|
+
def add_invoice(post, money, options)
|
206
|
+
post[:amount] = amount(money)
|
207
|
+
post[:currency] = (options[:currency] || currency(money))
|
208
|
+
post[:reference] = options[:order_id]
|
209
|
+
post[:transaction_id] = options[:order_id]
|
210
|
+
end
|
211
|
+
|
212
|
+
def add_payment(post, payment)
|
213
|
+
post[:installments] = 1
|
214
|
+
post[:card] = payment.number
|
215
|
+
post[:expmonth] = payment.month
|
216
|
+
post[:expyear] = payment.year
|
217
|
+
post[:cvv] = payment.verification_value
|
218
|
+
post[:name_client] = [payment.first_name, payment.last_name].join(' ')
|
219
|
+
end
|
220
|
+
|
221
|
+
def commit(action, parameters)
|
222
|
+
json_str = JSON.generate(parameters)
|
223
|
+
cleaned_str = json_str.gsub('\n', '')
|
224
|
+
raw_response = ssl_post(live_url, cleaned_str, { 'Content-type' => 'application/json' })
|
225
|
+
response = JSON.parse(decrypt(raw_response, @options[:key_session]))
|
226
|
+
|
227
|
+
Response.new(
|
228
|
+
success_from(response),
|
229
|
+
message_from(response),
|
230
|
+
response,
|
231
|
+
authorization: authorization_from(response),
|
232
|
+
avs_result: AVSResult.new(code: response['some_avs_response_key']),
|
233
|
+
cvv_result: CVVResult.new(response['some_cvv_response_key']),
|
234
|
+
test: test?,
|
235
|
+
error_code: error_code_from(response)
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
def success_from(response)
|
240
|
+
response['response'] == 'approved'
|
241
|
+
end
|
242
|
+
|
243
|
+
def message_from(response)
|
244
|
+
response['response']
|
245
|
+
end
|
246
|
+
|
247
|
+
def authorization_from(response)
|
248
|
+
response['reference']
|
249
|
+
end
|
250
|
+
|
251
|
+
def post_data(action, parameters = {})
|
252
|
+
parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
|
253
|
+
end
|
254
|
+
|
255
|
+
def error_code_from(response)
|
256
|
+
response['message'].split(' -- ', 2)[0] unless success_from(response)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class MokaGateway < Gateway
|
4
|
-
self.test_url = 'https://service.
|
4
|
+
self.test_url = 'https://service.refmoka.com'
|
5
5
|
self.live_url = 'https://service.moka.com'
|
6
6
|
|
7
7
|
self.supported_countries = %w[GB TR US]
|
@@ -55,8 +55,10 @@ module ActiveMerchant #:nodoc:
|
|
55
55
|
post[:PaymentDealerRequest] = {}
|
56
56
|
options[:pre_auth] = 0
|
57
57
|
add_auth_purchase(post, money, payment, options)
|
58
|
+
add_3ds_data(post, options) if options[:execute_threed]
|
58
59
|
|
59
|
-
|
60
|
+
action = options[:execute_threed] ? 'three_ds_purchase' : 'purchase'
|
61
|
+
commit(action, post)
|
60
62
|
end
|
61
63
|
|
62
64
|
def authorize(money, payment, options = {})
|
@@ -64,8 +66,10 @@ module ActiveMerchant #:nodoc:
|
|
64
66
|
post[:PaymentDealerRequest] = {}
|
65
67
|
options[:pre_auth] = 1
|
66
68
|
add_auth_purchase(post, money, payment, options)
|
69
|
+
add_3ds_data(post, options) if options[:execute_threed]
|
67
70
|
|
68
|
-
|
71
|
+
action = options[:execute_threed] ? 'three_ds_authorize' : 'authorize'
|
72
|
+
commit(action, post)
|
69
73
|
end
|
70
74
|
|
71
75
|
def capture(money, authorization, options = {})
|
@@ -73,7 +77,7 @@ module ActiveMerchant #:nodoc:
|
|
73
77
|
post[:PaymentDealerRequest] = {}
|
74
78
|
add_payment_dealer_authentication(post)
|
75
79
|
add_transaction_reference(post, authorization)
|
76
|
-
|
80
|
+
add_invoice(post, money, options)
|
77
81
|
|
78
82
|
commit('capture', post)
|
79
83
|
end
|
@@ -83,7 +87,6 @@ module ActiveMerchant #:nodoc:
|
|
83
87
|
post[:PaymentDealerRequest] = {}
|
84
88
|
add_payment_dealer_authentication(post)
|
85
89
|
add_transaction_reference(post, authorization)
|
86
|
-
add_additional_transaction_data(post, options)
|
87
90
|
add_void_refund_reason(post)
|
88
91
|
add_amount(post, money)
|
89
92
|
|
@@ -95,7 +98,6 @@ module ActiveMerchant #:nodoc:
|
|
95
98
|
post[:PaymentDealerRequest] = {}
|
96
99
|
add_payment_dealer_authentication(post)
|
97
100
|
add_transaction_reference(post, authorization)
|
98
|
-
add_additional_transaction_data(post, options)
|
99
101
|
add_void_refund_reason(post)
|
100
102
|
|
101
103
|
commit('void', post)
|
@@ -134,6 +136,12 @@ module ActiveMerchant #:nodoc:
|
|
134
136
|
add_basket_product(post, options[:basket_product]) if options[:basket_product]
|
135
137
|
end
|
136
138
|
|
139
|
+
def add_3ds_data(post, options)
|
140
|
+
post[:PaymentDealerRequest][:ReturnHash] = 1
|
141
|
+
post[:PaymentDealerRequest][:RedirectUrl] = options[:redirect_url] || ''
|
142
|
+
post[:PaymentDealerRequest][:RedirectType] = options[:redirect_type] || 0
|
143
|
+
end
|
144
|
+
|
137
145
|
def add_payment_dealer_authentication(post)
|
138
146
|
post[:PaymentDealerAuthentication] = {
|
139
147
|
DealerCode: @options[:dealer_code],
|
@@ -156,18 +164,19 @@ module ActiveMerchant #:nodoc:
|
|
156
164
|
def add_payment(post, card)
|
157
165
|
post[:PaymentDealerRequest][:CardHolderFullName] = card.name
|
158
166
|
post[:PaymentDealerRequest][:CardNumber] = card.number
|
159
|
-
post[:PaymentDealerRequest][:ExpMonth] = card.month
|
167
|
+
post[:PaymentDealerRequest][:ExpMonth] = card.month.to_s.rjust(2, '0')
|
160
168
|
post[:PaymentDealerRequest][:ExpYear] = card.year
|
161
|
-
post[:PaymentDealerRequest][:CvcNumber] = card.verification_value
|
169
|
+
post[:PaymentDealerRequest][:CvcNumber] = card.verification_value || ''
|
162
170
|
end
|
163
171
|
|
164
172
|
def add_amount(post, money)
|
165
|
-
post[:PaymentDealerRequest][:Amount] = money || 0
|
173
|
+
post[:PaymentDealerRequest][:Amount] = amount(money) || 0
|
166
174
|
end
|
167
175
|
|
168
176
|
def add_additional_auth_purchase_data(post, options)
|
169
177
|
post[:PaymentDealerRequest][:IsPreAuth] = options[:pre_auth]
|
170
|
-
post[:PaymentDealerRequest][:Description] = options[:
|
178
|
+
post[:PaymentDealerRequest][:Description] = options[:description] if options[:description]
|
179
|
+
post[:PaymentDealerRequest][:InstallmentNumber] = options[:installment_number].to_i if options[:installment_number]
|
171
180
|
post[:SubMerchantName] = options[:sub_merchant_name] if options[:sub_merchant_name]
|
172
181
|
post[:IsPoolPayment] = options[:is_pool_payment] || 0
|
173
182
|
end
|
@@ -232,6 +241,8 @@ module ActiveMerchant #:nodoc:
|
|
232
241
|
|
233
242
|
def endpoint(action)
|
234
243
|
case action
|
244
|
+
when 'three_ds_authorize', 'three_ds_purchase'
|
245
|
+
'DoDirectPaymentThreeD'
|
235
246
|
when 'purchase', 'authorize'
|
236
247
|
'DoDirectPayment'
|
237
248
|
when 'capture'
|
@@ -256,7 +267,9 @@ module ActiveMerchant #:nodoc:
|
|
256
267
|
end
|
257
268
|
|
258
269
|
def success_from(response)
|
259
|
-
response.dig('Data', 'IsSuccessful')
|
270
|
+
return response.dig('Data', 'IsSuccessful') if response.dig('Data', 'IsSuccessful').to_s.present?
|
271
|
+
|
272
|
+
response['ResultCode']&.casecmp('success') == 0
|
260
273
|
end
|
261
274
|
|
262
275
|
def message_from(response)
|
@@ -50,15 +50,16 @@ module ActiveMerchant #:nodoc:
|
|
50
50
|
post[:order_id] = options[:order_id]
|
51
51
|
post[:address] = options[:billing_address] || options[:address]
|
52
52
|
post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
|
53
|
+
add_external_mpi_fields(post, options)
|
53
54
|
add_stored_credential(post, options)
|
54
|
-
action = if post[:cavv]
|
55
|
+
action = if post[:cavv] || options[:three_d_secure]
|
55
56
|
'cavv_preauth'
|
56
57
|
elsif post[:data_key].blank?
|
57
58
|
'preauth'
|
58
59
|
else
|
59
60
|
'res_preauth_cc'
|
60
61
|
end
|
61
|
-
commit(action, post)
|
62
|
+
commit(action, post, options)
|
62
63
|
end
|
63
64
|
|
64
65
|
# This action verifies funding on a customer's card and readies them for
|
@@ -73,15 +74,16 @@ module ActiveMerchant #:nodoc:
|
|
73
74
|
post[:order_id] = options[:order_id]
|
74
75
|
post[:address] = options[:billing_address] || options[:address]
|
75
76
|
post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
|
77
|
+
add_external_mpi_fields(post, options)
|
76
78
|
add_stored_credential(post, options)
|
77
|
-
action = if post[:cavv]
|
79
|
+
action = if post[:cavv] || options[:three_d_secure]
|
78
80
|
'cavv_purchase'
|
79
81
|
elsif post[:data_key].blank?
|
80
82
|
'purchase'
|
81
83
|
else
|
82
84
|
'res_purchase_cc'
|
83
85
|
end
|
84
|
-
commit(action, post)
|
86
|
+
commit(action, post, options)
|
85
87
|
end
|
86
88
|
|
87
89
|
# This method retrieves locked funds from a customer's account (from a
|
@@ -203,6 +205,21 @@ module ActiveMerchant #:nodoc:
|
|
203
205
|
sprintf('%.4i', creditcard.year)[-2..-1] + sprintf('%.2i', creditcard.month)
|
204
206
|
end
|
205
207
|
|
208
|
+
def add_external_mpi_fields(post, options)
|
209
|
+
# See these pages:
|
210
|
+
# https://developer.moneris.com/livedemo/3ds2/cavv_purchase/tool/php
|
211
|
+
# https://developer.moneris.com/livedemo/3ds2/cavv_preauth/guide/php
|
212
|
+
return unless options[:three_d_secure]
|
213
|
+
|
214
|
+
three_d_secure_options = options[:three_d_secure]
|
215
|
+
|
216
|
+
post[:threeds_version] = three_d_secure_options[:version]
|
217
|
+
post[:crypt_type] = three_d_secure_options[:eci]
|
218
|
+
post[:cavv] = three_d_secure_options[:cavv]
|
219
|
+
post[:threeds_server_trans_id] = three_d_secure_options[:three_ds_server_trans_id]
|
220
|
+
post[:ds_trans_id] = three_d_secure_options[:ds_transaction_id]
|
221
|
+
end
|
222
|
+
|
206
223
|
def add_payment_source(post, payment_method, options)
|
207
224
|
if payment_method.is_a?(String)
|
208
225
|
post[:data_key] = payment_method
|
@@ -291,14 +308,16 @@ module ActiveMerchant #:nodoc:
|
|
291
308
|
end
|
292
309
|
end
|
293
310
|
|
294
|
-
def commit(action, parameters = {})
|
311
|
+
def commit(action, parameters = {}, options = {})
|
312
|
+
threed_ds_transaction = options[:three_d_secure].present?
|
313
|
+
|
295
314
|
data = post_data(action, parameters)
|
296
315
|
url = test? ? self.test_url : self.live_url
|
297
316
|
raw = ssl_post(url, data)
|
298
317
|
response = parse(raw)
|
299
318
|
|
300
319
|
Response.new(
|
301
|
-
successful?(response),
|
320
|
+
successful?(action, response, threed_ds_transaction),
|
302
321
|
message_from(response[:message]),
|
303
322
|
response,
|
304
323
|
test: test?,
|
@@ -314,8 +333,16 @@ module ActiveMerchant #:nodoc:
|
|
314
333
|
end
|
315
334
|
|
316
335
|
# Tests for a successful response from Moneris' servers
|
317
|
-
def successful?(response)
|
318
|
-
|
336
|
+
def successful?(action, response, threed_ds_transaction = false)
|
337
|
+
# See 9.4 CAVV Result Codes in https://developer.moneris.com/livedemo/3ds2/reference/guide/php
|
338
|
+
cavv_accepted = if threed_ds_transaction
|
339
|
+
response[:cavv_result_code] && response[:cavv_result_code] == '2'
|
340
|
+
else
|
341
|
+
true
|
342
|
+
end
|
343
|
+
|
344
|
+
cavv_accepted &&
|
345
|
+
response[:response_code] &&
|
319
346
|
response[:complete] &&
|
320
347
|
(0..49).cover?(response[:response_code].to_i)
|
321
348
|
end
|
@@ -276,14 +276,14 @@ module ActiveMerchant #:nodoc:
|
|
276
276
|
end
|
277
277
|
|
278
278
|
Response.new(
|
279
|
-
success_from(response),
|
279
|
+
success_from(response, action),
|
280
280
|
message_from(response),
|
281
281
|
response,
|
282
282
|
authorization: authorization_from(response, action),
|
283
283
|
avs_result: AVSResult.new(code: response['some_avs_response_key']),
|
284
284
|
cvv_result: CVVResult.new(response['some_cvv_response_key']),
|
285
285
|
test: test?,
|
286
|
-
error_code: error_code_from(response)
|
286
|
+
error_code: error_code_from(response, action)
|
287
287
|
)
|
288
288
|
rescue ResponseError => e
|
289
289
|
message = get_error_messages(e)
|
@@ -297,8 +297,10 @@ module ActiveMerchant #:nodoc:
|
|
297
297
|
)
|
298
298
|
end
|
299
299
|
|
300
|
-
def success_from(response)
|
301
|
-
|
300
|
+
def success_from(response, action)
|
301
|
+
success = response.try(:[], 'last_transaction').try(:[], 'success') unless action == 'store'
|
302
|
+
success = !response.try(:[], 'id').nil? if action == 'store'
|
303
|
+
success
|
302
304
|
end
|
303
305
|
|
304
306
|
def message_from(response)
|
@@ -350,8 +352,8 @@ module ActiveMerchant #:nodoc:
|
|
350
352
|
parameters.to_json
|
351
353
|
end
|
352
354
|
|
353
|
-
def error_code_from(response)
|
354
|
-
return if success_from(response)
|
355
|
+
def error_code_from(response, action)
|
356
|
+
return if success_from(response, action)
|
355
357
|
return response['last_transaction']['acquirer_return_code'] if response['last_transaction']
|
356
358
|
|
357
359
|
STANDARD_ERROR_CODE[:processing_error]
|