activemerchant 1.119.0 → 1.124.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +216 -1
  3. data/README.md +4 -2
  4. data/lib/active_merchant/billing/check.rb +19 -12
  5. data/lib/active_merchant/billing/credit_card.rb +3 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +32 -14
  8. data/lib/active_merchant/billing/gateways/adyen.rb +94 -25
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -0
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +52 -8
  14. data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
  15. data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
  16. data/lib/active_merchant/billing/gateways/checkout_v2.rb +31 -0
  17. data/lib/active_merchant/billing/gateways/credorax.rb +15 -9
  18. data/lib/active_merchant/billing/gateways/cyber_source.rb +53 -6
  19. data/lib/active_merchant/billing/gateways/d_local.rb +9 -2
  20. data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
  21. data/lib/active_merchant/billing/gateways/elavon.rb +70 -28
  22. data/lib/active_merchant/billing/gateways/element.rb +2 -0
  23. data/lib/active_merchant/billing/gateways/forte.rb +12 -0
  24. data/lib/active_merchant/billing/gateways/global_collect.rb +24 -10
  25. data/lib/active_merchant/billing/gateways/hps.rb +55 -1
  26. data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
  27. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
  29. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  30. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  31. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  32. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  33. data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
  34. data/lib/active_merchant/billing/gateways/netbanx.rb +26 -2
  35. data/lib/active_merchant/billing/gateways/nmi.rb +27 -9
  36. data/lib/active_merchant/billing/gateways/orbital.rb +99 -59
  37. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  38. data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
  39. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  40. data/lib/active_merchant/billing/gateways/payeezy.rb +34 -6
  41. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  42. data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
  43. data/lib/active_merchant/billing/gateways/payment_express.rb +5 -5
  44. data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
  45. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  46. data/lib/active_merchant/billing/gateways/paysafe.rb +376 -0
  47. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
  48. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  49. data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
  50. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  51. data/lib/active_merchant/billing/gateways/redsys.rb +42 -24
  52. data/lib/active_merchant/billing/gateways/safe_charge.rb +25 -13
  53. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  54. data/lib/active_merchant/billing/gateways/stripe.rb +18 -8
  55. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +126 -48
  56. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  57. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  58. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  59. data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
  60. data/lib/active_merchant/billing/gateways/worldpay.rb +78 -18
  61. data/lib/active_merchant/billing/response.rb +4 -0
  62. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  63. data/lib/active_merchant/billing.rb +1 -0
  64. data/lib/active_merchant/version.rb +1 -1
  65. data/lib/certs/cacert.pem +1582 -2431
  66. metadata +11 -3
@@ -0,0 +1,290 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class MokaGateway < Gateway
4
+ self.test_url = 'https://service.refmoka.com'
5
+ self.live_url = 'https://service.moka.com'
6
+
7
+ self.supported_countries = %w[GB TR US]
8
+ self.default_currency = 'TRY'
9
+ self.money_format = :dollars
10
+ self.supported_cardtypes = %i[visa master american_express discover]
11
+
12
+ self.homepage_url = 'http://developer.moka.com/'
13
+ self.display_name = 'Moka'
14
+
15
+ ERROR_CODE_MAPPING = {
16
+ '000' => 'General error',
17
+ '001' => '3D Not authenticated',
18
+ '002' => 'Limit is insufficient',
19
+ '003' => 'Credit card number format is wrong',
20
+ '004' => 'General decline',
21
+ '005' => 'This process is invalid for the card owner',
22
+ '006' => 'Expiration date is wrong',
23
+ '007' => 'Invalid transaction',
24
+ '008' => 'Connection with the bank not established',
25
+ '009' => 'Undefined error code',
26
+ '010' => 'Bank SSL error',
27
+ '011' => 'Call the bank for the manual authentication',
28
+ '012' => 'Card info is wrong - Kart Number or CVV2',
29
+ '013' => '3D secure is not supported other than Visa MC cards',
30
+ '014' => 'Invalid account number',
31
+ '015' => 'CVV is wrong',
32
+ '016' => 'Authentication process is not present',
33
+ '017' => 'System error',
34
+ '018' => 'Stolen card',
35
+ '019' => 'Lost card',
36
+ '020' => 'Card with limited properties',
37
+ '021' => 'Timeout',
38
+ '022' => 'Invalid merchant',
39
+ '023' => 'False authentication',
40
+ '024' => '3D authorization is successful but the process cannot be completed',
41
+ '025' => '3D authorization failure',
42
+ '026' => 'Either the issuer bank or the card is not enrolled to the 3D process',
43
+ '027' => 'The bank did not allow the process',
44
+ '028' => 'Fraud suspect',
45
+ '029' => 'The card is closed to the e-commerce operations'
46
+ }
47
+
48
+ def initialize(options = {})
49
+ requires!(options, :dealer_code, :username, :password)
50
+ super
51
+ end
52
+
53
+ def purchase(money, payment, options = {})
54
+ post = {}
55
+ post[:PaymentDealerRequest] = {}
56
+ options[:pre_auth] = 0
57
+ add_auth_purchase(post, money, payment, options)
58
+ add_3ds_data(post, options) if options[:execute_threed]
59
+
60
+ action = options[:execute_threed] ? 'three_ds_purchase' : 'purchase'
61
+ commit(action, post)
62
+ end
63
+
64
+ def authorize(money, payment, options = {})
65
+ post = {}
66
+ post[:PaymentDealerRequest] = {}
67
+ options[:pre_auth] = 1
68
+ add_auth_purchase(post, money, payment, options)
69
+ add_3ds_data(post, options) if options[:execute_threed]
70
+
71
+ action = options[:execute_threed] ? 'three_ds_authorize' : 'authorize'
72
+ commit(action, post)
73
+ end
74
+
75
+ def capture(money, authorization, options = {})
76
+ post = {}
77
+ post[:PaymentDealerRequest] = {}
78
+ add_payment_dealer_authentication(post)
79
+ add_transaction_reference(post, authorization)
80
+ add_invoice(post, money, options)
81
+
82
+ commit('capture', post)
83
+ end
84
+
85
+ def refund(money, authorization, options = {})
86
+ post = {}
87
+ post[:PaymentDealerRequest] = {}
88
+ add_payment_dealer_authentication(post)
89
+ add_transaction_reference(post, authorization)
90
+ add_void_refund_reason(post)
91
+ add_amount(post, money)
92
+
93
+ commit('refund', post)
94
+ end
95
+
96
+ def void(authorization, options = {})
97
+ post = {}
98
+ post[:PaymentDealerRequest] = {}
99
+ add_payment_dealer_authentication(post)
100
+ add_transaction_reference(post, authorization)
101
+ add_void_refund_reason(post)
102
+
103
+ commit('void', post)
104
+ end
105
+
106
+ def verify(credit_card, options = {})
107
+ MultiResponse.run(:use_first_response) do |r|
108
+ r.process { authorize(100, credit_card, options) }
109
+ r.process(:ignore_result) { void(r.authorization, options) }
110
+ end
111
+ end
112
+
113
+ def supports_scrubbing?
114
+ true
115
+ end
116
+
117
+ def scrub(transcript)
118
+ transcript.
119
+ gsub(%r(("CardNumber\\?":\\?")[^"]*)i, '\1[FILTERED]').
120
+ gsub(%r(("CvcNumber\\?":\\?")[^"]*)i, '\1[FILTERED]').
121
+ gsub(%r(("DealerCode\\?":\\?"?)[^"?]*)i, '\1[FILTERED]').
122
+ gsub(%r(("Username\\?":\\?")[^"]*)i, '\1[FILTERED]').
123
+ gsub(%r(("Password\\?":\\?")[^"]*)i, '\1[FILTERED]').
124
+ gsub(%r(("CheckKey\\?":\\?")[^"]*)i, '\1[FILTERED]')
125
+ end
126
+
127
+ private
128
+
129
+ def add_auth_purchase(post, money, payment, options)
130
+ add_payment_dealer_authentication(post)
131
+ add_invoice(post, money, options)
132
+ add_payment(post, payment)
133
+ add_additional_auth_purchase_data(post, options)
134
+ add_additional_transaction_data(post, options)
135
+ add_buyer_information(post, payment, options)
136
+ add_basket_product(post, options[:basket_product]) if options[:basket_product]
137
+ end
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
+
145
+ def add_payment_dealer_authentication(post)
146
+ post[:PaymentDealerAuthentication] = {
147
+ DealerCode: @options[:dealer_code],
148
+ Username: @options[:username],
149
+ Password: @options[:password],
150
+ CheckKey: check_key
151
+ }
152
+ end
153
+
154
+ def check_key
155
+ str = "#{@options[:dealer_code]}MK#{@options[:username]}PD#{@options[:password]}"
156
+ Digest::SHA256.hexdigest(str)
157
+ end
158
+
159
+ def add_invoice(post, money, options)
160
+ post[:PaymentDealerRequest][:Amount] = amount(money) || 0
161
+ post[:PaymentDealerRequest][:Currency] = options[:currency] || 'TL'
162
+ end
163
+
164
+ def add_payment(post, card)
165
+ post[:PaymentDealerRequest][:CardHolderFullName] = card.name
166
+ post[:PaymentDealerRequest][:CardNumber] = card.number
167
+ post[:PaymentDealerRequest][:ExpMonth] = card.month.to_s.rjust(2, '0')
168
+ post[:PaymentDealerRequest][:ExpYear] = card.year
169
+ post[:PaymentDealerRequest][:CvcNumber] = card.verification_value || ''
170
+ end
171
+
172
+ def add_amount(post, money)
173
+ post[:PaymentDealerRequest][:Amount] = amount(money) || 0
174
+ end
175
+
176
+ def add_additional_auth_purchase_data(post, options)
177
+ post[:PaymentDealerRequest][:IsPreAuth] = options[:pre_auth]
178
+ post[:PaymentDealerRequest][:Description] = options[:description] if options[:description]
179
+ post[:PaymentDealerRequest][:InstallmentNumber] = options[:installment_number].to_i if options[:installment_number]
180
+ post[:SubMerchantName] = options[:sub_merchant_name] if options[:sub_merchant_name]
181
+ post[:IsPoolPayment] = options[:is_pool_payment] || 0
182
+ end
183
+
184
+ def add_buyer_information(post, card, options)
185
+ obj = {}
186
+
187
+ obj[:BuyerFullName] = card.name || ''
188
+ obj[:BuyerEmail] = options[:email] if options[:email]
189
+ obj[:BuyerAddress] = options[:billing_address][:address1] if options[:billing_address]
190
+ obj[:BuyerGsmNumber] = options[:billing_address][:phone] if options[:billing_address]
191
+
192
+ post[:PaymentDealerRequest][:BuyerInformation] = obj
193
+ end
194
+
195
+ def add_basket_product(post, basket_options)
196
+ basket = []
197
+
198
+ basket_options.each do |product|
199
+ obj = {}
200
+ obj[:ProductId] = product[:product_id] if product[:product_id]
201
+ obj[:ProductCode] = product[:product_code] if product[:product_code]
202
+ obj[:UnitPrice] = amount(product[:unit_price]) if product[:unit_price]
203
+ obj[:Quantity] = product[:quantity] if product[:quantity]
204
+ basket << obj
205
+ end
206
+
207
+ post[:PaymentDealerRequest][:BasketProduct] = basket
208
+ end
209
+
210
+ def add_additional_transaction_data(post, options)
211
+ post[:PaymentDealerRequest][:ClientIP] = options[:ip] if options[:ip]
212
+ post[:PaymentDealerRequest][:OtherTrxCode] = options[:order_id] if options[:order_id]
213
+ end
214
+
215
+ def add_transaction_reference(post, authorization)
216
+ post[:PaymentDealerRequest][:VirtualPosOrderId] = authorization
217
+ end
218
+
219
+ def add_void_refund_reason(post)
220
+ post[:PaymentDealerRequest][:VoidRefundReason] = 2
221
+ end
222
+
223
+ def commit(action, parameters)
224
+ response = parse(ssl_post(url(action), post_data(parameters), request_headers))
225
+ Response.new(
226
+ success_from(response),
227
+ message_from(response),
228
+ response,
229
+ authorization: authorization_from(response),
230
+ test: test?,
231
+ error_code: error_code_from(response)
232
+ )
233
+ end
234
+
235
+ def url(action)
236
+ host = (test? ? test_url : live_url)
237
+ endpoint = endpoint(action)
238
+
239
+ "#{host}/PaymentDealer/#{endpoint}"
240
+ end
241
+
242
+ def endpoint(action)
243
+ case action
244
+ when 'three_ds_authorize', 'three_ds_purchase'
245
+ 'DoDirectPaymentThreeD'
246
+ when 'purchase', 'authorize'
247
+ 'DoDirectPayment'
248
+ when 'capture'
249
+ 'DoCapture'
250
+ when 'void'
251
+ 'DoVoid'
252
+ when 'refund'
253
+ 'DoCreateRefundRequest'
254
+ end
255
+ end
256
+
257
+ def request_headers
258
+ { 'Content-Type' => 'application/json' }
259
+ end
260
+
261
+ def post_data(parameters = {})
262
+ JSON.generate(parameters)
263
+ end
264
+
265
+ def parse(body)
266
+ JSON.parse(body)
267
+ end
268
+
269
+ def success_from(response)
270
+ return response.dig('Data', 'IsSuccessful') if response.dig('Data', 'IsSuccessful').to_s.present?
271
+
272
+ response['ResultCode']&.casecmp('success') == 0
273
+ end
274
+
275
+ def message_from(response)
276
+ response.dig('Data', 'ResultMessage').presence || response['ResultCode']
277
+ end
278
+
279
+ def authorization_from(response)
280
+ response.dig('Data', 'VirtualPosOrderId')
281
+ end
282
+
283
+ def error_code_from(response)
284
+ codes = [response['ResultCode'], response.dig('Data', 'ResultCode')].flatten
285
+ codes.reject! { |code| code.blank? || code.casecmp('success').zero? }
286
+ codes.map { |code| ERROR_CODE_MAPPING[code] || code }.join(', ')
287
+ end
288
+ end
289
+ end
290
+ end