activemerchant 1.114.0 → 1.120.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +183 -0
  3. data/README.md +4 -2
  4. data/lib/active_merchant.rb +1 -1
  5. data/lib/active_merchant/billing/avs_result.rb +1 -1
  6. data/lib/active_merchant/billing/check.rb +10 -0
  7. data/lib/active_merchant/billing/compatibility.rb +3 -3
  8. data/lib/active_merchant/billing/credit_card.rb +3 -0
  9. data/lib/active_merchant/billing/credit_card_methods.rb +80 -15
  10. data/lib/active_merchant/billing/gateways/adyen.rb +44 -20
  11. data/lib/active_merchant/billing/gateways/allied_wallet.rb +7 -7
  12. data/lib/active_merchant/billing/gateways/authorize_net.rb +50 -12
  13. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +3 -4
  14. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +5 -1
  15. data/lib/active_merchant/billing/gateways/axcessms.rb +8 -9
  16. data/lib/active_merchant/billing/gateways/balanced.rb +4 -3
  17. data/lib/active_merchant/billing/gateways/bambora_apac.rb +7 -7
  18. data/lib/active_merchant/billing/gateways/bank_frick.rb +7 -7
  19. data/lib/active_merchant/billing/gateways/banwire.rb +1 -1
  20. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +6 -4
  21. data/lib/active_merchant/billing/gateways/beanstream.rb +3 -3
  22. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +4 -5
  23. data/lib/active_merchant/billing/gateways/blue_pay.rb +2 -3
  24. data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -18
  25. data/lib/active_merchant/billing/gateways/bogus.rb +19 -19
  26. data/lib/active_merchant/billing/gateways/borgun.rb +11 -11
  27. data/lib/active_merchant/billing/gateways/bpoint.rb +8 -8
  28. data/lib/active_merchant/billing/gateways/braintree.rb +1 -1
  29. data/lib/active_merchant/billing/gateways/braintree_blue.rb +60 -17
  30. data/lib/active_merchant/billing/gateways/bridge_pay.rb +7 -7
  31. data/lib/active_merchant/billing/gateways/cams.rb +8 -8
  32. data/lib/active_merchant/billing/gateways/card_connect.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/card_save.rb +1 -1
  34. data/lib/active_merchant/billing/gateways/card_stream.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/cardknox.rb +7 -7
  36. data/lib/active_merchant/billing/gateways/cardprocess.rb +1 -1
  37. data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
  38. data/lib/active_merchant/billing/gateways/cecabank.rb +5 -5
  39. data/lib/active_merchant/billing/gateways/cenpos.rb +10 -10
  40. data/lib/active_merchant/billing/gateways/checkout.rb +2 -2
  41. data/lib/active_merchant/billing/gateways/checkout_v2.rb +38 -20
  42. data/lib/active_merchant/billing/gateways/clearhaus.rb +7 -7
  43. data/lib/active_merchant/billing/gateways/commercegate.rb +1 -1
  44. data/lib/active_merchant/billing/gateways/conekta.rb +2 -2
  45. data/lib/active_merchant/billing/gateways/creditcall.rb +10 -10
  46. data/lib/active_merchant/billing/gateways/credorax.rb +39 -23
  47. data/lib/active_merchant/billing/gateways/ct_payment.rb +10 -10
  48. data/lib/active_merchant/billing/gateways/culqi.rb +9 -9
  49. data/lib/active_merchant/billing/gateways/cyber_source.rb +81 -39
  50. data/lib/active_merchant/billing/gateways/d_local.rb +12 -12
  51. data/lib/active_merchant/billing/gateways/data_cash.rb +2 -3
  52. data/lib/active_merchant/billing/gateways/decidir.rb +31 -10
  53. data/lib/active_merchant/billing/gateways/dibs.rb +8 -8
  54. data/lib/active_merchant/billing/gateways/digitzs.rb +5 -5
  55. data/lib/active_merchant/billing/gateways/ebanx.rb +9 -9
  56. data/lib/active_merchant/billing/gateways/efsnet.rb +2 -3
  57. data/lib/active_merchant/billing/gateways/elavon.rb +296 -225
  58. data/lib/active_merchant/billing/gateways/element.rb +8 -8
  59. data/lib/active_merchant/billing/gateways/evo_ca.rb +5 -6
  60. data/lib/active_merchant/billing/gateways/eway.rb +3 -4
  61. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -7
  62. data/lib/active_merchant/billing/gateways/eway_rapid.rb +19 -6
  63. data/lib/active_merchant/billing/gateways/exact.rb +8 -9
  64. data/lib/active_merchant/billing/gateways/ezic.rb +7 -7
  65. data/lib/active_merchant/billing/gateways/fat_zebra.rb +4 -4
  66. data/lib/active_merchant/billing/gateways/federated_canada.rb +2 -3
  67. data/lib/active_merchant/billing/gateways/first_giving.rb +1 -1
  68. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -6
  69. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +7 -7
  70. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +21 -10
  71. data/lib/active_merchant/billing/gateways/flo2cash.rb +8 -8
  72. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +1 -1
  73. data/lib/active_merchant/billing/gateways/forte.rb +26 -8
  74. data/lib/active_merchant/billing/gateways/global_collect.rb +35 -16
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +7 -7
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +9 -9
  77. data/lib/active_merchant/billing/gateways/hps.rb +72 -9
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +9 -4
  79. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +1 -1
  80. data/lib/active_merchant/billing/gateways/inspire.rb +3 -4
  81. data/lib/active_merchant/billing/gateways/instapay.rb +1 -2
  82. data/lib/active_merchant/billing/gateways/ipp.rb +5 -5
  83. data/lib/active_merchant/billing/gateways/iridium.rb +14 -15
  84. data/lib/active_merchant/billing/gateways/iveri.rb +7 -7
  85. data/lib/active_merchant/billing/gateways/ixopay.rb +7 -7
  86. data/lib/active_merchant/billing/gateways/jetpay.rb +1 -2
  87. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -5
  88. data/lib/active_merchant/billing/gateways/kushki.rb +6 -6
  89. data/lib/active_merchant/billing/gateways/latitude19.rb +14 -14
  90. data/lib/active_merchant/billing/gateways/linkpoint.rb +4 -5
  91. data/lib/active_merchant/billing/gateways/litle.rb +32 -16
  92. data/lib/active_merchant/billing/gateways/mastercard.rb +10 -10
  93. data/lib/active_merchant/billing/gateways/mercado_pago.rb +9 -9
  94. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +1 -2
  95. data/lib/active_merchant/billing/gateways/merchant_one.rb +1 -1
  96. data/lib/active_merchant/billing/gateways/merchant_partners.rb +10 -10
  97. data/lib/active_merchant/billing/gateways/merchant_ware.rb +5 -7
  98. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +4 -6
  99. data/lib/active_merchant/billing/gateways/mercury.rb +4 -4
  100. data/lib/active_merchant/billing/gateways/metrics_global.rb +4 -5
  101. data/lib/active_merchant/billing/gateways/micropayment.rb +8 -8
  102. data/lib/active_merchant/billing/gateways/migs.rb +3 -4
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +2 -4
  104. data/lib/active_merchant/billing/gateways/monei.rb +7 -7
  105. data/lib/active_merchant/billing/gateways/moneris.rb +4 -3
  106. data/lib/active_merchant/billing/gateways/money_movers.rb +2 -3
  107. data/lib/active_merchant/billing/gateways/mundipagg.rb +37 -10
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +2 -4
  109. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +7 -7
  110. data/lib/active_merchant/billing/gateways/net_registry.rb +1 -2
  111. data/lib/active_merchant/billing/gateways/netaxept.rb +6 -6
  112. data/lib/active_merchant/billing/gateways/netbanx.rb +45 -10
  113. data/lib/active_merchant/billing/gateways/netbilling.rb +4 -5
  114. data/lib/active_merchant/billing/gateways/network_merchants.rb +2 -3
  115. data/lib/active_merchant/billing/gateways/nmi.rb +21 -7
  116. data/lib/active_merchant/billing/gateways/ogone.rb +3 -3
  117. data/lib/active_merchant/billing/gateways/omise.rb +13 -13
  118. data/lib/active_merchant/billing/gateways/openpay.rb +3 -4
  119. data/lib/active_merchant/billing/gateways/opp.rb +9 -9
  120. data/lib/active_merchant/billing/gateways/optimal_payment.rb +2 -3
  121. data/lib/active_merchant/billing/gateways/orbital.rb +225 -105
  122. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +3 -4
  123. data/lib/active_merchant/billing/gateways/pagarme.rb +8 -8
  124. data/lib/active_merchant/billing/gateways/pago_facil.rb +2 -2
  125. data/lib/active_merchant/billing/gateways/pay_conex.rb +8 -8
  126. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -7
  127. data/lib/active_merchant/billing/gateways/pay_hub.rb +7 -8
  128. data/lib/active_merchant/billing/gateways/pay_junction.rb +2 -3
  129. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +9 -9
  130. data/lib/active_merchant/billing/gateways/pay_secure.rb +2 -3
  131. data/lib/active_merchant/billing/gateways/paybox_direct.rb +23 -1
  132. data/lib/active_merchant/billing/gateways/payeezy.rb +62 -20
  133. data/lib/active_merchant/billing/gateways/payex.rb +6 -7
  134. data/lib/active_merchant/billing/gateways/payflow.rb +1 -1
  135. data/lib/active_merchant/billing/gateways/payment_express.rb +11 -7
  136. data/lib/active_merchant/billing/gateways/paymentez.rb +26 -6
  137. data/lib/active_merchant/billing/gateways/paymill.rb +7 -7
  138. data/lib/active_merchant/billing/gateways/paypal.rb +10 -2
  139. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -0
  140. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -1
  141. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +1 -1
  142. data/lib/active_merchant/billing/gateways/payscout.rb +1 -2
  143. data/lib/active_merchant/billing/gateways/paystation.rb +3 -4
  144. data/lib/active_merchant/billing/gateways/payu_in.rb +3 -3
  145. data/lib/active_merchant/billing/gateways/payu_latam.rb +17 -10
  146. data/lib/active_merchant/billing/gateways/payway.rb +8 -9
  147. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  148. data/lib/active_merchant/billing/gateways/pin.rb +11 -0
  149. data/lib/active_merchant/billing/gateways/plugnpay.rb +1 -2
  150. data/lib/active_merchant/billing/gateways/pro_pay.rb +8 -8
  151. data/lib/active_merchant/billing/gateways/psigate.rb +2 -3
  152. data/lib/active_merchant/billing/gateways/psl_card.rb +1 -2
  153. data/lib/active_merchant/billing/gateways/qbms.rb +1 -2
  154. data/lib/active_merchant/billing/gateways/quantum.rb +1 -2
  155. data/lib/active_merchant/billing/gateways/quickbooks.rb +1 -1
  156. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +3 -4
  157. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -2
  158. data/lib/active_merchant/billing/gateways/qvalent.rb +31 -17
  159. data/lib/active_merchant/billing/gateways/realex.rb +1 -1
  160. data/lib/active_merchant/billing/gateways/redsys.rb +105 -9
  161. data/lib/active_merchant/billing/gateways/s5.rb +7 -7
  162. data/lib/active_merchant/billing/gateways/safe_charge.rb +51 -18
  163. data/lib/active_merchant/billing/gateways/sage.rb +3 -5
  164. data/lib/active_merchant/billing/gateways/sage_pay.rb +2 -3
  165. data/lib/active_merchant/billing/gateways/sallie_mae.rb +1 -2
  166. data/lib/active_merchant/billing/gateways/secure_net.rb +1 -2
  167. data/lib/active_merchant/billing/gateways/secure_pay.rb +3 -4
  168. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +2 -4
  169. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +1 -2
  170. data/lib/active_merchant/billing/gateways/securion_pay.rb +5 -6
  171. data/lib/active_merchant/billing/gateways/skip_jack.rb +2 -3
  172. data/lib/active_merchant/billing/gateways/smart_ps.rb +5 -6
  173. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +7 -7
  174. data/lib/active_merchant/billing/gateways/spreedly_core.rb +6 -6
  175. data/lib/active_merchant/billing/gateways/stripe.rb +18 -18
  176. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +91 -25
  177. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +3 -4
  178. data/lib/active_merchant/billing/gateways/telr.rb +8 -8
  179. data/lib/active_merchant/billing/gateways/trans_first.rb +2 -2
  180. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +12 -12
  181. data/lib/active_merchant/billing/gateways/transact_pro.rb +9 -9
  182. data/lib/active_merchant/billing/gateways/trust_commerce.rb +1 -2
  183. data/lib/active_merchant/billing/gateways/usa_epay.rb +1 -1
  184. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +32 -32
  185. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +3 -4
  186. data/lib/active_merchant/billing/gateways/vanco.rb +3 -3
  187. data/lib/active_merchant/billing/gateways/verifi.rb +1 -2
  188. data/lib/active_merchant/billing/gateways/viaklix.rb +1 -2
  189. data/lib/active_merchant/billing/gateways/visanet_peru.rb +10 -10
  190. data/lib/active_merchant/billing/gateways/vpos.rb +172 -0
  191. data/lib/active_merchant/billing/gateways/webpay.rb +2 -2
  192. data/lib/active_merchant/billing/gateways/wepay.rb +3 -2
  193. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -2
  194. data/lib/active_merchant/billing/gateways/worldpay.rb +43 -22
  195. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +14 -16
  196. data/lib/active_merchant/billing/gateways/worldpay_us.rb +7 -7
  197. data/lib/active_merchant/billing/response.rb +3 -2
  198. data/lib/active_merchant/country.rb +1 -1
  199. data/lib/active_merchant/network_connection_retries.rb +2 -2
  200. data/lib/active_merchant/post_data.rb +1 -1
  201. data/lib/active_merchant/posts_data.rb +1 -1
  202. data/lib/active_merchant/version.rb +1 -1
  203. data/lib/certs/cacert.pem +1582 -2431
  204. data/lib/support/ssl_verify.rb +2 -2
  205. data/lib/support/ssl_version.rb +2 -2
  206. metadata +5 -3
@@ -6,38 +6,38 @@ module ActiveMerchant #:nodoc:
6
6
 
7
7
  self.supported_countries = %w[AR BR CL CO MX PE UY TR]
8
8
  self.default_currency = 'USD'
9
- self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro naranja cabal]
9
+ self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro naranja cabal elo alia carnet]
10
10
 
11
11
  self.homepage_url = 'https://dlocal.com/'
12
12
  self.display_name = 'dLocal'
13
13
 
14
- def initialize(options={})
14
+ def initialize(options = {})
15
15
  requires!(options, :login, :trans_key, :secret_key)
16
16
  super
17
17
  end
18
18
 
19
- def purchase(money, payment, options={})
19
+ def purchase(money, payment, options = {})
20
20
  post = {}
21
21
  add_auth_purchase_params(post, money, payment, 'purchase', options)
22
22
 
23
23
  commit('purchase', post, options)
24
24
  end
25
25
 
26
- def authorize(money, payment, options={})
26
+ def authorize(money, payment, options = {})
27
27
  post = {}
28
28
  add_auth_purchase_params(post, money, payment, 'authorize', options)
29
29
 
30
30
  commit('authorize', post, options)
31
31
  end
32
32
 
33
- def capture(money, authorization, options={})
33
+ def capture(money, authorization, options = {})
34
34
  post = {}
35
35
  post[:authorization_id] = authorization
36
36
  add_invoice(post, money, options) if money
37
37
  commit('capture', post, options)
38
38
  end
39
39
 
40
- def refund(money, authorization, options={})
40
+ def refund(money, authorization, options = {})
41
41
  post = {}
42
42
  post[:payment_id] = authorization
43
43
  post[:notification_url] = options[:notification_url]
@@ -45,13 +45,13 @@ module ActiveMerchant #:nodoc:
45
45
  commit('refund', post, options)
46
46
  end
47
47
 
48
- def void(authorization, options={})
48
+ def void(authorization, options = {})
49
49
  post = {}
50
50
  post[:authorization_id] = authorization
51
51
  commit('void', post, options)
52
52
  end
53
53
 
54
- def verify(credit_card, options={})
54
+ def verify(credit_card, options = {})
55
55
  MultiResponse.run(:use_first_response) do |r|
56
56
  r.process { authorize(100, credit_card, options) }
57
57
  r.process(:ignore_result) { void(r.authorization, options) }
@@ -138,7 +138,7 @@ module ActiveMerchant #:nodoc:
138
138
  house.empty? ? nil : house
139
139
  end
140
140
 
141
- def add_card(post, card, action, options={})
141
+ def add_card(post, card, action, options = {})
142
142
  post[:card] = {}
143
143
  post[:card][:holder_name] = card.name
144
144
  post[:card][:expiration_month] = card.month
@@ -155,7 +155,7 @@ module ActiveMerchant #:nodoc:
155
155
  JSON.parse(body)
156
156
  end
157
157
 
158
- def commit(action, parameters, options={})
158
+ def commit(action, parameters, options = {})
159
159
  url = url(action, parameters, options)
160
160
  post = post_data(action, parameters)
161
161
  begin
@@ -202,7 +202,7 @@ module ActiveMerchant #:nodoc:
202
202
  code&.to_s
203
203
  end
204
204
 
205
- def url(action, parameters, options={})
205
+ def url(action, parameters, options = {})
206
206
  "#{(test? ? test_url : live_url)}/#{endpoint(action, parameters, options)}/"
207
207
  end
208
208
 
@@ -221,7 +221,7 @@ module ActiveMerchant #:nodoc:
221
221
  end
222
222
  end
223
223
 
224
- def headers(post, options={})
224
+ def headers(post, options = {})
225
225
  timestamp = Time.now.utc.iso8601
226
226
  headers = {
227
227
  'Content-Type' => 'application/json',
@@ -262,8 +262,7 @@ module ActiveMerchant
262
262
 
263
263
  Response.new(response[:status] == '1', response[:reason], response,
264
264
  test: test?,
265
- authorization: "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}"
266
- )
265
+ authorization: "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}")
267
266
  end
268
267
 
269
268
  def format_date(month, year)
@@ -296,7 +295,7 @@ module ActiveMerchant
296
295
 
297
296
  def parse_authorization_string(authorization)
298
297
  reference, auth_code, ca_reference = authorization.to_s.split(';')
299
- {reference: reference, auth_code: auth_code, ca_reference: ca_reference}
298
+ { reference: reference, auth_code: auth_code, ca_reference: ca_reference }
300
299
  end
301
300
  end
302
301
  end
@@ -42,13 +42,13 @@ module ActiveMerchant #:nodoc:
42
42
  97 => STANDARD_ERROR_CODE[:processing_error]
43
43
  }
44
44
 
45
- def initialize(options={})
45
+ def initialize(options = {})
46
46
  requires!(options, :api_key)
47
47
  super
48
48
  @options[:preauth_mode] ||= false
49
49
  end
50
50
 
51
- def purchase(money, payment, options={})
51
+ def purchase(money, payment, options = {})
52
52
  raise ArgumentError, 'Purchase is not supported on Decidir gateways configured with the preauth_mode option' if @options[:preauth_mode]
53
53
 
54
54
  post = {}
@@ -56,7 +56,7 @@ module ActiveMerchant #:nodoc:
56
56
  commit(:post, 'payments', post)
57
57
  end
58
58
 
59
- def authorize(money, payment, options={})
59
+ def authorize(money, payment, options = {})
60
60
  raise ArgumentError, 'Authorize is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
61
61
 
62
62
  post = {}
@@ -64,7 +64,7 @@ module ActiveMerchant #:nodoc:
64
64
  commit(:post, 'payments', post)
65
65
  end
66
66
 
67
- def capture(money, authorization, options={})
67
+ def capture(money, authorization, options = {})
68
68
  raise ArgumentError, 'Capture is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
69
69
 
70
70
  post = {}
@@ -72,18 +72,18 @@ module ActiveMerchant #:nodoc:
72
72
  commit(:put, "payments/#{authorization}", post)
73
73
  end
74
74
 
75
- def refund(money, authorization, options={})
75
+ def refund(money, authorization, options = {})
76
76
  post = {}
77
77
  add_amount(post, money, options)
78
78
  commit(:post, "payments/#{authorization}/refunds", post)
79
79
  end
80
80
 
81
- def void(authorization, options={})
81
+ def void(authorization, options = {})
82
82
  post = {}
83
83
  commit(:post, "payments/#{authorization}/refunds", post)
84
84
  end
85
85
 
86
- def verify(credit_card, options={})
86
+ def verify(credit_card, options = {})
87
87
  raise ArgumentError, 'Verify is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
88
88
 
89
89
  MultiResponse.run(:use_first_response) do |r|
@@ -170,6 +170,12 @@ module ActiveMerchant #:nodoc:
170
170
  card_data[:security_code] = credit_card.verification_value if credit_card.verification_value?
171
171
  card_data[:card_holder_name] = credit_card.name if credit_card.name
172
172
 
173
+ # the device_unique_id has to be sent in via the card data (as device_unique_identifier) no other fraud detection fields require this
174
+ if options[:fraud_detection].present?
175
+ card_data[:fraud_detection] = {} if (options[:fraud_detection][:device_unique_id]).present?
176
+ card_data[:fraud_detection][:device_unique_identifier] = (options[:fraud_detection][:device_unique_id]) if (options[:fraud_detection][:device_unique_id]).present?
177
+ end
178
+
173
179
  # additional data used for Visa transactions
174
180
  card_data[:card_holder_door_number] = options[:card_holder_door_number].to_i if options[:card_holder_door_number]
175
181
  card_data[:card_holder_birthday] = options[:card_holder_birthday] if options[:card_holder_birthday]
@@ -209,6 +215,15 @@ module ActiveMerchant #:nodoc:
209
215
  hsh[:send_to_cs] = options[:send_to_cs] if valid_fraud_detection_option?(options[:send_to_cs]) # true/false
210
216
  hsh[:channel] = options[:channel] if valid_fraud_detection_option?(options[:channel])
211
217
  hsh[:dispatch_method] = options[:dispatch_method] if valid_fraud_detection_option?(options[:dispatch_method])
218
+ hsh[:csmdds] = options[:csmdds] if valid_fraud_detection_option?(options[:csmdds])
219
+ hsh[:device_unique_id] = options[:device_unique_id] if valid_fraud_detection_option?(options[:device_unique_id])
220
+ hsh[:bill_to] = options[:bill_to] if valid_fraud_detection_option?(options[:bill_to])
221
+ hsh[:purchase_totals] = options[:purchase_totals] if valid_fraud_detection_option?(options[:purchase_totals])
222
+ hsh[:customer_in_site] = options[:customer_in_site] if valid_fraud_detection_option?(options[:customer_in_site])
223
+ hsh[:retail_transaction_data] = options[:retail_transaction_data] if valid_fraud_detection_option?(options[:retail_transaction_data])
224
+ hsh[:ship_to] = options[:ship_to] if valid_fraud_detection_option?(options[:ship_to])
225
+ hsh[:tax_voucher_required] = options[:tax_voucher_required] if valid_fraud_detection_option?(options[:tax_voucher_required])
226
+ hsh[:copy_paste_card_data] = options[:copy_paste_card_data] if valid_fraud_detection_option?(options[:copy_paste_card_data])
212
227
  end
213
228
  end
214
229
 
@@ -225,7 +240,7 @@ module ActiveMerchant #:nodoc:
225
240
  }
226
241
  end
227
242
 
228
- def commit(method, endpoint, parameters, options={})
243
+ def commit(method, endpoint, parameters, options = {})
229
244
  url = "#{(test? ? test_url : live_url)}/#{endpoint}"
230
245
 
231
246
  begin
@@ -286,15 +301,21 @@ module ActiveMerchant #:nodoc:
286
301
  error_code = nil
287
302
  if error = response.dig('status_details', 'error')
288
303
  code = error.dig('reason', 'id')
289
- error_code = STANDARD_ERROR_CODE_MAPPING[code]
304
+ standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
305
+ error_code = "#{code}, #{standard_error_code}"
290
306
  error_code ||= error['type']
291
307
  elsif response['error_type']
292
308
  error_code = response['error_type'] if response['validation_errors']
293
- elsif error = response.dig('error')
309
+ elsif response.dig('error', 'validation_errors')
310
+ error = response.dig('error')
294
311
  validation_errors = error.dig('validation_errors', 0)
295
312
  code = validation_errors['code'] if validation_errors && validation_errors['code']
296
313
  param = validation_errors['param'] if validation_errors && validation_errors['param']
297
314
  error_code = "#{error['error_type']} | #{code} | #{param}" if error['error_type']
315
+ elsif error = response.dig('error')
316
+ code = error.dig('reason', 'id')
317
+ standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
318
+ error_code = "#{code}, #{standard_error_code}"
298
319
  end
299
320
 
300
321
  error_code || STANDARD_ERROR_CODE[:processing_error]
@@ -11,19 +11,19 @@ module ActiveMerchant #:nodoc:
11
11
  self.money_format = :cents
12
12
  self.supported_cardtypes = %i[visa master american_express discover]
13
13
 
14
- def initialize(options={})
14
+ def initialize(options = {})
15
15
  requires!(options, :merchant_id, :secret_key)
16
16
  super
17
17
  end
18
18
 
19
- def purchase(amount, payment_method, options={})
19
+ def purchase(amount, payment_method, options = {})
20
20
  MultiResponse.run(false) do |r|
21
21
  r.process { authorize(amount, payment_method, options) }
22
22
  r.process { capture(amount, r.authorization, options) }
23
23
  end
24
24
  end
25
25
 
26
- def authorize(amount, payment_method, options={})
26
+ def authorize(amount, payment_method, options = {})
27
27
  post = {}
28
28
  add_amount(post, amount)
29
29
  add_invoice(post, amount, options)
@@ -36,7 +36,7 @@ module ActiveMerchant #:nodoc:
36
36
  end
37
37
  end
38
38
 
39
- def capture(amount, authorization, options={})
39
+ def capture(amount, authorization, options = {})
40
40
  post = {}
41
41
  add_amount(post, amount)
42
42
  add_reference(post, authorization)
@@ -44,14 +44,14 @@ module ActiveMerchant #:nodoc:
44
44
  commit(:capture, post)
45
45
  end
46
46
 
47
- def void(authorization, options={})
47
+ def void(authorization, options = {})
48
48
  post = {}
49
49
  add_reference(post, authorization)
50
50
 
51
51
  commit(:void, post)
52
52
  end
53
53
 
54
- def refund(amount, authorization, options={})
54
+ def refund(amount, authorization, options = {})
55
55
  post = {}
56
56
  add_amount(post, amount)
57
57
  add_reference(post, authorization)
@@ -59,7 +59,7 @@ module ActiveMerchant #:nodoc:
59
59
  commit(:refund, post)
60
60
  end
61
61
 
62
- def verify(credit_card, options={})
62
+ def verify(credit_card, options = {})
63
63
  MultiResponse.run(:use_first_response) do |r|
64
64
  r.process { authorize(100, credit_card, options) }
65
65
  r.process(:ignore_result) { void(r.authorization, options) }
@@ -87,7 +87,7 @@ module ActiveMerchant #:nodoc:
87
87
 
88
88
  private
89
89
 
90
- CURRENCY_CODES = Hash.new { |h, k| raise ArgumentError.new("Unsupported currency: #{k}") }
90
+ CURRENCY_CODES = Hash.new { |_h, k| raise ArgumentError.new("Unsupported currency: #{k}") }
91
91
  CURRENCY_CODES['USD'] = '840'
92
92
  CURRENCY_CODES['DKK'] = '208'
93
93
  CURRENCY_CODES['NOK'] = '578'
@@ -14,19 +14,19 @@ module ActiveMerchant #:nodoc:
14
14
  self.homepage_url = 'https://digitzs.com'
15
15
  self.display_name = 'Digitzs'
16
16
 
17
- def initialize(options={})
17
+ def initialize(options = {})
18
18
  requires!(options, :app_key, :api_key)
19
19
  super
20
20
  end
21
21
 
22
- def purchase(money, payment, options={})
22
+ def purchase(money, payment, options = {})
23
23
  MultiResponse.run do |r|
24
24
  r.process { commit('auth/token', app_token_request(options)) }
25
25
  r.process { commit('payments', purchase_request(money, payment, options), options.merge({ app_token: app_token_from(r) })) }
26
26
  end
27
27
  end
28
28
 
29
- def refund(money, authorization, options={})
29
+ def refund(money, authorization, options = {})
30
30
  MultiResponse.run do |r|
31
31
  r.process { commit('auth/token', app_token_request(options)) }
32
32
  r.process { commit('payments', refund_request(money, authorization, options), options.merge({ app_token: app_token_from(r) })) }
@@ -151,7 +151,7 @@ module ActiveMerchant #:nodoc:
151
151
  post[:data][:type] = 'payments'
152
152
  post[:data][:attributes][:merchantId] = options[:merchant_id]
153
153
  post[:data][:attributes][:paymentType] = 'cardRefund'
154
- post[:data][:attributes][:originalTransaction] = {id: authorization}
154
+ post[:data][:attributes][:originalTransaction] = { id: authorization }
155
155
  add_transaction(post, money, options)
156
156
 
157
157
  post
@@ -206,7 +206,7 @@ module ActiveMerchant #:nodoc:
206
206
  JSON.parse(body)
207
207
  end
208
208
 
209
- def commit(action, parameters, options={})
209
+ def commit(action, parameters, options = {})
210
210
  url = (test? ? test_url : live_url)
211
211
  response = parse(ssl_post(url + "/#{action}", parameters.to_json, headers(options)))
212
212
 
@@ -46,12 +46,12 @@ module ActiveMerchant #:nodoc:
46
46
  'cl' => 5000
47
47
  }
48
48
 
49
- def initialize(options={})
49
+ def initialize(options = {})
50
50
  requires!(options, :integration_key)
51
51
  super
52
52
  end
53
53
 
54
- def purchase(money, payment, options={})
54
+ def purchase(money, payment, options = {})
55
55
  post = { payment: {} }
56
56
  add_integration_key(post)
57
57
  add_operation(post)
@@ -65,7 +65,7 @@ module ActiveMerchant #:nodoc:
65
65
  commit(:purchase, post)
66
66
  end
67
67
 
68
- def authorize(money, payment, options={})
68
+ def authorize(money, payment, options = {})
69
69
  post = { payment: {} }
70
70
  add_integration_key(post)
71
71
  add_operation(post)
@@ -80,7 +80,7 @@ module ActiveMerchant #:nodoc:
80
80
  commit(:authorize, post)
81
81
  end
82
82
 
83
- def capture(money, authorization, options={})
83
+ def capture(money, authorization, options = {})
84
84
  post = {}
85
85
  add_integration_key(post)
86
86
  post[:hash] = authorization
@@ -89,7 +89,7 @@ module ActiveMerchant #:nodoc:
89
89
  commit(:capture, post)
90
90
  end
91
91
 
92
- def refund(money, authorization, options={})
92
+ def refund(money, authorization, options = {})
93
93
  post = {}
94
94
  add_integration_key(post)
95
95
  add_operation(post)
@@ -100,7 +100,7 @@ module ActiveMerchant #:nodoc:
100
100
  commit(:refund, post)
101
101
  end
102
102
 
103
- def void(authorization, options={})
103
+ def void(authorization, options = {})
104
104
  post = {}
105
105
  add_integration_key(post)
106
106
  add_authorization(post, authorization)
@@ -108,7 +108,7 @@ module ActiveMerchant #:nodoc:
108
108
  commit(:void, post)
109
109
  end
110
110
 
111
- def store(credit_card, options={})
111
+ def store(credit_card, options = {})
112
112
  post = {}
113
113
  add_integration_key(post)
114
114
  add_payment_details(post, credit_card)
@@ -117,7 +117,7 @@ module ActiveMerchant #:nodoc:
117
117
  commit(:store, post)
118
118
  end
119
119
 
120
- def verify(credit_card, options={})
120
+ def verify(credit_card, options = {})
121
121
  MultiResponse.run(:use_first_response) do |r|
122
122
  r.process { authorize(VERIFY_AMOUNT_PER_COUNTRY[customer_country(options)], credit_card, options) }
123
123
  r.process(:ignore_result) { void(r.authorization, options) }
@@ -222,7 +222,7 @@ module ActiveMerchant #:nodoc:
222
222
 
223
223
  def commit(action, parameters)
224
224
  url = url_for((test? ? test_url : live_url), action, parameters)
225
- response = parse(ssl_request(HTTP_METHOD[action], url, post_data(action, parameters), {'x-ebanx-client-user-agent': "ActiveMerchant/#{ActiveMerchant::VERSION}"}))
225
+ response = parse(ssl_request(HTTP_METHOD[action], url, post_data(action, parameters), { 'x-ebanx-client-user-agent': "ActiveMerchant/#{ActiveMerchant::VERSION}" }))
226
226
 
227
227
  success = success_from(action, response)
228
228
 
@@ -54,7 +54,7 @@ module ActiveMerchant #:nodoc:
54
54
  def void(identification, options = {})
55
55
  requires!(options, :order_id)
56
56
  original_transaction_id, = identification.split(';')
57
- commit(:void_transaction, {reference_number: format_reference_number(options[:order_id]), transaction_id: original_transaction_id})
57
+ commit(:void_transaction, { reference_number: format_reference_number(options[:order_id]), transaction_id: original_transaction_id })
58
58
  end
59
59
 
60
60
  def voice_authorize(money, authorization_code, creditcard, options = {})
@@ -149,8 +149,7 @@ module ActiveMerchant #:nodoc:
149
149
  test: test?,
150
150
  authorization: authorization_from(response, parameters),
151
151
  avs_result: { code: response[:avs_response_code] },
152
- cvv_result: response[:cvv_response_code]
153
- )
152
+ cvv_result: response[:cvv_response_code])
154
153
  end
155
154
 
156
155
  def success?(response)
@@ -1,4 +1,5 @@
1
1
  require 'active_merchant/billing/gateways/viaklix'
2
+ require 'nokogiri'
2
3
 
3
4
  module ActiveMerchant #:nodoc:
4
5
  module Billing #:nodoc:
@@ -7,13 +8,15 @@ module ActiveMerchant #:nodoc:
7
8
 
8
9
  class_attribute :test_url, :live_url, :delimiter, :actions
9
10
 
10
- self.test_url = 'https://api.demo.convergepay.com/VirtualMerchantDemo/process.do'
11
- self.live_url = 'https://api.convergepay.com/VirtualMerchant/process.do'
11
+ self.test_url = 'https://api.demo.convergepay.com/VirtualMerchantDemo/processxml.do'
12
+ self.live_url = 'https://api.convergepay.com/VirtualMerchant/processxml.do'
12
13
 
13
14
  self.display_name = 'Elavon MyVirtualMerchant'
14
15
  self.supported_countries = %w(US CA PR DE IE NO PL LU BE NL MX)
15
16
  self.supported_cardtypes = %i[visa master american_express discover]
16
17
  self.homepage_url = 'http://www.elavon.com/'
18
+ self.money_format = :dollars
19
+ self.default_currency = 'USD'
17
20
 
18
21
  self.delimiter = "\n"
19
22
  self.actions = {
@@ -35,115 +38,153 @@ module ActiveMerchant #:nodoc:
35
38
  end
36
39
 
37
40
  def purchase(money, payment_method, options = {})
38
- form = {}
39
- add_salestax(form, options)
40
- add_invoice(form, options)
41
- if payment_method.is_a?(String)
42
- add_token(form, payment_method)
43
- else
44
- add_creditcard(form, payment_method)
41
+ request = build_xml_request do |xml|
42
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
43
+ xml.ssl_transaction_type self.actions[:purchase]
44
+ xml.ssl_amount amount(money)
45
+
46
+ if payment_method.is_a?(String)
47
+ add_token(xml, payment_method)
48
+ else
49
+ add_creditcard(xml, payment_method)
50
+ end
51
+
52
+ add_invoice(xml, options)
53
+ add_salestax(xml, options)
54
+ add_currency(xml, money, options)
55
+ add_address(xml, options)
56
+ add_customer_email(xml, options)
57
+ add_test_mode(xml, options)
58
+ add_ip(xml, options)
59
+ add_auth_purchase_params(xml, options)
60
+ add_level_3_fields(xml, options) if options[:level_3_data]
45
61
  end
46
- add_currency(form, money, options)
47
- add_address(form, options)
48
- add_customer_data(form, options)
49
- add_test_mode(form, options)
50
- add_ip(form, options)
51
- add_auth_purchase_params(form, options)
52
- add_level_3_fields(form, options) if options[:level_3_data]
53
- commit(:purchase, money, form, options)
62
+ commit(request)
54
63
  end
55
64
 
56
65
  def authorize(money, creditcard, options = {})
57
- form = {}
58
- add_salestax(form, options)
59
- add_invoice(form, options)
60
- add_creditcard(form, creditcard)
61
- add_currency(form, money, options)
62
- add_address(form, options)
63
- add_customer_data(form, options)
64
- add_test_mode(form, options)
65
- add_ip(form, options)
66
- add_auth_purchase_params(form, options)
67
- add_level_3_fields(form, options) if options[:level_3_data]
68
- commit(:authorize, money, form, options)
66
+ request = build_xml_request do |xml|
67
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
68
+ xml.ssl_transaction_type self.actions[:authorize]
69
+ xml.ssl_amount amount(money)
70
+
71
+ add_salestax(xml, options)
72
+ add_invoice(xml, options)
73
+ add_creditcard(xml, creditcard)
74
+ add_currency(xml, money, options)
75
+ add_address(xml, options)
76
+ add_customer_email(xml, options)
77
+ add_test_mode(xml, options)
78
+ add_ip(xml, options)
79
+ add_auth_purchase_params(xml, options)
80
+ add_level_3_fields(xml, options) if options[:level_3_data]
81
+ end
82
+ commit(request)
69
83
  end
70
84
 
71
85
  def capture(money, authorization, options = {})
72
- form = {}
73
- if options[:credit_card]
74
- action = :capture
75
- add_salestax(form, options)
76
- add_approval_code(form, authorization)
77
- add_invoice(form, options)
78
- add_creditcard(form, options[:credit_card])
79
- add_currency(form, money, options)
80
- add_address(form, options)
81
- add_customer_data(form, options)
82
- add_test_mode(form, options)
83
- else
84
- action = :capture_complete
85
- add_txn_id(form, authorization)
86
- add_partial_shipment_flag(form, options)
87
- add_test_mode(form, options)
86
+ request = build_xml_request do |xml|
87
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
88
+
89
+ if options[:credit_card]
90
+ xml.ssl_transaction_type self.actions[:capture]
91
+ xml.ssl_amount amount(money)
92
+ add_salestax(xml, options)
93
+ add_approval_code(xml, authorization)
94
+ add_invoice(xml, options)
95
+ add_creditcard(xml, options[:credit_card])
96
+ add_currency(xml, money, options)
97
+ add_address(xml, options)
98
+ add_customer_email(xml, options)
99
+ add_test_mode(xml, options)
100
+ else
101
+ xml.ssl_transaction_type self.actions[:capture_complete]
102
+ xml.ssl_amount amount(money)
103
+ add_currency(xml, money, options)
104
+ add_txn_id(xml, authorization)
105
+ add_partial_shipment_flag(xml, options)
106
+ add_test_mode(xml, options)
107
+ end
88
108
  end
89
- commit(action, money, form, options)
109
+ commit(request)
90
110
  end
91
111
 
92
112
  def refund(money, identification, options = {})
93
- form = {}
94
- add_txn_id(form, identification)
95
- add_test_mode(form, options)
96
- commit(:refund, money, form, options)
113
+ request = build_xml_request do |xml|
114
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
115
+ xml.ssl_transaction_type self.actions[:refund]
116
+ xml.ssl_amount amount(money)
117
+ add_txn_id(xml, identification)
118
+ add_test_mode(xml, options)
119
+ end
120
+ commit(request)
97
121
  end
98
122
 
99
123
  def void(identification, options = {})
100
- form = {}
101
- add_txn_id(form, identification)
102
- add_test_mode(form, options)
103
- commit(:void, nil, form, options)
124
+ request = build_xml_request do |xml|
125
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
126
+ xml.ssl_transaction_type self.actions[:void]
127
+
128
+ add_txn_id(xml, identification)
129
+ add_test_mode(xml, options)
130
+ end
131
+ commit(request)
104
132
  end
105
133
 
106
134
  def credit(money, creditcard, options = {})
107
135
  raise ArgumentError, 'Reference credits are not supported. Please supply the original credit card or use the #refund method.' if creditcard.is_a?(String)
108
136
 
109
- form = {}
110
- add_invoice(form, options)
111
- add_creditcard(form, creditcard)
112
- add_currency(form, money, options)
113
- add_address(form, options)
114
- add_customer_data(form, options)
115
- add_test_mode(form, options)
116
- commit(:credit, money, form, options)
137
+ request = build_xml_request do |xml|
138
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
139
+ xml.ssl_transaction_type self.actions[:credit]
140
+ xml.ssl_amount amount(money)
141
+ add_invoice(xml, options)
142
+ add_creditcard(xml, creditcard)
143
+ add_currency(xml, money, options)
144
+ add_address(xml, options)
145
+ add_customer_email(xml, options)
146
+ add_test_mode(xml, options)
147
+ end
148
+ commit(request)
117
149
  end
118
150
 
119
151
  def verify(credit_card, options = {})
120
- form = {}
121
- add_creditcard(form, credit_card)
122
- add_address(form, options)
123
- add_test_mode(form, options)
124
- add_ip(form, options)
125
- commit(:verify, 0, form, options)
152
+ request = build_xml_request do |xml|
153
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
154
+ xml.ssl_transaction_type self.actions[:verify]
155
+ add_creditcard(xml, credit_card)
156
+ add_address(xml, options)
157
+ add_test_mode(xml, options)
158
+ add_ip(xml, options)
159
+ end
160
+ commit(request)
126
161
  end
127
162
 
128
163
  def store(creditcard, options = {})
129
- form = {}
130
- add_creditcard(form, creditcard)
131
- add_address(form, options)
132
- add_customer_data(form, options)
133
- add_test_mode(form, options)
134
- add_verification(form, options)
135
- form[:add_token] = 'Y'
136
- commit(:store, nil, form, options)
164
+ request = build_xml_request do |xml|
165
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
166
+ xml.ssl_transaction_type self.actions[:store]
167
+ xml.ssl_add_token 'Y'
168
+ add_creditcard(xml, creditcard)
169
+ add_address(xml, options)
170
+ add_customer_email(xml, options)
171
+ add_test_mode(xml, options)
172
+ add_verification(xml, options)
173
+ end
174
+ commit(request)
137
175
  end
138
176
 
139
177
  def update(token, creditcard, options = {})
140
- form = {}
141
- add_token(form, token)
142
- add_creditcard(form, creditcard)
143
- add_address(form, options)
144
- add_customer_data(form, options)
145
- add_test_mode(form, options)
146
- commit(:update, nil, form, options)
178
+ request = build_xml_request do |xml|
179
+ xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id]
180
+ xml.ssl_transaction_type self.actions[:update]
181
+ add_token(xml, token)
182
+ add_creditcard(xml, creditcard)
183
+ add_address(xml, options)
184
+ add_customer_email(xml, options)
185
+ add_test_mode(xml, options)
186
+ end
187
+ commit(request)
147
188
  end
148
189
 
149
190
  def supports_scrubbing?
@@ -152,217 +193,247 @@ module ActiveMerchant #:nodoc:
152
193
 
153
194
  def scrub(transcript)
154
195
  transcript.
155
- gsub(%r((&?ssl_pin=)[^&]*)i, '\1[FILTERED]').
156
- gsub(%r((&?ssl_card_number=)[^&\\n\r\n]*)i, '\1[FILTERED]').
157
- gsub(%r((&?ssl_cvv2cvc2=)[^&]*)i, '\1[FILTERED]')
196
+ gsub(%r((<ssl_pin>)(.*)(</ssl_pin>)), '\1[FILTERED]\3').
197
+ gsub(%r((<ssl_card_number>)(.*)(</ssl_card_number>)), '\1[FILTERED]\3').
198
+ gsub(%r((<ssl_cvv2cvc2>)(.*)(</ssl_cvv2cvc2>)), '\1[FILTERED]\3')
158
199
  end
159
200
 
160
201
  private
161
202
 
162
- def add_invoice(form, options)
163
- form[:invoice_number] = truncate((options[:order_id] || options[:invoice]), 10)
164
- form[:description] = truncate(options[:description], 255)
203
+ def add_invoice(xml, options)
204
+ xml.ssl_invoice_number truncate((options[:order_id] || options[:invoice]), 25)
205
+ xml.ssl_description truncate(options[:description], 255)
165
206
  end
166
207
 
167
- def add_approval_code(form, authorization)
168
- form[:approval_code] = authorization.split(';').first
208
+ def add_approval_code(xml, authorization)
209
+ xml.ssl_approval_code authorization.split(';').first
169
210
  end
170
211
 
171
- def add_txn_id(form, authorization)
172
- form[:txn_id] = authorization.split(';').last
173
- end
174
-
175
- def authorization_from(response)
176
- [response['approval_code'], response['txn_id']].join(';')
212
+ def add_txn_id(xml, authorization)
213
+ xml.ssl_txn_id authorization.split(';').last
177
214
  end
178
215
 
179
- def add_creditcard(form, creditcard)
180
- form[:card_number] = creditcard.number
181
- form[:exp_date] = expdate(creditcard)
216
+ def add_creditcard(xml, creditcard)
217
+ xml.ssl_card_number creditcard.number
218
+ xml.ssl_exp_date expdate(creditcard)
182
219
 
183
- add_verification_value(form, creditcard) if creditcard.verification_value?
220
+ add_verification_value(xml, creditcard) if creditcard.verification_value?
184
221
 
185
- form[:first_name] = truncate(creditcard.first_name, 20)
186
- form[:last_name] = truncate(creditcard.last_name, 30)
222
+ xml.ssl_first_name truncate(creditcard.first_name, 20)
223
+ xml.ssl_last_name truncate(creditcard.last_name, 30)
187
224
  end
188
225
 
189
- def add_currency(form, money, options)
226
+ def add_currency(xml, money, options)
190
227
  currency = options[:currency] || currency(money)
191
- form[:transaction_currency] = currency if currency && (@options[:multi_currency] || options[:multi_currency])
228
+ return unless currency && (@options[:multi_currency] || options[:multi_currency])
229
+
230
+ xml.ssl_transaction_currency currency
192
231
  end
193
232
 
194
- def add_token(form, token)
195
- form[:token] = token
233
+ def add_token(xml, token)
234
+ xml.ssl_token token
196
235
  end
197
236
 
198
- def add_verification_value(form, creditcard)
199
- form[:cvv2cvc2] = creditcard.verification_value
200
- form[:cvv2cvc2_indicator] = '1'
237
+ def add_verification_value(xml, creditcard)
238
+ xml.ssl_cvv2cvc2 creditcard.verification_value
239
+ xml.ssl_cvv2cvc2_indicator 1
201
240
  end
202
241
 
203
- def add_customer_data(form, options)
204
- form[:email] = truncate(options[:email], 100) unless empty?(options[:email])
205
- form[:customer_code] = truncate(options[:customer], 10) unless empty?(options[:customer])
206
- form[:customer_number] = options[:customer_number] unless empty?(options[:customer_number])
207
- options[:custom_fields]&.each do |key, value|
208
- form[key.to_s] = value
209
- end
242
+ def add_customer_email(xml, options)
243
+ xml.ssl_email truncate(options[:email], 100) unless empty?(options[:email])
210
244
  end
211
245
 
212
- def add_salestax(form, options)
213
- form[:salestax] = options[:tax] if options[:tax].present?
246
+ def add_salestax(xml, options)
247
+ return unless options[:tax].present?
248
+
249
+ xml.ssl_salestax options[:tax]
214
250
  end
215
251
 
216
- def add_address(form, options)
252
+ def add_address(xml, options)
217
253
  billing_address = options[:billing_address] || options[:address]
218
254
 
219
255
  if billing_address
220
- form[:avs_address] = truncate(billing_address[:address1], 30)
221
- form[:address2] = truncate(billing_address[:address2], 30)
222
- form[:avs_zip] = truncate(billing_address[:zip].to_s.gsub(/[^a-zA-Z0-9]/, ''), 9)
223
- form[:city] = truncate(billing_address[:city], 30)
224
- form[:state] = truncate(billing_address[:state], 10)
225
- form[:company] = truncate(billing_address[:company], 50)
226
- form[:phone] = truncate(billing_address[:phone], 20)
227
- form[:country] = truncate(billing_address[:country], 50)
256
+ xml.ssl_avs_address truncate(billing_address[:address1], 30)
257
+ xml.ssl_address2 truncate(billing_address[:address2], 30)
258
+ xml.ssl_avs_zip truncate(billing_address[:zip].to_s.gsub(/[^a-zA-Z0-9]/, ''), 9)
259
+ xml.ssl_city truncate(billing_address[:city], 30)
260
+ xml.ssl_state truncate(billing_address[:state], 10)
261
+ xml.ssl_company truncate(billing_address[:company], 50)
262
+ xml.ssl_phone truncate(billing_address[:phone], 20)
263
+ xml.ssl_country truncate(billing_address[:country], 50)
228
264
  end
229
265
 
230
266
  if shipping_address = options[:shipping_address]
231
- first_name, last_name = split_names(shipping_address[:name])
232
- form[:ship_to_first_name] = truncate(first_name, 20)
233
- form[:ship_to_last_name] = truncate(last_name, 30)
234
- form[:ship_to_address1] = truncate(shipping_address[:address1], 30)
235
- form[:ship_to_address2] = truncate(shipping_address[:address2], 30)
236
- form[:ship_to_city] = truncate(shipping_address[:city], 30)
237
- form[:ship_to_state] = truncate(shipping_address[:state], 10)
238
- form[:ship_to_company] = truncate(shipping_address[:company], 50)
239
- form[:ship_to_country] = truncate(shipping_address[:country], 50)
240
- form[:ship_to_zip] = truncate(shipping_address[:zip], 10)
267
+ xml.ssl_ship_to_address1 truncate(shipping_address[:address1], 30)
268
+ xml.ssl_ship_to_address2 truncate(shipping_address[:address2], 30)
269
+ xml.ssl_ship_to_city truncate(shipping_address[:city], 30)
270
+ xml.ssl_ship_to_company truncate(shipping_address[:company], 50)
271
+ xml.ssl_ship_to_country truncate(shipping_address[:country], 50)
272
+ xml.ssl_ship_to_first_name truncate(shipping_address[:first_name], 20)
273
+ xml.ssl_ship_to_last_name truncate(shipping_address[:last_name], 30)
274
+ xml.ssl_ship_to_phone truncate(shipping_address[:phone], 10)
275
+ xml.ssl_ship_to_state truncate(shipping_address[:state], 2)
276
+ xml.ssl_ship_to_zip truncate(shipping_address[:zip], 10)
241
277
  end
242
278
  end
243
279
 
244
- def add_verification(form, options)
245
- form[:verify] = 'Y' if options[:verify]
280
+ def add_verification(xml, options)
281
+ xml.ssl_verify 'Y' if options[:verify]
282
+ end
283
+
284
+ def add_test_mode(xml, options)
285
+ xml.ssl_test_mode 'TRUE' if options[:test_mode]
246
286
  end
247
287
 
248
- def add_test_mode(form, options)
249
- form[:test_mode] = 'TRUE' if options[:test_mode]
288
+ def add_partial_shipment_flag(xml, options)
289
+ xml.ssl_partial_shipment_flag 'Y' if options[:partial_shipment_flag]
250
290
  end
251
291
 
252
- def add_partial_shipment_flag(form, options)
253
- form[:partial_shipment_flag] = 'Y' if options[:partial_shipment_flag]
292
+ def add_ip(xml, options)
293
+ xml.ssl_cardholder_ip options[:ip] if options.has_key?(:ip)
254
294
  end
255
295
 
256
- def add_ip(form, options)
257
- form[:cardholder_ip] = options[:ip] if options.has_key?(:ip)
296
+ def add_auth_purchase_params(xml, options)
297
+ xml.ssl_dynamic_dba options[:dba] if options.has_key?(:dba)
298
+ xml.ssl_merchant_initiated_unscheduled merchant_initiated_unscheduled(options) if merchant_initiated_unscheduled(options)
299
+ xml.ssl_customer_code options[:customer] if options.has_key?(:customer)
300
+ xml.ssl_customer_number options[:customer_number] if options.has_key?(:customer_number)
301
+ xml.ssl_entry_mode entry_mode(options) if entry_mode(options)
302
+ add_custom_fields(xml, options) if options[:custom_fields]
303
+ add_stored_credential(xml, options) if options[:stored_credential]
258
304
  end
259
305
 
260
- def add_auth_purchase_params(form, options)
261
- form[:dynamic_dba] = options[:dba] if options.has_key?(:dba)
262
- form[:merchant_initiated_unscheduled] = options[:merchant_initiated_unscheduled] if options.has_key?(:merchant_initiated_unscheduled)
306
+ def add_custom_fields(xml, options)
307
+ options[:custom_fields]&.each do |key, value|
308
+ xml.send(key.to_sym, value)
309
+ end
263
310
  end
264
311
 
265
- def add_level_3_fields(form, options)
312
+ def add_level_3_fields(xml, options)
266
313
  level_3_data = options[:level_3_data]
267
- form[:customer_code] = level_3_data[:customer_code] if level_3_data[:customer_code]
268
- form[:salestax] = level_3_data[:salestax] if level_3_data[:salestax]
269
- form[:salestax_indicator] = level_3_data[:salestax_indicator] if level_3_data[:salestax_indicator]
270
- form[:level3_indicator] = level_3_data[:level3_indicator] if level_3_data[:level3_indicator]
271
- form[:ship_to_zip] = level_3_data[:ship_to_zip] if level_3_data[:ship_to_zip]
272
- form[:ship_to_country] = level_3_data[:ship_to_country] if level_3_data[:ship_to_country]
273
- form[:shipping_amount] = level_3_data[:shipping_amount] if level_3_data[:shipping_amount]
274
- form[:ship_from_postal_code] = level_3_data[:ship_from_postal_code] if level_3_data[:ship_from_postal_code]
275
- form[:discount_amount] = level_3_data[:discount_amount] if level_3_data[:discount_amount]
276
- form[:duty_amount] = level_3_data[:duty_amount] if level_3_data[:duty_amount]
277
- form[:national_tax_indicator] = level_3_data[:national_tax_indicator] if level_3_data[:national_tax_indicator]
278
- form[:national_tax_amount] = level_3_data[:national_tax_amount] if level_3_data[:national_tax_amount]
279
- form[:order_date] = level_3_data[:order_date] if level_3_data[:order_date]
280
- form[:other_tax] = level_3_data[:other_tax] if level_3_data[:other_tax]
281
- form[:summary_commodity_code] = level_3_data[:summary_commodity_code] if level_3_data[:summary_commodity_code]
282
- form[:merchant_vat_number] = level_3_data[:merchant_vat_number] if level_3_data[:merchant_vat_number]
283
- form[:customer_vat_number] = level_3_data[:customer_vat_number] if level_3_data[:customer_vat_number]
284
- form[:freight_tax_amount] = level_3_data[:freight_tax_amount] if level_3_data[:freight_tax_amount]
285
- form[:vat_invoice_number] = level_3_data[:vat_invoice_number] if level_3_data[:vat_invoice_number]
286
- form[:tracking_number] = level_3_data[:tracking_number] if level_3_data[:tracking_number]
287
- form[:shipping_company] = level_3_data[:shipping_company] if level_3_data[:shipping_company]
288
- form[:other_fees] = level_3_data[:other_fees] if level_3_data[:other_fees]
289
- add_line_items(form, level_3_data) if level_3_data[:line_items]
290
- end
291
-
292
- def add_line_items(form, level_3_data)
293
- items = []
294
- level_3_data[:line_items].each do |line_item|
295
- item = {}
296
- line_item.each do |key, value|
297
- prefixed_key = "ssl_line_Item_#{key}"
298
- item[prefixed_key.to_sym] = value
314
+ xml.ssl_customer_code level_3_data[:customer_code] if level_3_data[:customer_code]
315
+ xml.ssl_salestax level_3_data[:salestax] if level_3_data[:salestax]
316
+ xml.ssl_salestax_indicator level_3_data[:salestax_indicator] if level_3_data[:salestax_indicator]
317
+ xml.ssl_level3_indicator level_3_data[:level3_indicator] if level_3_data[:level3_indicator]
318
+ xml.ssl_ship_to_zip level_3_data[:ship_to_zip] if level_3_data[:ship_to_zip]
319
+ xml.ssl_ship_to_country level_3_data[:ship_to_country] if level_3_data[:ship_to_country]
320
+ xml.ssl_shipping_amount level_3_data[:shipping_amount] if level_3_data[:shipping_amount]
321
+ xml.ssl_ship_from_postal_code level_3_data[:ship_from_postal_code] if level_3_data[:ship_from_postal_code]
322
+ xml.ssl_discount_amount level_3_data[:discount_amount] if level_3_data[:discount_amount]
323
+ xml.ssl_duty_amount level_3_data[:duty_amount] if level_3_data[:duty_amount]
324
+ xml.ssl_national_tax_indicator level_3_data[:national_tax_indicator] if level_3_data[:national_tax_indicator]
325
+ xml.ssl_national_tax_amount level_3_data[:national_tax_amount] if level_3_data[:national_tax_amount]
326
+ xml.ssl_order_date level_3_data[:order_date] if level_3_data[:order_date]
327
+ xml.ssl_other_tax level_3_data[:other_tax] if level_3_data[:other_tax]
328
+ xml.ssl_summary_commodity_code level_3_data[:summary_commodity_code] if level_3_data[:summary_commodity_code]
329
+ xml.ssl_merchant_vat_number level_3_data[:merchant_vat_number] if level_3_data[:merchant_vat_number]
330
+ xml.ssl_customer_vat_number level_3_data[:customer_vat_number] if level_3_data[:customer_vat_number]
331
+ xml.ssl_freight_tax_amount level_3_data[:freight_tax_amount] if level_3_data[:freight_tax_amount]
332
+ xml.ssl_vat_invoice_number level_3_data[:vat_invoice_number] if level_3_data[:vat_invoice_number]
333
+ xml.ssl_tracking_number level_3_data[:tracking_number] if level_3_data[:tracking_number]
334
+ xml.ssl_shipping_company level_3_data[:shipping_company] if level_3_data[:shipping_company]
335
+ xml.ssl_other_fees level_3_data[:other_fees] if level_3_data[:other_fees]
336
+ add_line_items(xml, level_3_data) if level_3_data[:line_items]
337
+ end
338
+
339
+ def add_line_items(xml, level_3_data)
340
+ xml.LineItemProducts {
341
+ level_3_data[:line_items].each do |line_item|
342
+ xml.product {
343
+ line_item.each do |key, value|
344
+ prefixed_key = "ssl_line_Item_#{key}"
345
+ xml.send(prefixed_key, value)
346
+ end
347
+ }
299
348
  end
300
- items << item
349
+ }
350
+ end
351
+
352
+ def add_stored_credential(xml, options)
353
+ network_transaction_id = options.dig(:stored_credential, :network_transaction_id)
354
+ case
355
+ when network_transaction_id.nil?
356
+ return
357
+ when network_transaction_id.to_s.include?('|')
358
+ oar_data, ps2000_data = options[:stored_credential][:network_transaction_id].split('|')
359
+ xml.ssl_oar_data oar_data unless oar_data.nil? || oar_data.empty?
360
+ xml.ssl_ps2000_data ps2000_data unless ps2000_data.nil? || ps2000_data.empty?
361
+ when network_transaction_id.to_s.length > 22
362
+ xml.ssl_oar_data options.dig(:stored_credential, :network_transaction_id)
363
+ else
364
+ xml.ssl_ps2000_data options.dig(:stored_credential, :network_transaction_id)
301
365
  end
302
- form[:LineItemProducts] = { product: items }
303
366
  end
304
367
 
305
- def message_from(response)
306
- success?(response) ? response['result_message'] : response['errorMessage']
368
+ def merchant_initiated_unscheduled(options)
369
+ return options[:merchant_initiated_unscheduled] if options[:merchant_initiated_unscheduled]
370
+ return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
307
371
  end
308
372
 
309
- def success?(response)
310
- !response.has_key?('errorMessage')
373
+ def entry_mode(options)
374
+ return options[:entry_mode] if options[:entry_mode]
375
+ return 12 if options[:stored_credential]
311
376
  end
312
377
 
313
- def commit(action, money, parameters, options)
314
- parameters[:amount] = amount(money)
315
- parameters[:transaction_type] = self.actions[action]
378
+ def build_xml_request
379
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
380
+ xml.txn do
381
+ xml.ssl_merchant_id @options[:login]
382
+ xml.ssl_user_id @options[:user]
383
+ xml.ssl_pin @options[:password]
384
+ yield(xml)
385
+ end
386
+ end
387
+
388
+ builder.to_xml.gsub("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", '')
389
+ end
316
390
 
317
- response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(parameters, options)))
391
+ def commit(request)
392
+ request = "xmldata=#{request}".delete('&')
318
393
 
319
- Response.new(response['result'] == '0', message_from(response), response,
394
+ response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
395
+
396
+ Response.new(
397
+ response[:result] == '0',
398
+ response[:result_message] || response[:errorMessage],
399
+ response,
320
400
  test: @options[:test] || test?,
321
401
  authorization: authorization_from(response),
322
- avs_result: { code: response['avs_response'] },
323
- cvv_result: response['cvv2_response']
402
+ error_code: response[:errorCode],
403
+ avs_result: { code: response[:avs_response] },
404
+ cvv_result: response[:cvv2_response],
405
+ network_transaction_id: build_network_transaction_id(response)
324
406
  )
325
407
  end
326
408
 
327
- def post_data(parameters, options)
328
- result = preamble
329
- result.merge!(parameters)
330
- result.collect { |key, value| post_data_string(key, value, options) }.join('&')
409
+ def build_network_transaction_id(response)
410
+ "#{response[:oar_data]}|#{response[:ps2000_data]}"
331
411
  end
332
412
 
333
- def post_data_string(key, value, options)
334
- if custom_field?(key, options) || key == :LineItemProducts
335
- "#{key}=#{CGI.escape(value.to_s)}"
336
- else
337
- "ssl_#{key}=#{CGI.escape(value.to_s)}"
338
- end
413
+ def headers
414
+ {
415
+ 'Accept' => 'application/xml',
416
+ 'Content-type' => 'application/x-www-form-urlencoded'
417
+ }
339
418
  end
340
419
 
341
- def custom_field?(field_name, options)
342
- return true if options[:custom_fields]&.include?(field_name.to_sym)
420
+ def parse(body)
421
+ xml = Nokogiri::XML(body)
422
+ response = Hash.from_xml(xml.to_s)['txn']
343
423
 
344
- field_name == :customer_number
424
+ response.deep_transform_keys { |key| key.gsub('ssl_', '').to_sym }
345
425
  end
346
426
 
347
- def preamble
348
- result = {
349
- 'merchant_id' => @options[:login],
350
- 'pin' => @options[:password],
351
- 'show_form' => 'false',
352
- 'result_format' => 'ASCII'
353
- }
354
-
355
- result['user_id'] = @options[:user] unless empty?(@options[:user])
356
- result
427
+ def authorization_from(response)
428
+ [response[:approval_code], response[:txn_id]].join(';')
357
429
  end
358
430
 
359
- def parse(msg)
360
- resp = {}
361
- msg.split(self.delimiter).collect { |li|
362
- key, value = li.split('=')
363
- resp[key.to_s.strip.gsub(/^ssl_/, '')] = value.to_s.strip
364
- }
365
- resp
431
+ def truncate(value, size)
432
+ return nil unless value
433
+
434
+ difference = value.force_encoding('iso-8859-1').length - value.length
435
+
436
+ return value.delete('&"<>').to_s[0, (size - difference)]
366
437
  end
367
438
  end
368
439
  end