activemerchant 1.113.0 → 1.119.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +114 -0
  3. data/README.md +1 -1
  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/compatibility.rb +3 -3
  7. data/lib/active_merchant/billing/credit_card.rb +3 -0
  8. data/lib/active_merchant/billing/credit_card_methods.rb +72 -13
  9. data/lib/active_merchant/billing/gateways/adyen.rb +24 -14
  10. data/lib/active_merchant/billing/gateways/allied_wallet.rb +7 -7
  11. data/lib/active_merchant/billing/gateways/authorize_net.rb +44 -12
  12. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +3 -4
  13. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -1
  14. data/lib/active_merchant/billing/gateways/axcessms.rb +8 -9
  15. data/lib/active_merchant/billing/gateways/balanced.rb +4 -3
  16. data/lib/active_merchant/billing/gateways/bambora_apac.rb +7 -7
  17. data/lib/active_merchant/billing/gateways/bank_frick.rb +7 -7
  18. data/lib/active_merchant/billing/gateways/banwire.rb +1 -1
  19. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +6 -4
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +3 -3
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +4 -5
  22. data/lib/active_merchant/billing/gateways/blue_pay.rb +2 -3
  23. data/lib/active_merchant/billing/gateways/blue_snap.rb +37 -12
  24. data/lib/active_merchant/billing/gateways/bogus.rb +19 -19
  25. data/lib/active_merchant/billing/gateways/borgun.rb +11 -11
  26. data/lib/active_merchant/billing/gateways/bpoint.rb +8 -8
  27. data/lib/active_merchant/billing/gateways/braintree.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/braintree_blue.rb +13 -10
  29. data/lib/active_merchant/billing/gateways/bridge_pay.rb +7 -7
  30. data/lib/active_merchant/billing/gateways/cams.rb +8 -8
  31. data/lib/active_merchant/billing/gateways/card_connect.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/card_save.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/card_stream.rb +2 -2
  34. data/lib/active_merchant/billing/gateways/cardknox.rb +7 -7
  35. data/lib/active_merchant/billing/gateways/cardprocess.rb +1 -1
  36. data/lib/active_merchant/billing/gateways/cecabank.rb +5 -5
  37. data/lib/active_merchant/billing/gateways/cenpos.rb +10 -10
  38. data/lib/active_merchant/billing/gateways/checkout.rb +2 -2
  39. data/lib/active_merchant/billing/gateways/checkout_v2.rb +17 -20
  40. data/lib/active_merchant/billing/gateways/clearhaus.rb +7 -7
  41. data/lib/active_merchant/billing/gateways/commercegate.rb +1 -1
  42. data/lib/active_merchant/billing/gateways/conekta.rb +2 -2
  43. data/lib/active_merchant/billing/gateways/creditcall.rb +10 -10
  44. data/lib/active_merchant/billing/gateways/credorax.rb +26 -15
  45. data/lib/active_merchant/billing/gateways/ct_payment.rb +10 -10
  46. data/lib/active_merchant/billing/gateways/culqi.rb +9 -9
  47. data/lib/active_merchant/billing/gateways/cyber_source.rb +58 -36
  48. data/lib/active_merchant/billing/gateways/d_local.rb +11 -11
  49. data/lib/active_merchant/billing/gateways/data_cash.rb +2 -3
  50. data/lib/active_merchant/billing/gateways/decidir.rb +31 -10
  51. data/lib/active_merchant/billing/gateways/dibs.rb +8 -8
  52. data/lib/active_merchant/billing/gateways/digitzs.rb +5 -5
  53. data/lib/active_merchant/billing/gateways/ebanx.rb +9 -9
  54. data/lib/active_merchant/billing/gateways/efsnet.rb +2 -3
  55. data/lib/active_merchant/billing/gateways/elavon.rb +286 -225
  56. data/lib/active_merchant/billing/gateways/element.rb +8 -8
  57. data/lib/active_merchant/billing/gateways/evo_ca.rb +5 -6
  58. data/lib/active_merchant/billing/gateways/eway.rb +3 -4
  59. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -7
  60. data/lib/active_merchant/billing/gateways/eway_rapid.rb +19 -6
  61. data/lib/active_merchant/billing/gateways/exact.rb +8 -9
  62. data/lib/active_merchant/billing/gateways/ezic.rb +7 -7
  63. data/lib/active_merchant/billing/gateways/fat_zebra.rb +4 -4
  64. data/lib/active_merchant/billing/gateways/federated_canada.rb +2 -3
  65. data/lib/active_merchant/billing/gateways/first_giving.rb +1 -1
  66. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -6
  67. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +7 -7
  68. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +21 -10
  69. data/lib/active_merchant/billing/gateways/flo2cash.rb +8 -8
  70. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +1 -1
  71. data/lib/active_merchant/billing/gateways/forte.rb +14 -8
  72. data/lib/active_merchant/billing/gateways/global_collect.rb +35 -16
  73. data/lib/active_merchant/billing/gateways/global_transport.rb +7 -7
  74. data/lib/active_merchant/billing/gateways/hdfc.rb +9 -9
  75. data/lib/active_merchant/billing/gateways/hps.rb +17 -8
  76. data/lib/active_merchant/billing/gateways/iats_payments.rb +9 -4
  77. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +1 -1
  78. data/lib/active_merchant/billing/gateways/inspire.rb +3 -4
  79. data/lib/active_merchant/billing/gateways/instapay.rb +1 -2
  80. data/lib/active_merchant/billing/gateways/ipp.rb +5 -5
  81. data/lib/active_merchant/billing/gateways/iridium.rb +14 -15
  82. data/lib/active_merchant/billing/gateways/iveri.rb +7 -7
  83. data/lib/active_merchant/billing/gateways/ixopay.rb +7 -7
  84. data/lib/active_merchant/billing/gateways/jetpay.rb +1 -2
  85. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -5
  86. data/lib/active_merchant/billing/gateways/kushki.rb +6 -6
  87. data/lib/active_merchant/billing/gateways/latitude19.rb +14 -14
  88. data/lib/active_merchant/billing/gateways/linkpoint.rb +4 -5
  89. data/lib/active_merchant/billing/gateways/litle.rb +31 -15
  90. data/lib/active_merchant/billing/gateways/mastercard.rb +10 -10
  91. data/lib/active_merchant/billing/gateways/mercado_pago.rb +7 -7
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +1 -2
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +1 -1
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +10 -10
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +5 -7
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +4 -6
  97. data/lib/active_merchant/billing/gateways/mercury.rb +4 -4
  98. data/lib/active_merchant/billing/gateways/metrics_global.rb +4 -5
  99. data/lib/active_merchant/billing/gateways/micropayment.rb +8 -8
  100. data/lib/active_merchant/billing/gateways/migs.rb +3 -4
  101. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +2 -4
  102. data/lib/active_merchant/billing/gateways/monei.rb +7 -7
  103. data/lib/active_merchant/billing/gateways/moneris.rb +4 -3
  104. data/lib/active_merchant/billing/gateways/money_movers.rb +2 -3
  105. data/lib/active_merchant/billing/gateways/mundipagg.rb +37 -10
  106. data/lib/active_merchant/billing/gateways/nab_transact.rb +2 -4
  107. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +7 -7
  108. data/lib/active_merchant/billing/gateways/net_registry.rb +1 -2
  109. data/lib/active_merchant/billing/gateways/netaxept.rb +6 -6
  110. data/lib/active_merchant/billing/gateways/netbanx.rb +19 -8
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +4 -5
  112. data/lib/active_merchant/billing/gateways/network_merchants.rb +2 -3
  113. data/lib/active_merchant/billing/gateways/nmi.rb +21 -7
  114. data/lib/active_merchant/billing/gateways/ogone.rb +3 -3
  115. data/lib/active_merchant/billing/gateways/omise.rb +13 -13
  116. data/lib/active_merchant/billing/gateways/openpay.rb +3 -4
  117. data/lib/active_merchant/billing/gateways/opp.rb +9 -9
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +2 -3
  119. data/lib/active_merchant/billing/gateways/orbital.rb +196 -85
  120. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +3 -4
  121. data/lib/active_merchant/billing/gateways/pagarme.rb +8 -8
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +2 -2
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +8 -8
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -7
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +7 -8
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +2 -3
  127. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +9 -9
  128. data/lib/active_merchant/billing/gateways/pay_secure.rb +2 -3
  129. data/lib/active_merchant/billing/gateways/paybox_direct.rb +23 -1
  130. data/lib/active_merchant/billing/gateways/payeezy.rb +32 -14
  131. data/lib/active_merchant/billing/gateways/payex.rb +6 -7
  132. data/lib/active_merchant/billing/gateways/payflow.rb +1 -1
  133. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  134. data/lib/active_merchant/billing/gateways/paymentez.rb +26 -6
  135. data/lib/active_merchant/billing/gateways/paymill.rb +7 -7
  136. data/lib/active_merchant/billing/gateways/paypal.rb +10 -2
  137. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -0
  138. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -1
  139. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +1 -1
  140. data/lib/active_merchant/billing/gateways/payscout.rb +1 -2
  141. data/lib/active_merchant/billing/gateways/paystation.rb +3 -4
  142. data/lib/active_merchant/billing/gateways/payu_in.rb +3 -3
  143. data/lib/active_merchant/billing/gateways/payu_latam.rb +17 -10
  144. data/lib/active_merchant/billing/gateways/payway.rb +8 -9
  145. data/lib/active_merchant/billing/gateways/pin.rb +11 -0
  146. data/lib/active_merchant/billing/gateways/plugnpay.rb +1 -2
  147. data/lib/active_merchant/billing/gateways/pro_pay.rb +8 -8
  148. data/lib/active_merchant/billing/gateways/psigate.rb +2 -3
  149. data/lib/active_merchant/billing/gateways/psl_card.rb +1 -2
  150. data/lib/active_merchant/billing/gateways/qbms.rb +1 -2
  151. data/lib/active_merchant/billing/gateways/quantum.rb +1 -2
  152. data/lib/active_merchant/billing/gateways/quickbooks.rb +1 -1
  153. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +3 -4
  154. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -2
  155. data/lib/active_merchant/billing/gateways/qvalent.rb +8 -8
  156. data/lib/active_merchant/billing/gateways/realex.rb +1 -1
  157. data/lib/active_merchant/billing/gateways/redsys.rb +86 -5
  158. data/lib/active_merchant/billing/gateways/s5.rb +7 -7
  159. data/lib/active_merchant/billing/gateways/safe_charge.rb +40 -14
  160. data/lib/active_merchant/billing/gateways/sage.rb +3 -5
  161. data/lib/active_merchant/billing/gateways/sage_pay.rb +2 -3
  162. data/lib/active_merchant/billing/gateways/sallie_mae.rb +1 -2
  163. data/lib/active_merchant/billing/gateways/secure_net.rb +1 -2
  164. data/lib/active_merchant/billing/gateways/secure_pay.rb +3 -4
  165. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +2 -4
  166. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +1 -2
  167. data/lib/active_merchant/billing/gateways/securion_pay.rb +5 -6
  168. data/lib/active_merchant/billing/gateways/skip_jack.rb +2 -3
  169. data/lib/active_merchant/billing/gateways/smart_ps.rb +5 -6
  170. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +7 -7
  171. data/lib/active_merchant/billing/gateways/spreedly_core.rb +6 -6
  172. data/lib/active_merchant/billing/gateways/stripe.rb +10 -10
  173. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +30 -0
  174. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +3 -4
  175. data/lib/active_merchant/billing/gateways/telr.rb +8 -8
  176. data/lib/active_merchant/billing/gateways/trans_first.rb +2 -2
  177. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +12 -12
  178. data/lib/active_merchant/billing/gateways/transact_pro.rb +9 -9
  179. data/lib/active_merchant/billing/gateways/trust_commerce.rb +1 -2
  180. data/lib/active_merchant/billing/gateways/usa_epay.rb +1 -1
  181. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +32 -32
  182. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +3 -4
  183. data/lib/active_merchant/billing/gateways/vanco.rb +3 -3
  184. data/lib/active_merchant/billing/gateways/verifi.rb +1 -2
  185. data/lib/active_merchant/billing/gateways/viaklix.rb +1 -2
  186. data/lib/active_merchant/billing/gateways/visanet_peru.rb +10 -10
  187. data/lib/active_merchant/billing/gateways/webpay.rb +2 -2
  188. data/lib/active_merchant/billing/gateways/wepay.rb +3 -2
  189. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -2
  190. data/lib/active_merchant/billing/gateways/worldpay.rb +19 -11
  191. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +14 -16
  192. data/lib/active_merchant/billing/gateways/worldpay_us.rb +7 -7
  193. data/lib/active_merchant/billing/response.rb +3 -2
  194. data/lib/active_merchant/country.rb +1 -1
  195. data/lib/active_merchant/network_connection_retries.rb +2 -2
  196. data/lib/active_merchant/post_data.rb +1 -1
  197. data/lib/active_merchant/posts_data.rb +1 -1
  198. data/lib/active_merchant/version.rb +1 -1
  199. data/lib/support/ssl_verify.rb +2 -2
  200. data/lib/support/ssl_version.rb +2 -2
  201. metadata +2 -2
@@ -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,143 @@ 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_transaction_type self.actions[:purchase]
43
+ xml.ssl_amount amount(money)
44
+
45
+ if payment_method.is_a?(String)
46
+ add_token(xml, payment_method)
47
+ else
48
+ add_creditcard(xml, payment_method)
49
+ end
50
+
51
+ add_invoice(xml, options)
52
+ add_salestax(xml, options)
53
+ add_currency(xml, money, options)
54
+ add_address(xml, options)
55
+ add_customer_email(xml, options)
56
+ add_test_mode(xml, options)
57
+ add_ip(xml, options)
58
+ add_auth_purchase_params(xml, options)
59
+ add_level_3_fields(xml, options) if options[:level_3_data]
45
60
  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)
61
+ commit(request)
54
62
  end
55
63
 
56
64
  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)
65
+ request = build_xml_request do |xml|
66
+ xml.ssl_transaction_type self.actions[:authorize]
67
+ xml.ssl_amount amount(money)
68
+
69
+ add_salestax(xml, options)
70
+ add_invoice(xml, options)
71
+ add_creditcard(xml, creditcard)
72
+ add_currency(xml, money, options)
73
+ add_address(xml, options)
74
+ add_customer_email(xml, options)
75
+ add_test_mode(xml, options)
76
+ add_ip(xml, options)
77
+ add_auth_purchase_params(xml, options)
78
+ add_level_3_fields(xml, options) if options[:level_3_data]
79
+ end
80
+ commit(request)
69
81
  end
70
82
 
71
83
  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)
84
+ request = build_xml_request do |xml|
85
+ if options[:credit_card]
86
+ xml.ssl_transaction_type self.actions[:capture]
87
+ xml.ssl_amount amount(money)
88
+ add_salestax(xml, options)
89
+ add_approval_code(xml, authorization)
90
+ add_invoice(xml, options)
91
+ add_creditcard(xml, options[:credit_card])
92
+ add_currency(xml, money, options)
93
+ add_address(xml, options)
94
+ add_customer_email(xml, options)
95
+ add_test_mode(xml, options)
96
+ else
97
+ xml.ssl_transaction_type self.actions[:capture_complete]
98
+ xml.ssl_amount amount(money)
99
+ add_currency(xml, money, options)
100
+ add_txn_id(xml, authorization)
101
+ add_partial_shipment_flag(xml, options)
102
+ add_test_mode(xml, options)
103
+ end
88
104
  end
89
- commit(action, money, form, options)
105
+ commit(request)
90
106
  end
91
107
 
92
108
  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)
109
+ request = build_xml_request do |xml|
110
+ xml.ssl_transaction_type self.actions[:refund]
111
+ xml.ssl_amount amount(money)
112
+ add_txn_id(xml, identification)
113
+ add_test_mode(xml, options)
114
+ end
115
+ commit(request)
97
116
  end
98
117
 
99
118
  def void(identification, options = {})
100
- form = {}
101
- add_txn_id(form, identification)
102
- add_test_mode(form, options)
103
- commit(:void, nil, form, options)
119
+ request = build_xml_request do |xml|
120
+ xml.ssl_transaction_type self.actions[:void]
121
+
122
+ add_txn_id(xml, identification)
123
+ add_test_mode(xml, options)
124
+ end
125
+ commit(request)
104
126
  end
105
127
 
106
128
  def credit(money, creditcard, options = {})
107
129
  raise ArgumentError, 'Reference credits are not supported. Please supply the original credit card or use the #refund method.' if creditcard.is_a?(String)
108
130
 
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)
131
+ request = build_xml_request do |xml|
132
+ xml.ssl_transaction_type self.actions[:credit]
133
+ xml.ssl_amount amount(money)
134
+ add_invoice(xml, options)
135
+ add_creditcard(xml, creditcard)
136
+ add_currency(xml, money, options)
137
+ add_address(xml, options)
138
+ add_customer_email(xml, options)
139
+ add_test_mode(xml, options)
140
+ end
141
+ commit(request)
117
142
  end
118
143
 
119
144
  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)
145
+ request = build_xml_request do |xml|
146
+ xml.ssl_transaction_type self.actions[:verify]
147
+ add_creditcard(xml, credit_card)
148
+ add_address(xml, options)
149
+ add_test_mode(xml, options)
150
+ add_ip(xml, options)
151
+ end
152
+ commit(request)
126
153
  end
127
154
 
128
155
  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)
156
+ request = build_xml_request do |xml|
157
+ xml.ssl_transaction_type self.actions[:store]
158
+ xml.ssl_add_token 'Y'
159
+ add_creditcard(xml, creditcard)
160
+ add_address(xml, options)
161
+ add_customer_email(xml, options)
162
+ add_test_mode(xml, options)
163
+ add_verification(xml, options)
164
+ end
165
+ commit(request)
137
166
  end
138
167
 
139
168
  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)
169
+ request = build_xml_request do |xml|
170
+ xml.ssl_transaction_type self.actions[:update]
171
+ add_token(xml, token)
172
+ add_creditcard(xml, creditcard)
173
+ add_address(xml, options)
174
+ add_customer_email(xml, options)
175
+ add_test_mode(xml, options)
176
+ end
177
+ commit(request)
147
178
  end
148
179
 
149
180
  def supports_scrubbing?
@@ -152,217 +183,247 @@ module ActiveMerchant #:nodoc:
152
183
 
153
184
  def scrub(transcript)
154
185
  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]')
186
+ gsub(%r((<ssl_pin>)(.*)(</ssl_pin>)), '\1[FILTERED]\3').
187
+ gsub(%r((<ssl_card_number>)(.*)(</ssl_card_number>)), '\1[FILTERED]\3').
188
+ gsub(%r((<ssl_cvv2cvc2>)(.*)(</ssl_cvv2cvc2>)), '\1[FILTERED]\3')
158
189
  end
159
190
 
160
191
  private
161
192
 
162
- def add_invoice(form, options)
163
- form[:invoice_number] = truncate((options[:order_id] || options[:invoice]), 10)
164
- form[:description] = truncate(options[:description], 255)
193
+ def add_invoice(xml, options)
194
+ xml.ssl_invoice_number truncate((options[:order_id] || options[:invoice]), 25)
195
+ xml.ssl_description truncate(options[:description], 255)
165
196
  end
166
197
 
167
- def add_approval_code(form, authorization)
168
- form[:approval_code] = authorization.split(';').first
198
+ def add_approval_code(xml, authorization)
199
+ xml.ssl_approval_code authorization.split(';').first
169
200
  end
170
201
 
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(';')
202
+ def add_txn_id(xml, authorization)
203
+ xml.ssl_txn_id authorization.split(';').last
177
204
  end
178
205
 
179
- def add_creditcard(form, creditcard)
180
- form[:card_number] = creditcard.number
181
- form[:exp_date] = expdate(creditcard)
206
+ def add_creditcard(xml, creditcard)
207
+ xml.ssl_card_number creditcard.number
208
+ xml.ssl_exp_date expdate(creditcard)
182
209
 
183
- add_verification_value(form, creditcard) if creditcard.verification_value?
210
+ add_verification_value(xml, creditcard) if creditcard.verification_value?
184
211
 
185
- form[:first_name] = truncate(creditcard.first_name, 20)
186
- form[:last_name] = truncate(creditcard.last_name, 30)
212
+ xml.ssl_first_name truncate(creditcard.first_name, 20)
213
+ xml.ssl_last_name truncate(creditcard.last_name, 30)
187
214
  end
188
215
 
189
- def add_currency(form, money, options)
216
+ def add_currency(xml, money, options)
190
217
  currency = options[:currency] || currency(money)
191
- form[:transaction_currency] = currency if currency && (@options[:multi_currency] || options[:multi_currency])
218
+ return unless currency && (@options[:multi_currency] || options[:multi_currency])
219
+
220
+ xml.ssl_transaction_currency currency
192
221
  end
193
222
 
194
- def add_token(form, token)
195
- form[:token] = token
223
+ def add_token(xml, token)
224
+ xml.ssl_token token
196
225
  end
197
226
 
198
- def add_verification_value(form, creditcard)
199
- form[:cvv2cvc2] = creditcard.verification_value
200
- form[:cvv2cvc2_indicator] = '1'
227
+ def add_verification_value(xml, creditcard)
228
+ xml.ssl_cvv2cvc2 creditcard.verification_value
229
+ xml.ssl_cvv2cvc2_indicator 1
201
230
  end
202
231
 
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
232
+ def add_customer_email(xml, options)
233
+ xml.ssl_email truncate(options[:email], 100) unless empty?(options[:email])
210
234
  end
211
235
 
212
- def add_salestax(form, options)
213
- form[:salestax] = options[:tax] if options[:tax].present?
236
+ def add_salestax(xml, options)
237
+ return unless options[:tax].present?
238
+
239
+ xml.ssl_salestax options[:tax]
214
240
  end
215
241
 
216
- def add_address(form, options)
242
+ def add_address(xml, options)
217
243
  billing_address = options[:billing_address] || options[:address]
218
244
 
219
245
  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)
246
+ xml.ssl_avs_address truncate(billing_address[:address1], 30)
247
+ xml.ssl_address2 truncate(billing_address[:address2], 30)
248
+ xml.ssl_avs_zip truncate(billing_address[:zip].to_s.gsub(/[^a-zA-Z0-9]/, ''), 9)
249
+ xml.ssl_city truncate(billing_address[:city], 30)
250
+ xml.ssl_state truncate(billing_address[:state], 10)
251
+ xml.ssl_company truncate(billing_address[:company], 50)
252
+ xml.ssl_phone truncate(billing_address[:phone], 20)
253
+ xml.ssl_country truncate(billing_address[:country], 50)
228
254
  end
229
255
 
230
256
  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)
257
+ xml.ssl_ship_to_address1 truncate(shipping_address[:address1], 30)
258
+ xml.ssl_ship_to_address2 truncate(shipping_address[:address2], 30)
259
+ xml.ssl_ship_to_city truncate(shipping_address[:city], 30)
260
+ xml.ssl_ship_to_company truncate(shipping_address[:company], 50)
261
+ xml.ssl_ship_to_country truncate(shipping_address[:country], 50)
262
+ xml.ssl_ship_to_first_name truncate(shipping_address[:first_name], 20)
263
+ xml.ssl_ship_to_last_name truncate(shipping_address[:last_name], 30)
264
+ xml.ssl_ship_to_phone truncate(shipping_address[:phone], 10)
265
+ xml.ssl_ship_to_state truncate(shipping_address[:state], 2)
266
+ xml.ssl_ship_to_zip truncate(shipping_address[:zip], 10)
241
267
  end
242
268
  end
243
269
 
244
- def add_verification(form, options)
245
- form[:verify] = 'Y' if options[:verify]
270
+ def add_verification(xml, options)
271
+ xml.ssl_verify 'Y' if options[:verify]
272
+ end
273
+
274
+ def add_test_mode(xml, options)
275
+ xml.ssl_test_mode 'TRUE' if options[:test_mode]
246
276
  end
247
277
 
248
- def add_test_mode(form, options)
249
- form[:test_mode] = 'TRUE' if options[:test_mode]
278
+ def add_partial_shipment_flag(xml, options)
279
+ xml.ssl_partial_shipment_flag 'Y' if options[:partial_shipment_flag]
250
280
  end
251
281
 
252
- def add_partial_shipment_flag(form, options)
253
- form[:partial_shipment_flag] = 'Y' if options[:partial_shipment_flag]
282
+ def add_ip(xml, options)
283
+ xml.ssl_cardholder_ip options[:ip] if options.has_key?(:ip)
254
284
  end
255
285
 
256
- def add_ip(form, options)
257
- form[:cardholder_ip] = options[:ip] if options.has_key?(:ip)
286
+ def add_auth_purchase_params(xml, options)
287
+ xml.ssl_dynamic_dba options[:dba] if options.has_key?(:dba)
288
+ xml.ssl_merchant_initiated_unscheduled merchant_initiated_unscheduled(options) if merchant_initiated_unscheduled(options)
289
+ xml.ssl_customer_code options[:customer] if options.has_key?(:customer)
290
+ xml.ssl_customer_number options[:customer_number] if options.has_key?(:customer_number)
291
+ xml.ssl_entry_mode entry_mode(options) if entry_mode(options)
292
+ add_custom_fields(xml, options) if options[:custom_fields]
293
+ add_stored_credential(xml, options) if options[:stored_credential]
258
294
  end
259
295
 
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)
296
+ def add_custom_fields(xml, options)
297
+ options[:custom_fields]&.each do |key, value|
298
+ xml.send(key.to_sym, value)
299
+ end
263
300
  end
264
301
 
265
- def add_level_3_fields(form, options)
302
+ def add_level_3_fields(xml, options)
266
303
  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
304
+ xml.ssl_customer_code level_3_data[:customer_code] if level_3_data[:customer_code]
305
+ xml.ssl_salestax level_3_data[:salestax] if level_3_data[:salestax]
306
+ xml.ssl_salestax_indicator level_3_data[:salestax_indicator] if level_3_data[:salestax_indicator]
307
+ xml.ssl_level3_indicator level_3_data[:level3_indicator] if level_3_data[:level3_indicator]
308
+ xml.ssl_ship_to_zip level_3_data[:ship_to_zip] if level_3_data[:ship_to_zip]
309
+ xml.ssl_ship_to_country level_3_data[:ship_to_country] if level_3_data[:ship_to_country]
310
+ xml.ssl_shipping_amount level_3_data[:shipping_amount] if level_3_data[:shipping_amount]
311
+ xml.ssl_ship_from_postal_code level_3_data[:ship_from_postal_code] if level_3_data[:ship_from_postal_code]
312
+ xml.ssl_discount_amount level_3_data[:discount_amount] if level_3_data[:discount_amount]
313
+ xml.ssl_duty_amount level_3_data[:duty_amount] if level_3_data[:duty_amount]
314
+ xml.ssl_national_tax_indicator level_3_data[:national_tax_indicator] if level_3_data[:national_tax_indicator]
315
+ xml.ssl_national_tax_amount level_3_data[:national_tax_amount] if level_3_data[:national_tax_amount]
316
+ xml.ssl_order_date level_3_data[:order_date] if level_3_data[:order_date]
317
+ xml.ssl_other_tax level_3_data[:other_tax] if level_3_data[:other_tax]
318
+ xml.ssl_summary_commodity_code level_3_data[:summary_commodity_code] if level_3_data[:summary_commodity_code]
319
+ xml.ssl_merchant_vat_number level_3_data[:merchant_vat_number] if level_3_data[:merchant_vat_number]
320
+ xml.ssl_customer_vat_number level_3_data[:customer_vat_number] if level_3_data[:customer_vat_number]
321
+ xml.ssl_freight_tax_amount level_3_data[:freight_tax_amount] if level_3_data[:freight_tax_amount]
322
+ xml.ssl_vat_invoice_number level_3_data[:vat_invoice_number] if level_3_data[:vat_invoice_number]
323
+ xml.ssl_tracking_number level_3_data[:tracking_number] if level_3_data[:tracking_number]
324
+ xml.ssl_shipping_company level_3_data[:shipping_company] if level_3_data[:shipping_company]
325
+ xml.ssl_other_fees level_3_data[:other_fees] if level_3_data[:other_fees]
326
+ add_line_items(xml, level_3_data) if level_3_data[:line_items]
327
+ end
328
+
329
+ def add_line_items(xml, level_3_data)
330
+ xml.LineItemProducts {
331
+ level_3_data[:line_items].each do |line_item|
332
+ xml.product {
333
+ line_item.each do |key, value|
334
+ prefixed_key = "ssl_line_Item_#{key}"
335
+ xml.send(prefixed_key, value)
336
+ end
337
+ }
299
338
  end
300
- items << item
339
+ }
340
+ end
341
+
342
+ def add_stored_credential(xml, options)
343
+ network_transaction_id = options.dig(:stored_credential, :network_transaction_id)
344
+ case
345
+ when network_transaction_id.nil?
346
+ return
347
+ when network_transaction_id.to_s.include?('|')
348
+ oar_data, ps2000_data = options[:stored_credential][:network_transaction_id].split('|')
349
+ xml.ssl_oar_data oar_data unless oar_data.nil? || oar_data.empty?
350
+ xml.ssl_ps2000_data ps2000_data unless ps2000_data.nil? || ps2000_data.empty?
351
+ when network_transaction_id.to_s.length > 22
352
+ xml.ssl_oar_data options.dig(:stored_credential, :network_transaction_id)
353
+ else
354
+ xml.ssl_ps2000_data options.dig(:stored_credential, :network_transaction_id)
301
355
  end
302
- form[:LineItemProducts] = { product: items }
303
356
  end
304
357
 
305
- def message_from(response)
306
- success?(response) ? response['result_message'] : response['errorMessage']
358
+ def merchant_initiated_unscheduled(options)
359
+ return options[:merchant_initiated_unscheduled] if options[:merchant_initiated_unscheduled]
360
+ return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
307
361
  end
308
362
 
309
- def success?(response)
310
- !response.has_key?('errorMessage')
363
+ def entry_mode(options)
364
+ return options[:entry_mode] if options[:entry_mode]
365
+ return 12 if options[:stored_credential]
311
366
  end
312
367
 
313
- def commit(action, money, parameters, options)
314
- parameters[:amount] = amount(money)
315
- parameters[:transaction_type] = self.actions[action]
368
+ def build_xml_request
369
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
370
+ xml.txn do
371
+ xml.ssl_merchant_id @options[:login]
372
+ xml.ssl_user_id @options[:user]
373
+ xml.ssl_pin @options[:password]
374
+ yield(xml)
375
+ end
376
+ end
377
+
378
+ builder.to_xml.gsub("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", '')
379
+ end
316
380
 
317
- response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(parameters, options)))
381
+ def commit(request)
382
+ request = "xmldata=#{request}".delete('&')
318
383
 
319
- Response.new(response['result'] == '0', message_from(response), response,
384
+ response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
385
+
386
+ Response.new(
387
+ response[:result] == '0',
388
+ response[:result_message] || response[:errorMessage],
389
+ response,
320
390
  test: @options[:test] || test?,
321
391
  authorization: authorization_from(response),
322
- avs_result: { code: response['avs_response'] },
323
- cvv_result: response['cvv2_response']
392
+ error_code: response[:errorCode],
393
+ avs_result: { code: response[:avs_response] },
394
+ cvv_result: response[:cvv2_response],
395
+ network_transaction_id: build_network_transaction_id(response)
324
396
  )
325
397
  end
326
398
 
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('&')
399
+ def build_network_transaction_id(response)
400
+ "#{response[:oar_data]}|#{response[:ps2000_data]}"
331
401
  end
332
402
 
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
403
+ def headers
404
+ {
405
+ 'Accept' => 'application/xml',
406
+ 'Content-type' => 'application/x-www-form-urlencoded'
407
+ }
339
408
  end
340
409
 
341
- def custom_field?(field_name, options)
342
- return true if options[:custom_fields]&.include?(field_name.to_sym)
410
+ def parse(body)
411
+ xml = Nokogiri::XML(body)
412
+ response = Hash.from_xml(xml.to_s)['txn']
343
413
 
344
- field_name == :customer_number
414
+ response.deep_transform_keys { |key| key.gsub('ssl_', '').to_sym }
345
415
  end
346
416
 
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
417
+ def authorization_from(response)
418
+ [response[:approval_code], response[:txn_id]].join(';')
357
419
  end
358
420
 
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
421
+ def truncate(value, size)
422
+ return nil unless value
423
+
424
+ difference = value.force_encoding('iso-8859-1').length - value.length
425
+
426
+ return value.to_s[0, (size - difference)]
366
427
  end
367
428
  end
368
429
  end