activemerchant 1.121.0 → 1.125.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 +217 -0
- data/README.md +1 -1
- data/lib/active_merchant/billing/check.rb +13 -19
- data/lib/active_merchant/billing/credit_card.rb +13 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +24 -12
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/adyen.rb +75 -27
- data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -3
- 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 +33 -4
- data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +41 -6
- data/lib/active_merchant/billing/gateways/d_local.rb +12 -6
- data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +65 -30
- data/lib/active_merchant/billing/gateways/element.rb +22 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +130 -26
- data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +30 -0
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +6 -3
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
- data/lib/active_merchant/billing/gateways/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/moka.rb +290 -0
- data/lib/active_merchant/billing/gateways/monei.rb +228 -144
- data/lib/active_merchant/billing/gateways/mundipagg.rb +22 -11
- data/lib/active_merchant/billing/gateways/nmi.rb +29 -10
- data/lib/active_merchant/billing/gateways/orbital.rb +46 -8
- data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
- data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
- data/lib/active_merchant/billing/gateways/paymentez.rb +14 -2
- data/lib/active_merchant/billing/gateways/paysafe.rb +412 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +9 -4
- 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 +347 -0
- data/lib/active_merchant/billing/gateways/realex.rb +18 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
- data/lib/active_merchant/billing/gateways/safe_charge.rb +8 -2
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +115 -39
- 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 +21 -7
- data/lib/active_merchant/billing/gateways/vpos.rb +49 -6
- data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +226 -62
- 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/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +13 -3
@@ -0,0 +1,412 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PaysafeGateway < Gateway
|
4
|
+
self.test_url = 'https://api.test.paysafe.com'
|
5
|
+
self.live_url = 'https://api.paysafe.com'
|
6
|
+
|
7
|
+
self.supported_countries = %w(AL AT BE BA BG CA HR CY CZ DK EE FI FR DE GR HU IS IE IT LV LI LT LU MT ME NL MK NO PL PT RO RS SK SI ES SE CH TR GB US)
|
8
|
+
self.supported_cardtypes = %i[visa master american_express discover]
|
9
|
+
|
10
|
+
self.homepage_url = 'https://www.paysafe.com/'
|
11
|
+
self.display_name = 'Paysafe'
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
requires!(options, :username, :password, :account_id)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def purchase(money, payment, options = {})
|
19
|
+
post = {}
|
20
|
+
add_invoice(post, money, options)
|
21
|
+
add_payment(post, payment)
|
22
|
+
add_billing_address(post, options)
|
23
|
+
add_merchant_details(post, options)
|
24
|
+
add_airline_travel_details(post, options)
|
25
|
+
add_customer_data(post, payment, options) unless payment.is_a?(String)
|
26
|
+
add_three_d_secure(post, payment, options) if options[:three_d_secure]
|
27
|
+
add_stored_credential(post, options) if options[:stored_credential]
|
28
|
+
add_split_pay_details(post, options)
|
29
|
+
post[:settleWithAuth] = true
|
30
|
+
|
31
|
+
commit(:post, 'auths', post, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def authorize(money, payment, options = {})
|
35
|
+
post = {}
|
36
|
+
add_invoice(post, money, options)
|
37
|
+
add_payment(post, payment)
|
38
|
+
add_billing_address(post, options)
|
39
|
+
add_merchant_details(post, options)
|
40
|
+
add_customer_data(post, payment, options) unless payment.is_a?(String)
|
41
|
+
add_three_d_secure(post, payment, options) if options[:three_d_secure]
|
42
|
+
add_stored_credential(post, options) if options[:stored_credential]
|
43
|
+
|
44
|
+
commit(:post, 'auths', post, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def capture(money, authorization, options = {})
|
48
|
+
post = {}
|
49
|
+
add_invoice(post, money, options)
|
50
|
+
|
51
|
+
commit(:post, "auths/#{authorization}/settlements", post, options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def refund(money, authorization, options = {})
|
55
|
+
post = {}
|
56
|
+
add_invoice(post, money, options)
|
57
|
+
|
58
|
+
commit(:post, "settlements/#{authorization}/refunds", post, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def void(authorization, options = {})
|
62
|
+
post = {}
|
63
|
+
money = options[:amount]
|
64
|
+
add_invoice(post, money, options)
|
65
|
+
|
66
|
+
commit(:post, "auths/#{authorization}/voidauths", post, options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def credit(money, payment, options = {})
|
70
|
+
post = {}
|
71
|
+
add_invoice(post, money, options)
|
72
|
+
add_payment(post, payment)
|
73
|
+
|
74
|
+
commit(:post, 'standalonecredits', post, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
# This is a '$0 auth' done at a specific verification endpoint at the gateway
|
78
|
+
def verify(payment, options = {})
|
79
|
+
post = {}
|
80
|
+
add_payment(post, payment)
|
81
|
+
add_billing_address(post, options)
|
82
|
+
add_customer_data(post, payment, options) unless payment.is_a?(String)
|
83
|
+
|
84
|
+
commit(:post, 'verifications', post, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def store(payment, options = {})
|
88
|
+
post = {}
|
89
|
+
add_payment(post, payment)
|
90
|
+
add_address_for_vaulting(post, options)
|
91
|
+
add_profile_data(post, payment, options)
|
92
|
+
add_store_data(post, payment, options)
|
93
|
+
|
94
|
+
commit(:post, 'profiles', post, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
def unstore(pm_profile_id)
|
98
|
+
commit_for_unstore(:delete, "profiles/#{pm_profile_id}", nil, nil)
|
99
|
+
end
|
100
|
+
|
101
|
+
def supports_scrubbing?
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
def scrub(transcript)
|
106
|
+
transcript.
|
107
|
+
gsub(%r((Authorization: Basic )[a-zA-Z0-9:_]+), '\1[FILTERED]').
|
108
|
+
gsub(%r(("cardNum\\?":\\?")\d+), '\1[FILTERED]').
|
109
|
+
gsub(%r(("cvv\\?":\\?")\d+), '\1[FILTERED]')
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Customer data can be included in transactions where the payment method is a credit card
|
115
|
+
# but should not be sent when the payment method is a token
|
116
|
+
def add_customer_data(post, creditcard, options)
|
117
|
+
post[:profile] = {}
|
118
|
+
post[:profile][:firstName] = creditcard.first_name
|
119
|
+
post[:profile][:lastName] = creditcard.last_name
|
120
|
+
post[:profile][:email] = options[:email] if options[:email]
|
121
|
+
post[:customerIp] = options[:ip] if options[:ip]
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_billing_address(post, options)
|
125
|
+
return unless address = options[:billing_address] || options[:address]
|
126
|
+
|
127
|
+
post[:billingDetails] = {}
|
128
|
+
post[:billingDetails][:street] = address[:address1]
|
129
|
+
post[:billingDetails][:city] = address[:city]
|
130
|
+
post[:billingDetails][:state] = address[:state]
|
131
|
+
post[:billingDetails][:country] = address[:country]
|
132
|
+
post[:billingDetails][:zip] = address[:zip]
|
133
|
+
post[:billingDetails][:phone] = address[:phone]
|
134
|
+
end
|
135
|
+
|
136
|
+
# The add_address_for_vaulting method is applicable to the store method, as the APIs address
|
137
|
+
# object is formatted differently from the standard transaction billing address
|
138
|
+
def add_address_for_vaulting(post, options)
|
139
|
+
return unless address = options[:billing_address] || options[:address]
|
140
|
+
|
141
|
+
post[:card][:billingAddress] = {}
|
142
|
+
post[:card][:billingAddress][:street] = address[:address1]
|
143
|
+
post[:card][:billingAddress][:street2] = address[:address2]
|
144
|
+
post[:card][:billingAddress][:city] = address[:city]
|
145
|
+
post[:card][:billingAddress][:zip] = address[:zip]
|
146
|
+
post[:card][:billingAddress][:country] = address[:country]
|
147
|
+
post[:card][:billingAddress][:state] = address[:state] if address[:state]
|
148
|
+
end
|
149
|
+
|
150
|
+
# This data is specific to creating a profile at the gateway's vault level
|
151
|
+
def add_profile_data(post, payment, options)
|
152
|
+
post[:firstName] = payment.first_name
|
153
|
+
post[:lastName] = payment.last_name
|
154
|
+
post[:dateOfBirth] = {}
|
155
|
+
post[:dateOfBirth][:year] = options[:date_of_birth][:year]
|
156
|
+
post[:dateOfBirth][:month] = options[:date_of_birth][:month]
|
157
|
+
post[:dateOfBirth][:day] = options[:date_of_birth][:day]
|
158
|
+
post[:email] = options[:email] if options[:email]
|
159
|
+
post[:ip] = options[:ip] if options[:ip]
|
160
|
+
|
161
|
+
if options[:phone]
|
162
|
+
post[:phone] = options[:phone]
|
163
|
+
elsif address = options[:billing_address] || options[:address]
|
164
|
+
post[:phone] = address[:phone] if address[:phone]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def add_store_data(post, payment, options)
|
169
|
+
post[:merchantCustomerId] = options[:customer_id] || SecureRandom.hex(12)
|
170
|
+
post[:locale] = options[:locale] || 'en_US'
|
171
|
+
post[:card][:holderName] = payment.name
|
172
|
+
end
|
173
|
+
|
174
|
+
# Paysafe expects minor units so we are not calling amount method on money parameter
|
175
|
+
def add_invoice(post, money, options)
|
176
|
+
post[:amount] = money
|
177
|
+
end
|
178
|
+
|
179
|
+
def add_payment(post, payment)
|
180
|
+
if payment.is_a?(String)
|
181
|
+
post[:card] = {}
|
182
|
+
post[:card][:paymentToken] = payment
|
183
|
+
else
|
184
|
+
post[:card] = { cardExpiry: {} }
|
185
|
+
post[:card][:cardNum] = payment.number
|
186
|
+
post[:card][:cardExpiry][:month] = payment.month
|
187
|
+
post[:card][:cardExpiry][:year] = payment.year
|
188
|
+
post[:card][:cvv] = payment.verification_value
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def add_merchant_details(post, options)
|
193
|
+
return unless options[:merchant_descriptor]
|
194
|
+
|
195
|
+
post[:merchantDescriptor] = {}
|
196
|
+
post[:merchantDescriptor][:dynamicDescriptor] = options[:merchant_descriptor][:dynamic_descriptor] if options[:merchant_descriptor][:dynamic_descriptor]
|
197
|
+
post[:merchantDescriptor][:phone] = options[:merchant_descriptor][:phone] if options[:merchant_descriptor][:phone]
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_three_d_secure(post, payment, options)
|
201
|
+
three_d_secure = options[:three_d_secure]
|
202
|
+
|
203
|
+
post[:authentication] = {}
|
204
|
+
post[:authentication][:eci] = three_d_secure[:eci]
|
205
|
+
post[:authentication][:cavv] = three_d_secure[:cavv]
|
206
|
+
post[:authentication][:xid] = three_d_secure[:xid] if three_d_secure[:xid]
|
207
|
+
post[:authentication][:threeDSecureVersion] = three_d_secure[:version]
|
208
|
+
post[:authentication][:directoryServerTransactionId] = three_d_secure[:ds_transaction_id] unless payment.is_a?(String) || !mastercard?(payment)
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_airline_travel_details(post, options)
|
212
|
+
return unless options[:airline_travel_details]
|
213
|
+
|
214
|
+
post[:airlineTravelDetails] = {}
|
215
|
+
post[:airlineTravelDetails][:passengerName] = options[:airline_travel_details][:passenger_name] if options[:airline_travel_details][:passenger_name]
|
216
|
+
post[:airlineTravelDetails][:departureDate] = options[:airline_travel_details][:departure_date] if options[:airline_travel_details][:departure_date]
|
217
|
+
post[:airlineTravelDetails][:origin] = options[:airline_travel_details][:origin] if options[:airline_travel_details][:origin]
|
218
|
+
post[:airlineTravelDetails][:computerizedReservationSystem] = options[:airline_travel_details][:computerized_reservation_system] if options[:airline_travel_details][:computerized_reservation_system]
|
219
|
+
post[:airlineTravelDetails][:customerReferenceNumber] = options[:airline_travel_details][:customer_reference_number] if options[:airline_travel_details][:customer_reference_number]
|
220
|
+
|
221
|
+
add_ticket_details(post, options)
|
222
|
+
add_travel_agency_details(post, options)
|
223
|
+
add_trip_legs(post, options)
|
224
|
+
end
|
225
|
+
|
226
|
+
def add_ticket_details(post, options)
|
227
|
+
return unless ticket = options[:airline_travel_details][:ticket]
|
228
|
+
|
229
|
+
post[:airlineTravelDetails][:ticket] = {}
|
230
|
+
post[:airlineTravelDetails][:ticket][:ticketNumber] = ticket[:ticket_number] if ticket[:ticket_number]
|
231
|
+
post[:airlineTravelDetails][:ticket][:isRestrictedTicket] = ticket[:is_restricted_ticket] if ticket[:is_restricted_ticket]
|
232
|
+
end
|
233
|
+
|
234
|
+
def add_travel_agency_details(post, options)
|
235
|
+
return unless agency = options[:airline_travel_details][:travel_agency]
|
236
|
+
|
237
|
+
post[:airlineTravelDetails][:travelAgency] = {}
|
238
|
+
post[:airlineTravelDetails][:travelAgency][:name] = agency[:name] if agency[:name]
|
239
|
+
post[:airlineTravelDetails][:travelAgency][:code] = agency[:code] if agency[:code]
|
240
|
+
end
|
241
|
+
|
242
|
+
def add_trip_legs(post, options)
|
243
|
+
return unless trip_legs = options[:airline_travel_details][:trip_legs]
|
244
|
+
|
245
|
+
trip_legs_hash = {}
|
246
|
+
trip_legs.each.with_index(1) do |leg, i|
|
247
|
+
my_leg = "leg#{i}".to_sym
|
248
|
+
details = add_leg_details(my_leg, leg[1])
|
249
|
+
|
250
|
+
trip_legs_hash[my_leg] = details
|
251
|
+
end
|
252
|
+
post[:airlineTravelDetails][:tripLegs] = trip_legs_hash
|
253
|
+
end
|
254
|
+
|
255
|
+
def add_leg_details(obj, leg)
|
256
|
+
details = {}
|
257
|
+
add_flight_details(details, obj, leg)
|
258
|
+
details[:serviceClass] = leg[:service_class] if leg[:service_class]
|
259
|
+
details[:isStopOverAllowed] = leg[:is_stop_over_allowed] if leg[:is_stop_over_allowed]
|
260
|
+
details[:destination] = leg[:destination] if leg[:destination]
|
261
|
+
details[:fareBasis] = leg[:fare_basis] if leg[:fare_basis]
|
262
|
+
details[:departureDate] = leg[:departure_date] if leg[:departure_date]
|
263
|
+
|
264
|
+
details
|
265
|
+
end
|
266
|
+
|
267
|
+
def add_flight_details(details, obj, leg)
|
268
|
+
details[:flight] = {}
|
269
|
+
details[:flight][:carrierCode] = leg[:flight][:carrier_code] if leg[:flight][:carrier_code]
|
270
|
+
details[:flight][:flightNumber] = leg[:flight][:flight_number] if leg[:flight][:flight_number]
|
271
|
+
end
|
272
|
+
|
273
|
+
def add_split_pay_details(post, options)
|
274
|
+
return unless options[:split_pay]
|
275
|
+
|
276
|
+
split_pay = []
|
277
|
+
options[:split_pay].each do |pmnt|
|
278
|
+
split = {}
|
279
|
+
|
280
|
+
split[:linkedAccount] = pmnt[:linked_account]
|
281
|
+
split[:amount] = pmnt[:amount].to_i if pmnt[:amount]
|
282
|
+
split[:percent] = pmnt[:percent].to_i if pmnt[:percent]
|
283
|
+
|
284
|
+
split_pay << split
|
285
|
+
end
|
286
|
+
post[:splitpay] = split_pay
|
287
|
+
end
|
288
|
+
|
289
|
+
def add_stored_credential(post, options)
|
290
|
+
return unless options[:stored_credential]
|
291
|
+
|
292
|
+
post[:storedCredential] = {}
|
293
|
+
|
294
|
+
case options[:stored_credential][:initial_transaction]
|
295
|
+
when true
|
296
|
+
post[:storedCredential][:occurrence] = 'INITIAL'
|
297
|
+
when false
|
298
|
+
post[:storedCredential][:occurrence] = 'SUBSEQUENT'
|
299
|
+
end
|
300
|
+
|
301
|
+
case options[:stored_credential][:reason_type]
|
302
|
+
when 'recurring' || 'installment'
|
303
|
+
post[:storedCredential][:type] = 'RECURRING'
|
304
|
+
when 'unscheduled'
|
305
|
+
if options[:stored_credential][:initiator] == 'merchant'
|
306
|
+
post[:storedCredential][:type] = 'TOPUP'
|
307
|
+
elsif options[:stored_credential][:initiator] == 'cardholder'
|
308
|
+
post[:storedCredential][:type] = 'ADHOC'
|
309
|
+
else
|
310
|
+
return
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
post[:storedCredential][:initialTransactionId] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
|
315
|
+
end
|
316
|
+
|
317
|
+
def mastercard?(payment)
|
318
|
+
return false unless payment.respond_to?(:brand)
|
319
|
+
|
320
|
+
payment.brand == 'master'
|
321
|
+
end
|
322
|
+
|
323
|
+
def parse(body)
|
324
|
+
JSON.parse(body)
|
325
|
+
end
|
326
|
+
|
327
|
+
def commit(method, action, parameters, options)
|
328
|
+
url = url(action)
|
329
|
+
raw_response = ssl_request(method, url, post_data(parameters, options), headers)
|
330
|
+
response = parse(raw_response)
|
331
|
+
success = success_from(response)
|
332
|
+
|
333
|
+
Response.new(
|
334
|
+
success,
|
335
|
+
message_from(success, response),
|
336
|
+
response,
|
337
|
+
authorization: authorization_from(action, response),
|
338
|
+
avs_result: AVSResult.new(code: response['avsResponse']),
|
339
|
+
cvv_result: CVVResult.new(response['cvvVerification']),
|
340
|
+
test: test?,
|
341
|
+
error_code: success ? nil : error_code_from(response)
|
342
|
+
)
|
343
|
+
end
|
344
|
+
|
345
|
+
def commit_for_unstore(method, action, parameters, options)
|
346
|
+
url = url(action)
|
347
|
+
response = raw_ssl_request(method, url, post_data(parameters, options), headers)
|
348
|
+
success = true if response.code == '200'
|
349
|
+
|
350
|
+
Response.new(
|
351
|
+
success,
|
352
|
+
message: response.message
|
353
|
+
)
|
354
|
+
end
|
355
|
+
|
356
|
+
def headers
|
357
|
+
{
|
358
|
+
'Content-Type' => 'application/json',
|
359
|
+
'Authorization' => 'Basic ' + Base64.strict_encode64("#{@options[:username]}:#{@options[:password]}")
|
360
|
+
}
|
361
|
+
end
|
362
|
+
|
363
|
+
def url(action, options = {})
|
364
|
+
base_url = (test? ? test_url : live_url)
|
365
|
+
|
366
|
+
if action.include? 'profiles'
|
367
|
+
"#{base_url}/customervault/v1/#{action}"
|
368
|
+
else
|
369
|
+
"#{base_url}/cardpayments/v1/accounts/#{@options[:account_id]}/#{action}"
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
def success_from(response)
|
374
|
+
return false if response['status'] == 'FAILED' || response['error']
|
375
|
+
|
376
|
+
true
|
377
|
+
end
|
378
|
+
|
379
|
+
def message_from(success, response)
|
380
|
+
return response['status'] unless response['error']
|
381
|
+
|
382
|
+
"Error(s)- code:#{response['error']['code']}, message:#{response['error']['message']}"
|
383
|
+
end
|
384
|
+
|
385
|
+
def authorization_from(action, response)
|
386
|
+
if action == 'profiles'
|
387
|
+
response['cards'].first['paymentToken']
|
388
|
+
else
|
389
|
+
response['id']
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def post_data(parameters = {}, options = {})
|
394
|
+
return unless parameters.present?
|
395
|
+
|
396
|
+
parameters[:merchantRefNum] = options[:merchant_ref_num] || SecureRandom.hex(16).to_s
|
397
|
+
|
398
|
+
parameters.to_json
|
399
|
+
end
|
400
|
+
|
401
|
+
def error_code_from(response)
|
402
|
+
return unless response['error']
|
403
|
+
|
404
|
+
response['error']['code']
|
405
|
+
end
|
406
|
+
|
407
|
+
def handle_response(response)
|
408
|
+
response.body
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
@@ -17,6 +17,7 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
BRAND_MAP = {
|
18
18
|
'visa' => 'VISA',
|
19
19
|
'master' => 'MASTERCARD',
|
20
|
+
'maestro' => 'MASTERCARD',
|
20
21
|
'american_express' => 'AMEX',
|
21
22
|
'diners_club' => 'DINERS',
|
22
23
|
'naranja' => 'NARANJA',
|
@@ -208,7 +209,7 @@ module ActiveMerchant #:nodoc:
|
|
208
209
|
buyer[:merchantBuyerId] = buyer_hash[:merchant_buyer_id]
|
209
210
|
buyer[:cnpj] = buyer_hash[:cnpj] if @options[:payment_country] == 'BR'
|
210
211
|
buyer[:emailAddress] = buyer_hash[:email]
|
211
|
-
buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:
|
212
|
+
buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone_number] if options[:shipping_address]) || ''
|
212
213
|
buyer[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
|
213
214
|
else
|
214
215
|
buyer[:fullName] = payment_method.name.strip
|
@@ -217,7 +218,7 @@ module ActiveMerchant #:nodoc:
|
|
217
218
|
buyer[:merchantBuyerId] = options[:merchant_buyer_id]
|
218
219
|
buyer[:cnpj] = options[:cnpj] if @options[:payment_country] == 'BR'
|
219
220
|
buyer[:emailAddress] = options[:email]
|
220
|
-
buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:
|
221
|
+
buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone_number] if options[:shipping_address]) || ''
|
221
222
|
buyer[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
|
222
223
|
end
|
223
224
|
post[:transaction][:order][:buyer] = buyer
|
@@ -233,7 +234,7 @@ module ActiveMerchant #:nodoc:
|
|
233
234
|
shipping_address[:state] = address[:state]
|
234
235
|
shipping_address[:country] = address[:country]
|
235
236
|
shipping_address[:postalCode] = address[:zip]
|
236
|
-
shipping_address[:phone] = address[:
|
237
|
+
shipping_address[:phone] = address[:phone_number]
|
237
238
|
shipping_address
|
238
239
|
end
|
239
240
|
|
@@ -278,6 +279,10 @@ module ActiveMerchant #:nodoc:
|
|
278
279
|
Digest::MD5.hexdigest(signature_string)
|
279
280
|
end
|
280
281
|
|
282
|
+
def codensa_bin?(number)
|
283
|
+
number.start_with?('590712')
|
284
|
+
end
|
285
|
+
|
281
286
|
def add_payment_method(post, payment_method, options)
|
282
287
|
if payment_method.is_a?(String)
|
283
288
|
brand, token = split_authorization(payment_method)
|
@@ -295,7 +300,7 @@ module ActiveMerchant #:nodoc:
|
|
295
300
|
credit_card[:name] = payment_method.name.strip
|
296
301
|
credit_card[:processWithoutCvv2] = true if add_process_without_cvv2(payment_method, options)
|
297
302
|
post[:transaction][:creditCard] = credit_card
|
298
|
-
post[:transaction][:paymentMethod] = BRAND_MAP[payment_method.brand.to_s]
|
303
|
+
post[:transaction][:paymentMethod] = codensa_bin?(payment_method.number) ? 'CODENSA' : BRAND_MAP[payment_method.brand.to_s]
|
299
304
|
end
|
300
305
|
end
|
301
306
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class PaywayDotComGateway < Gateway
|
4
|
-
self.test_url = 'https://
|
5
|
-
self.live_url = 'https://
|
4
|
+
self.test_url = 'https://paywaywsdev.com/PaywayWS/Payment/CreditCard'
|
5
|
+
self.live_url = 'https://paywayws.com/PaywayWS/Payment/CreditCard'
|
6
6
|
|
7
7
|
self.supported_countries = %w[US CA]
|
8
8
|
self.default_currency = 'USD'
|
@@ -233,7 +233,7 @@ module ActiveMerchant #:nodoc:
|
|
233
233
|
|
234
234
|
return response['paywayCode'] + '-' + 'success' if success
|
235
235
|
|
236
|
-
response['paywayCode']
|
236
|
+
response['paywayCode']
|
237
237
|
end
|
238
238
|
|
239
239
|
def authorization_from(response)
|
@@ -6,8 +6,8 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
|
7
7
|
self.default_currency = 'AUD'
|
8
8
|
self.money_format = :cents
|
9
|
-
self.supported_countries =
|
10
|
-
self.supported_cardtypes = %i[visa master american_express]
|
9
|
+
self.supported_countries = %w(AU NZ)
|
10
|
+
self.supported_cardtypes = %i[visa master american_express diners_club discover jcb]
|
11
11
|
self.homepage_url = 'http://www.pinpayments.com/'
|
12
12
|
self.display_name = 'Pin Payments'
|
13
13
|
|
@@ -46,6 +46,17 @@ module ActiveMerchant #:nodoc:
|
|
46
46
|
commit(:post, 'customers', post, options)
|
47
47
|
end
|
48
48
|
|
49
|
+
# Unstore a customer and associated credit card.
|
50
|
+
def unstore(token)
|
51
|
+
customer_token =
|
52
|
+
if /cus_/.match?(token)
|
53
|
+
get_customer_token(token)
|
54
|
+
else
|
55
|
+
token
|
56
|
+
end
|
57
|
+
commit(:delete, "customers/#{CGI.escape(customer_token)}", {}, {})
|
58
|
+
end
|
59
|
+
|
49
60
|
# Refund a transaction
|
50
61
|
def refund(money, token, options = {})
|
51
62
|
commit(:post, "charges/#{CGI.escape(token)}/refunds", { amount: amount(money) }, options)
|
@@ -65,6 +76,11 @@ module ActiveMerchant #:nodoc:
|
|
65
76
|
commit(:put, "charges/#{CGI.escape(token)}/capture", { amount: amount(money) }, options)
|
66
77
|
end
|
67
78
|
|
79
|
+
# Voids a previously authorized charge.
|
80
|
+
def void(token, options = {})
|
81
|
+
commit(:put, "charges/#{CGI.escape(token)}/void", {}, options)
|
82
|
+
end
|
83
|
+
|
68
84
|
# Updates the credit card for the customer.
|
69
85
|
def update(token, creditcard, options = {})
|
70
86
|
post = {}
|
@@ -190,7 +206,9 @@ module ActiveMerchant #:nodoc:
|
|
190
206
|
body = parse(e.response.body)
|
191
207
|
end
|
192
208
|
|
193
|
-
if body
|
209
|
+
if body.nil?
|
210
|
+
no_content_response
|
211
|
+
elsif body['response']
|
194
212
|
success_response(body)
|
195
213
|
elsif body['error']
|
196
214
|
error_response(body)
|
@@ -220,6 +238,15 @@ module ActiveMerchant #:nodoc:
|
|
220
238
|
)
|
221
239
|
end
|
222
240
|
|
241
|
+
def no_content_response
|
242
|
+
Response.new(
|
243
|
+
true,
|
244
|
+
nil,
|
245
|
+
{},
|
246
|
+
test: test?
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
223
250
|
def unparsable_response(raw_response)
|
224
251
|
message = 'Invalid JSON response received from Pin Payments. Please contact support@pinpayments.com if you continue to receive this message.'
|
225
252
|
message += " (The raw response returned by the API was #{raw_response.inspect})"
|
@@ -235,7 +262,7 @@ module ActiveMerchant #:nodoc:
|
|
235
262
|
end
|
236
263
|
|
237
264
|
def parse(body)
|
238
|
-
JSON.parse(body)
|
265
|
+
JSON.parse(body) unless body.nil? || body.length == 0
|
239
266
|
end
|
240
267
|
|
241
268
|
def post_data(parameters = {})
|