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,308 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PlexoGateway < Gateway
|
4
|
+
self.test_url = 'https://api.testing.plexo.com.uy/v1/payments'
|
5
|
+
self.live_url = 'https://api.plexo.com.uy/v1/payments'
|
6
|
+
|
7
|
+
self.supported_countries = ['UY']
|
8
|
+
self.default_currency = 'UYU'
|
9
|
+
self.supported_cardtypes = %i[visa master american_express discover passcard edenred anda tarjeta-d]
|
10
|
+
|
11
|
+
self.homepage_url = 'https://www.plexo.com.uy'
|
12
|
+
self.display_name = 'Plexo'
|
13
|
+
|
14
|
+
APPENDED_URLS = %w(captures refunds cancellations verify)
|
15
|
+
AMOUNT_IN_RESPONSE = %w(authonly purchase /verify)
|
16
|
+
APPROVED_STATUS = %w(approved authorized)
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
requires!(options, :client_id, :api_key)
|
20
|
+
@credentials = options
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def purchase(money, payment, options = {})
|
25
|
+
post = {}
|
26
|
+
build_auth_purchase_request(money, post, payment, options)
|
27
|
+
|
28
|
+
commit('purchase', post, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def authorize(money, payment, options = {})
|
32
|
+
post = {}
|
33
|
+
build_auth_purchase_request(money, post, payment, options)
|
34
|
+
add_capture_type(post, options)
|
35
|
+
|
36
|
+
commit('authonly', post, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def capture(money, authorization, options = {})
|
40
|
+
post = {}
|
41
|
+
post[:ReferenceId] = options[:reference_id] || generate_unique_id
|
42
|
+
post[:Amount] = amount(money)
|
43
|
+
|
44
|
+
commit("/#{authorization}/captures", post, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def refund(money, authorization, options = {})
|
48
|
+
post = {}
|
49
|
+
post[:ReferenceId] = options[:reference_id] || generate_unique_id
|
50
|
+
post[:Type] = options[:refund_type] || 'refund'
|
51
|
+
post[:Description] = options[:description]
|
52
|
+
post[:Reason] = options[:reason]
|
53
|
+
post[:Amount] = amount(money)
|
54
|
+
|
55
|
+
commit("/#{authorization}/refunds", post, options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def void(authorization, options = {})
|
59
|
+
post = {}
|
60
|
+
post[:ReferenceId] = options[:reference_id] || generate_unique_id
|
61
|
+
post[:Description] = options[:description]
|
62
|
+
post[:Reason] = options[:reason]
|
63
|
+
|
64
|
+
commit("/#{authorization}/cancellations", post, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def verify(credit_card, options = {})
|
68
|
+
post = {}
|
69
|
+
post[:ReferenceId] = options[:reference_id] || generate_unique_id
|
70
|
+
post[:MerchantId] = options[:merchant_id] || @credentials[:merchant_id]
|
71
|
+
post[:StatementDescriptor] = options[:statement_descriptor] if options[:statement_descriptor]
|
72
|
+
post[:CustomerId] = options[:customer_id] if options[:customer_id]
|
73
|
+
money = options[:verify_amount].to_i || 100
|
74
|
+
|
75
|
+
add_payment_method(post, credit_card, options)
|
76
|
+
add_metadata(post, options[:metadata])
|
77
|
+
add_amount(money, post, options)
|
78
|
+
add_browser_details(post, options)
|
79
|
+
|
80
|
+
commit('/verify', post, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def supports_scrubbing?
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
def scrub(transcript)
|
88
|
+
transcript.
|
89
|
+
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
90
|
+
gsub(%r(("Number\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
91
|
+
gsub(%r(("Cvc\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
92
|
+
gsub(%r(("InvoiceNumber\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
93
|
+
gsub(%r(("MerchantId\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]')
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def encoded_credentials
|
99
|
+
Base64.encode64("#{@credentials[:client_id]}:#{@credentials[:api_key]}").delete("\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_auth_purchase_request(money, post, payment, options)
|
103
|
+
post[:ReferenceId] = options[:reference_id] || generate_unique_id
|
104
|
+
post[:MerchantId] = options[:merchant_id] || @credentials[:merchant_id]
|
105
|
+
post[:Installments] = options[:installments] if options[:installments]
|
106
|
+
post[:StatementDescriptor] = options[:statement_descriptor] if options[:statement_descriptor]
|
107
|
+
post[:CustomerId] = options[:customer_id] if options[:customer_id]
|
108
|
+
|
109
|
+
add_payment_method(post, payment, options)
|
110
|
+
add_items(post, options[:items])
|
111
|
+
add_metadata(post, options[:metadata])
|
112
|
+
add_amount(money, post, options)
|
113
|
+
add_browser_details(post, options)
|
114
|
+
end
|
115
|
+
|
116
|
+
def header(parameters = {})
|
117
|
+
{
|
118
|
+
'Content-Type' => 'application/json',
|
119
|
+
'Authorization' => "Basic #{encoded_credentials}"
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def add_capture_type(post, options)
|
124
|
+
post[:Capture] = {}
|
125
|
+
post[:Capture][:Method] = options.dig(:capture_type, :method) || 'manual'
|
126
|
+
end
|
127
|
+
|
128
|
+
def add_items(post, items)
|
129
|
+
return unless items&.kind_of?(Array)
|
130
|
+
|
131
|
+
post[:Items] = []
|
132
|
+
|
133
|
+
items.each do |option_item|
|
134
|
+
item = {}
|
135
|
+
item[:ReferenceId] = option_item[:reference_id] || generate_unique_id
|
136
|
+
item[:Name] = option_item[:name] if option_item[:name]
|
137
|
+
item[:Description] = option_item[:description] if option_item[:description]
|
138
|
+
item[:Quantity] = option_item[:quantity] if option_item[:quantity]
|
139
|
+
item[:Price] = option_item[:price] if option_item[:price]
|
140
|
+
item[:Discount] = option_item[:discount] if option_item[:discount]
|
141
|
+
|
142
|
+
post[:Items].append(item)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_metadata(post, metadata)
|
147
|
+
return unless metadata&.kind_of?(Hash)
|
148
|
+
|
149
|
+
metadata.transform_keys! { |key| key.to_s.camelize.to_sym }
|
150
|
+
post[:Metadata] = metadata
|
151
|
+
end
|
152
|
+
|
153
|
+
def add_amount(money, post, amount_options)
|
154
|
+
post[:Amount] = {}
|
155
|
+
|
156
|
+
post[:Amount][:Currency] = amount_options[:currency] || self.default_currency
|
157
|
+
post[:Amount][:Total] = amount(money)
|
158
|
+
post[:Amount][:Details] = {}
|
159
|
+
add_amount_details(post[:Amount][:Details], amount_options[:amount_details]) if amount_options[:amount_details]
|
160
|
+
end
|
161
|
+
|
162
|
+
def add_amount_details(amount_details, options)
|
163
|
+
return unless options
|
164
|
+
|
165
|
+
amount_details[:TaxedAmount] = options[:taxed_amount] if options[:taxed_amount]
|
166
|
+
amount_details[:TipAmount] = options[:tip_amount] if options[:tip_amount]
|
167
|
+
amount_details[:DiscountAmount] = options[:discount_amount] if options[:discount_amount]
|
168
|
+
amount_details[:TaxableAmount] = options[:taxable_amount] if options[:taxable_amount]
|
169
|
+
add_tax(amount_details, options[:tax])
|
170
|
+
end
|
171
|
+
|
172
|
+
def add_tax(post, tax)
|
173
|
+
return unless tax
|
174
|
+
|
175
|
+
post[:Tax] = {}
|
176
|
+
post[:Tax][:Type] = tax[:type] if tax[:type]
|
177
|
+
post[:Tax][:Amount] = tax[:amount] if tax[:amount]
|
178
|
+
post[:Tax][:Rate] = tax[:rate] if tax[:rate]
|
179
|
+
end
|
180
|
+
|
181
|
+
def add_browser_details(post, browser_details)
|
182
|
+
return unless browser_details
|
183
|
+
|
184
|
+
post[:BrowserDetails] = {}
|
185
|
+
post[:BrowserDetails][:DeviceFingerprint] = browser_details[:finger_print] if browser_details[:finger_print]
|
186
|
+
post[:BrowserDetails][:IpAddress] = browser_details[:ip] if browser_details[:ip]
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_payment_method(post, payment, options)
|
190
|
+
post[:paymentMethod] = {}
|
191
|
+
|
192
|
+
if payment&.is_a?(CreditCard)
|
193
|
+
post[:paymentMethod][:type] = 'card'
|
194
|
+
post[:paymentMethod][:Card] = {}
|
195
|
+
post[:paymentMethod][:Card][:Number] = payment.number
|
196
|
+
post[:paymentMethod][:Card][:ExpMonth] = format(payment.month, :two_digits) if payment.month
|
197
|
+
post[:paymentMethod][:Card][:ExpYear] = format(payment.year, :two_digits) if payment.year
|
198
|
+
post[:paymentMethod][:Card][:Cvc] = payment.verification_value if payment.verification_value
|
199
|
+
|
200
|
+
add_card_holder(post[:paymentMethod][:Card], payment, options)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def add_card_holder(card, payment, options)
|
205
|
+
requires!(options, :email)
|
206
|
+
|
207
|
+
cardholder = {}
|
208
|
+
cardholder[:FirstName] = payment.first_name if payment.first_name
|
209
|
+
cardholder[:LastName] = payment.last_name if payment.last_name
|
210
|
+
cardholder[:Email] = options[:email]
|
211
|
+
cardholder[:Birthdate] = options[:cardholder_birthdate] if options[:cardholder_birthdate]
|
212
|
+
cardholder[:Identification] = {}
|
213
|
+
cardholder[:Identification][:Type] = options[:identification_type] if options[:identification_type]
|
214
|
+
cardholder[:Identification][:Value] = options[:identification_value] if options[:identification_value]
|
215
|
+
add_billing_address(cardholder, options)
|
216
|
+
|
217
|
+
card[:Cardholder] = cardholder
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_billing_address(cardholder, options)
|
221
|
+
return unless address = options[:billing_address]
|
222
|
+
|
223
|
+
cardholder[:BillingAddress] = {}
|
224
|
+
cardholder[:BillingAddress][:City] = address[:city]
|
225
|
+
cardholder[:BillingAddress][:Country] = address[:country]
|
226
|
+
cardholder[:BillingAddress][:Line1] = address[:address1]
|
227
|
+
cardholder[:BillingAddress][:Line2] = address[:address2]
|
228
|
+
cardholder[:BillingAddress][:PostalCode] = address[:zip]
|
229
|
+
cardholder[:BillingAddress][:State] = address[:state]
|
230
|
+
end
|
231
|
+
|
232
|
+
def parse(body)
|
233
|
+
return {} if body == ''
|
234
|
+
|
235
|
+
JSON.parse(body)
|
236
|
+
end
|
237
|
+
|
238
|
+
def build_url(action, base)
|
239
|
+
url = base
|
240
|
+
url += action if APPENDED_URLS.any? { |key| action.include?(key) }
|
241
|
+
url
|
242
|
+
end
|
243
|
+
|
244
|
+
def get_authorization_from_url(url)
|
245
|
+
url.split('/')[1]
|
246
|
+
end
|
247
|
+
|
248
|
+
def reorder_amount_fields(response)
|
249
|
+
return response unless response['amount']
|
250
|
+
|
251
|
+
amount_obj = response['amount']
|
252
|
+
response['amount'] = amount_obj['total'].to_i if amount_obj['total']
|
253
|
+
response['currency'] = amount_obj['currency'] if amount_obj['currency']
|
254
|
+
response['amount_details'] = amount_obj['details'] if amount_obj['details']
|
255
|
+
response
|
256
|
+
end
|
257
|
+
|
258
|
+
def commit(action, parameters, options = {})
|
259
|
+
base_url = (test? ? test_url : live_url)
|
260
|
+
url = build_url(action, base_url)
|
261
|
+
response = parse(ssl_post(url, parameters.to_json, header(options)))
|
262
|
+
response = reorder_amount_fields(response) if AMOUNT_IN_RESPONSE.include?(action)
|
263
|
+
|
264
|
+
Response.new(
|
265
|
+
success_from(response),
|
266
|
+
message_from(response),
|
267
|
+
response,
|
268
|
+
authorization: authorization_from(response, action),
|
269
|
+
test: test?,
|
270
|
+
error_code: error_code_from(response)
|
271
|
+
)
|
272
|
+
end
|
273
|
+
|
274
|
+
def handle_response(response)
|
275
|
+
case response.code.to_i
|
276
|
+
when 200...300, 400, 401
|
277
|
+
response.body
|
278
|
+
else
|
279
|
+
raise ResponseError.new(response)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def success_from(response)
|
284
|
+
APPROVED_STATUS.include?(response['status'])
|
285
|
+
end
|
286
|
+
|
287
|
+
def message_from(response)
|
288
|
+
response = response['transactions']&.first if response['transactions']&.is_a?(Array)
|
289
|
+
response['resultMessage'] || response['message']
|
290
|
+
end
|
291
|
+
|
292
|
+
def authorization_from(response, action = nil)
|
293
|
+
if action.include?('captures')
|
294
|
+
get_authorization_from_url(action)
|
295
|
+
else
|
296
|
+
response['id']
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def error_code_from(response)
|
301
|
+
return if success_from(response)
|
302
|
+
|
303
|
+
response = response['transactions']&.first if response['transactions']&.is_a?(Array)
|
304
|
+
response['resultCode'] || response['status']
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
@@ -27,12 +27,12 @@ module ActiveMerchant #:nodoc:
|
|
27
27
|
self.display_name = 'Priority'
|
28
28
|
|
29
29
|
def initialize(options = {})
|
30
|
-
requires!(options, :merchant_id, :
|
30
|
+
requires!(options, :merchant_id, :api_key, :secret)
|
31
31
|
super
|
32
32
|
end
|
33
33
|
|
34
34
|
def basic_auth
|
35
|
-
Base64.strict_encode64("#{@options[:
|
35
|
+
Base64.strict_encode64("#{@options[:api_key]}:#{@options[:secret]}")
|
36
36
|
end
|
37
37
|
|
38
38
|
def request_headers
|
@@ -72,6 +72,18 @@ module ActiveMerchant #:nodoc:
|
|
72
72
|
commit('purchase', params: params)
|
73
73
|
end
|
74
74
|
|
75
|
+
def credit(amount, credit_card, options = {})
|
76
|
+
params = {}
|
77
|
+
params['authOnly'] = false
|
78
|
+
params['isSettleFunds'] = true
|
79
|
+
amount = -amount
|
80
|
+
|
81
|
+
add_merchant_id(params)
|
82
|
+
add_amount(params, amount, options)
|
83
|
+
add_credit_params(params, credit_card, options)
|
84
|
+
commit('credit', params: params)
|
85
|
+
end
|
86
|
+
|
75
87
|
def refund(amount, authorization, options = {})
|
76
88
|
params = {}
|
77
89
|
add_merchant_id(params)
|
@@ -147,6 +159,12 @@ module ActiveMerchant #:nodoc:
|
|
147
159
|
add_additional_data(params, options)
|
148
160
|
end
|
149
161
|
|
162
|
+
def add_credit_params(params, credit_card, options)
|
163
|
+
add_replay_id(params, options)
|
164
|
+
add_credit_card(params, credit_card, 'purchase', options)
|
165
|
+
add_additional_data(params, options)
|
166
|
+
end
|
167
|
+
|
150
168
|
def add_replay_id(params, options)
|
151
169
|
params['replayId'] = options[:replay_id] if options[:replay_id]
|
152
170
|
end
|
@@ -157,13 +175,12 @@ module ActiveMerchant #:nodoc:
|
|
157
175
|
card_details = {}
|
158
176
|
card_details['expiryMonth'] = format(credit_card.month, :two_digits).to_s
|
159
177
|
card_details['expiryYear'] = format(credit_card.year, :two_digits).to_s
|
160
|
-
card_details['expiryDate'] = exp_date(credit_card)
|
161
178
|
card_details['cardType'] = credit_card.brand
|
162
179
|
card_details['last4'] = credit_card.last_digits
|
163
|
-
card_details['cvv'] = credit_card.verification_value
|
180
|
+
card_details['cvv'] = credit_card.verification_value unless credit_card.verification_value.nil?
|
164
181
|
card_details['number'] = credit_card.number
|
165
182
|
card_details['avsStreet'] = options[:billing_address][:address1] if options[:billing_address]
|
166
|
-
card_details['avsZip'] = options[:billing_address][:zip] if options[:billing_address]
|
183
|
+
card_details['avsZip'] = options[:billing_address][:zip] if !options[:billing_address].nil? && !options[:billing_address][:zip].nil?
|
167
184
|
|
168
185
|
params['cardAccount'] = card_details
|
169
186
|
end
|
@@ -181,11 +198,17 @@ module ActiveMerchant #:nodoc:
|
|
181
198
|
params['shouldGetCreditCardLevel'] = options[:should_get_credit_card_level] if options[:should_get_credit_card_level]
|
182
199
|
params['source'] = options[:source] if options[:source]
|
183
200
|
params['invoice'] = options[:invoice] if options[:invoice]
|
201
|
+
params['isTicket'] = options[:is_ticket] if options[:is_ticket]
|
202
|
+
params['shouldVaultCard'] = options[:should_vault_card] if options[:should_vault_card]
|
203
|
+
params['sourceZip'] = options[:source_zip] if options[:source_zip]
|
204
|
+
params['authCode'] = options[:auth_code] if options[:auth_code]
|
205
|
+
params['achIndicator'] = options[:ach_indicator] if options[:ach_indicator]
|
206
|
+
params['bankAccount'] = options[:bank_account] if options[:bank_account]
|
207
|
+
params['meta'] = options[:meta] if options[:meta]
|
184
208
|
end
|
185
209
|
|
186
210
|
def add_pos_data(params, options)
|
187
211
|
pos_data = {}
|
188
|
-
|
189
212
|
pos_data['cardholderPresence'] = options.dig(:pos_data, :cardholder_presence) || 'Ecom'
|
190
213
|
pos_data['deviceAttendance'] = options.dig(:pos_data, :device_attendance) || 'HomePc'
|
191
214
|
pos_data['deviceInputCapability'] = options.dig(:pos_data, :device_input_capability) || 'Unknown'
|
@@ -4,13 +4,15 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.test_url = 'https://sandboxapi.rapyd.net/v1/'
|
5
5
|
self.live_url = 'https://api.rapyd.net/v1/'
|
6
6
|
|
7
|
-
self.supported_countries = %w(
|
7
|
+
self.supported_countries = %w(CA CL CO DO SV PE PT VI AU HK IN ID JP MY NZ PH SG KR TW TH VN AD AT BE BA BG HR CY CZ DK EE FI FR GE DE GI GR GL HU IS IE IL IT LV LI LT LU MK MT MD MC ME NL GB NO PL RO RU SM SK SI ZA ES SE CH TR VA)
|
8
8
|
self.default_currency = 'USD'
|
9
9
|
self.supported_cardtypes = %i[visa master american_express discover]
|
10
10
|
|
11
11
|
self.homepage_url = 'https://www.rapyd.net/'
|
12
12
|
self.display_name = 'Rapyd Gateway'
|
13
13
|
|
14
|
+
USA_PAYMENT_METHODS = %w[us_debit_discover_card us_debit_mastercard_card us_debit_visa_card us_ach_bank]
|
15
|
+
|
14
16
|
STANDARD_ERROR_CODE_MAPPING = {}
|
15
17
|
|
16
18
|
def initialize(options = {})
|
@@ -20,63 +22,58 @@ module ActiveMerchant #:nodoc:
|
|
20
22
|
|
21
23
|
def purchase(money, payment, options = {})
|
22
24
|
post = {}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
add_ewallet(post, options)
|
28
|
-
post[:capture] = true if payment_is_card?(options)
|
29
|
-
|
30
|
-
if payment_is_ach?(options)
|
31
|
-
MultiResponse.run do |r|
|
32
|
-
r.process { commit(:post, 'payments', post) }
|
33
|
-
post = {}
|
34
|
-
post[:token] = r.authorization
|
35
|
-
post[:param2] = r.params.dig('data', 'original_amount').to_s
|
36
|
-
r.process { commit(:post, 'payments/completePayment', post) }
|
37
|
-
end
|
38
|
-
else
|
39
|
-
commit(:post, 'payments', post)
|
40
|
-
end
|
25
|
+
add_auth_purchase(post, money, payment, options)
|
26
|
+
post[:capture] = true unless payment.is_a?(Check)
|
27
|
+
|
28
|
+
commit(:post, 'payments', post)
|
41
29
|
end
|
42
30
|
|
43
31
|
def authorize(money, payment, options = {})
|
44
32
|
post = {}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
add_metadata(post, options)
|
49
|
-
add_ewallet(post, options)
|
50
|
-
post[:capture] = false
|
33
|
+
add_auth_purchase(post, money, payment, options)
|
34
|
+
post[:capture] = false unless payment.is_a?(Check)
|
35
|
+
|
51
36
|
commit(:post, 'payments', post)
|
52
37
|
end
|
53
38
|
|
54
39
|
def capture(money, authorization, options = {})
|
55
40
|
post = {}
|
56
|
-
commit(:post, "payments/#{authorization}/capture", post)
|
41
|
+
commit(:post, "payments/#{add_reference(authorization)}/capture", post)
|
57
42
|
end
|
58
43
|
|
59
44
|
def refund(money, authorization, options = {})
|
60
45
|
post = {}
|
61
|
-
post[:payment] = authorization
|
46
|
+
post[:payment] = add_reference(authorization)
|
62
47
|
add_invoice(post, money, options)
|
63
48
|
add_metadata(post, options)
|
49
|
+
add_ewallet(post, options)
|
50
|
+
|
64
51
|
commit(:post, 'refunds', post)
|
65
52
|
end
|
66
53
|
|
67
54
|
def void(authorization, options = {})
|
68
55
|
post = {}
|
69
|
-
commit(:delete, "payments/#{authorization}", post)
|
56
|
+
commit(:delete, "payments/#{add_reference(authorization)}", post)
|
70
57
|
end
|
71
58
|
|
72
|
-
# Gateway returns an error if trying to run a $0 auth as invalid payment amount
|
73
|
-
# Gateway does not support void on a card transaction and refunds can only be done on completed transactions
|
74
|
-
# (such as a purchase). Authorize transactions are considered 'active' and not 'complete' until they are captured.
|
75
59
|
def verify(credit_card, options = {})
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
60
|
+
authorize(0, credit_card, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def store(payment, options = {})
|
64
|
+
post = {}
|
65
|
+
add_payment(post, payment, options)
|
66
|
+
add_customer_object(post, payment, options)
|
67
|
+
add_metadata(post, options)
|
68
|
+
add_ewallet(post, options)
|
69
|
+
add_payment_fields(post, options)
|
70
|
+
add_payment_urls(post, options)
|
71
|
+
add_address(post, payment, options)
|
72
|
+
commit(:post, 'customers', post)
|
73
|
+
end
|
74
|
+
|
75
|
+
def unstore(customer)
|
76
|
+
commit(:delete, "customers/#{add_reference(customer)}", {})
|
80
77
|
end
|
81
78
|
|
82
79
|
def supports_scrubbing?
|
@@ -87,25 +84,34 @@ module ActiveMerchant #:nodoc:
|
|
87
84
|
transcript.
|
88
85
|
gsub(%r((Access_key: )\w+), '\1[FILTERED]').
|
89
86
|
gsub(%r(("number\\?":\\?")\d+), '\1[FILTERED]').
|
87
|
+
gsub(%r(("account_number\\?":\\?")\d+), '\1[FILTERED]').
|
88
|
+
gsub(%r(("routing_number\\?":\\?")\d+), '\1[FILTERED]').
|
90
89
|
gsub(%r(("cvv\\?":\\?")\d+), '\1[FILTERED]')
|
91
90
|
end
|
92
91
|
|
93
92
|
private
|
94
93
|
|
95
|
-
def
|
96
|
-
return unless
|
94
|
+
def add_reference(authorization)
|
95
|
+
return unless authorization
|
97
96
|
|
98
|
-
|
97
|
+
authorization.split('|')[0]
|
99
98
|
end
|
100
99
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
def add_auth_purchase(post, money, payment, options)
|
101
|
+
add_invoice(post, money, options)
|
102
|
+
add_payment(post, payment, options)
|
103
|
+
add_customer_object(post, payment, options)
|
104
|
+
add_3ds(post, payment, options)
|
105
|
+
add_address(post, payment, options)
|
106
|
+
add_metadata(post, options)
|
107
|
+
add_ewallet(post, options)
|
108
|
+
add_payment_fields(post, options)
|
109
|
+
add_payment_urls(post, options)
|
110
|
+
add_customer_id(post, options)
|
105
111
|
end
|
106
112
|
|
107
113
|
def add_address(post, creditcard, options)
|
108
|
-
return unless address = options[:
|
114
|
+
return unless address = options[:billing_address]
|
109
115
|
|
110
116
|
post[:address] = {}
|
111
117
|
# name and line_1 are required at the gateway
|
@@ -116,22 +122,31 @@ module ActiveMerchant #:nodoc:
|
|
116
122
|
post[:address][:state] = address[:state] if address[:state]
|
117
123
|
post[:address][:country] = address[:country] if address[:country]
|
118
124
|
post[:address][:zip] = address[:zip] if address[:zip]
|
119
|
-
post[:address][:phone_number] = address[:phone] if address[:phone]
|
125
|
+
post[:address][:phone_number] = address[:phone].gsub(/\D/, '') if address[:phone]
|
120
126
|
end
|
121
127
|
|
122
128
|
def add_invoice(post, money, options)
|
123
|
-
post[:amount] = amount(money).to_f.to_s
|
129
|
+
post[:amount] = money.zero? ? 0 : amount(money).to_f.to_s
|
124
130
|
post[:currency] = (options[:currency] || currency(money))
|
125
131
|
end
|
126
132
|
|
127
133
|
def add_payment(post, payment, options)
|
128
|
-
if
|
134
|
+
if payment.is_a?(CreditCard)
|
129
135
|
add_creditcard(post, payment, options)
|
130
|
-
elsif
|
136
|
+
elsif payment.is_a?(Check)
|
131
137
|
add_ach(post, payment, options)
|
138
|
+
else
|
139
|
+
add_token(post, payment, options)
|
132
140
|
end
|
133
141
|
end
|
134
142
|
|
143
|
+
def add_stored_credential(post, options)
|
144
|
+
return unless stored_credential = options[:stored_credential]
|
145
|
+
|
146
|
+
post[:payment_method][:fields][:network_reference_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
147
|
+
post[:initiation_type] = stored_credential[:reason_type] if stored_credential[:reason_type]
|
148
|
+
end
|
149
|
+
|
135
150
|
def add_creditcard(post, payment, options)
|
136
151
|
post[:payment_method] = {}
|
137
152
|
post[:payment_method][:fields] = {}
|
@@ -141,8 +156,10 @@ module ActiveMerchant #:nodoc:
|
|
141
156
|
pm_fields[:number] = payment.number
|
142
157
|
pm_fields[:expiration_month] = payment.month.to_s
|
143
158
|
pm_fields[:expiration_year] = payment.year.to_s
|
144
|
-
pm_fields[:cvv] = payment.verification_value.to_s
|
145
159
|
pm_fields[:name] = "#{payment.first_name} #{payment.last_name}"
|
160
|
+
pm_fields[:cvv] = payment.verification_value.to_s
|
161
|
+
|
162
|
+
add_stored_credential(post, options)
|
146
163
|
end
|
147
164
|
|
148
165
|
def add_ach(post, payment, options)
|
@@ -158,6 +175,24 @@ module ActiveMerchant #:nodoc:
|
|
158
175
|
post[:payment_method][:fields][:payment_purpose] = options[:payment_purpose] if options[:payment_purpose]
|
159
176
|
end
|
160
177
|
|
178
|
+
def add_token(post, payment, options)
|
179
|
+
return unless token = payment.split('|')[1]
|
180
|
+
|
181
|
+
post[:payment_method] = token
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_3ds(post, payment, options)
|
185
|
+
return unless three_d_secure = options[:three_d_secure]
|
186
|
+
|
187
|
+
post[:payment_method_options] = {}
|
188
|
+
post[:payment_method_options]['3d_required'] = three_d_secure[:required]
|
189
|
+
post[:payment_method_options]['3d_version'] = three_d_secure[:version]
|
190
|
+
post[:payment_method_options][:cavv] = three_d_secure[:cavv]
|
191
|
+
post[:payment_method_options][:eci] = three_d_secure[:eci]
|
192
|
+
post[:payment_method_options][:xid] = three_d_secure[:xid]
|
193
|
+
post[:payment_method_options][:ds_trans_id] = three_d_secure[:ds_transaction_id]
|
194
|
+
end
|
195
|
+
|
161
196
|
def add_metadata(post, options)
|
162
197
|
post[:metadata] = options[:metadata] if options[:metadata]
|
163
198
|
end
|
@@ -166,6 +201,30 @@ module ActiveMerchant #:nodoc:
|
|
166
201
|
post[:ewallet_id] = options[:ewallet_id] if options[:ewallet_id]
|
167
202
|
end
|
168
203
|
|
204
|
+
def add_payment_fields(post, options)
|
205
|
+
post[:payment] = {}
|
206
|
+
|
207
|
+
post[:payment][:description] = options[:description] if options[:description]
|
208
|
+
post[:payment][:statement_descriptor] = options[:statement_descriptor] if options[:statement_descriptor]
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_payment_urls(post, options)
|
212
|
+
post[:complete_payment_url] = options[:complete_payment_url] if options[:complete_payment_url]
|
213
|
+
post[:error_payment_url] = options[:error_payment_url] if options[:error_payment_url]
|
214
|
+
end
|
215
|
+
|
216
|
+
def add_customer_object(post, payment, options)
|
217
|
+
post[:name] = "#{payment.first_name} #{payment.last_name}" unless payment.is_a?(String)
|
218
|
+
phone = options.dig(:billing_address, :phone) .gsub(/\D/, '') unless options[:billing_address].nil?
|
219
|
+
post[:phone_number] = phone || options.dig(:customer, :phone_number)
|
220
|
+
post[:email] = options[:email] || options.dig(:customer, :email)
|
221
|
+
post[:addresses] = options.dig(:customer, :addresses) if USA_PAYMENT_METHODS.include?(options[:pm_type])
|
222
|
+
end
|
223
|
+
|
224
|
+
def add_customer_id(post, options)
|
225
|
+
post[:customer] = options[:customer_id] if options[:customer_id]
|
226
|
+
end
|
227
|
+
|
169
228
|
def parse(body)
|
170
229
|
return {} if body.empty? || body.nil?
|
171
230
|
|
@@ -238,7 +297,9 @@ module ActiveMerchant #:nodoc:
|
|
238
297
|
end
|
239
298
|
|
240
299
|
def authorization_from(response)
|
241
|
-
response.dig('data') ? response.dig('data', 'id') : response.dig('status', 'operation_id')
|
300
|
+
id = response.dig('data') ? response.dig('data', 'id') : response.dig('status', 'operation_id')
|
301
|
+
|
302
|
+
"#{id}|#{response.dig('data', 'default_payment_method')}"
|
242
303
|
end
|
243
304
|
|
244
305
|
def error_code_from(response)
|