swiss-crm-activemerchant 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +4033 -0
  3. data/CONTRIBUTORS +568 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +252 -0
  6. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  7. data/lib/active_merchant/billing/avs_result.rb +95 -0
  8. data/lib/active_merchant/billing/base.rb +48 -0
  9. data/lib/active_merchant/billing/check.rb +112 -0
  10. data/lib/active_merchant/billing/compatibility.rb +118 -0
  11. data/lib/active_merchant/billing/credit_card.rb +451 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +512 -0
  14. data/lib/active_merchant/billing/cvv_result.rb +37 -0
  15. data/lib/active_merchant/billing/gateway.rb +332 -0
  16. data/lib/active_merchant/billing/gateways/adyen.rb +774 -0
  17. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  18. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +205 -0
  20. data/lib/active_merchant/billing/gateways/authorize_net.rb +1125 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +424 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +977 -0
  23. data/lib/active_merchant/billing/gateways/axcessms.rb +242 -0
  24. data/lib/active_merchant/billing/gateways/balanced.rb +263 -0
  25. data/lib/active_merchant/billing/gateways/bambora_apac.rb +222 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +116 -0
  28. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +397 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +474 -0
  32. data/lib/active_merchant/billing/gateways/beanstream.rb +238 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +57 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +549 -0
  35. data/lib/active_merchant/billing/gateways/blue_snap.rb +644 -0
  36. data/lib/active_merchant/billing/gateways/bogus.rb +190 -0
  37. data/lib/active_merchant/billing/gateways/borgun.rb +272 -0
  38. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +28 -0
  40. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  41. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  42. data/lib/active_merchant/billing/gateways/braintree_blue.rb +952 -0
  43. data/lib/active_merchant/billing/gateways/braintree_orange.rb +19 -0
  44. data/lib/active_merchant/billing/gateways/bridge_pay.rb +244 -0
  45. data/lib/active_merchant/billing/gateways/cams.rb +230 -0
  46. data/lib/active_merchant/billing/gateways/card_connect.rb +338 -0
  47. data/lib/active_merchant/billing/gateways/card_save.rb +21 -0
  48. data/lib/active_merchant/billing/gateways/card_stream.rb +394 -0
  49. data/lib/active_merchant/billing/gateways/cardknox.rb +327 -0
  50. data/lib/active_merchant/billing/gateways/cardprocess.rb +256 -0
  51. data/lib/active_merchant/billing/gateways/cashnet.rb +235 -0
  52. data/lib/active_merchant/billing/gateways/cc5.rb +198 -0
  53. data/lib/active_merchant/billing/gateways/cecabank.rb +249 -0
  54. data/lib/active_merchant/billing/gateways/cenpos.rb +328 -0
  55. data/lib/active_merchant/billing/gateways/checkout.rb +212 -0
  56. data/lib/active_merchant/billing/gateways/checkout_v2.rb +587 -0
  57. data/lib/active_merchant/billing/gateways/citrus_pay.rb +21 -0
  58. data/lib/active_merchant/billing/gateways/clearhaus.rb +219 -0
  59. data/lib/active_merchant/billing/gateways/commerce_hub.rb +366 -0
  60. data/lib/active_merchant/billing/gateways/commercegate.rb +142 -0
  61. data/lib/active_merchant/billing/gateways/conekta.rb +230 -0
  62. data/lib/active_merchant/billing/gateways/creditcall.rb +272 -0
  63. data/lib/active_merchant/billing/gateways/credorax.rb +526 -0
  64. data/lib/active_merchant/billing/gateways/ct_payment.rb +269 -0
  65. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  66. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  67. data/lib/active_merchant/billing/gateways/cyber_source.rb +1148 -0
  68. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +454 -0
  69. data/lib/active_merchant/billing/gateways/d_local.rb +343 -0
  70. data/lib/active_merchant/billing/gateways/data_cash.rb +302 -0
  71. data/lib/active_merchant/billing/gateways/decidir.rb +358 -0
  72. data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
  73. data/lib/active_merchant/billing/gateways/dibs.rb +199 -0
  74. data/lib/active_merchant/billing/gateways/digitzs.rb +295 -0
  75. data/lib/active_merchant/billing/gateways/ebanx.rb +346 -0
  76. data/lib/active_merchant/billing/gateways/efsnet.rb +215 -0
  77. data/lib/active_merchant/billing/gateways/elavon.rb +475 -0
  78. data/lib/active_merchant/billing/gateways/element.rb +406 -0
  79. data/lib/active_merchant/billing/gateways/epay.rb +296 -0
  80. data/lib/active_merchant/billing/gateways/evo_ca.rb +307 -0
  81. data/lib/active_merchant/billing/gateways/eway.rb +226 -0
  82. data/lib/active_merchant/billing/gateways/eway_managed.rb +289 -0
  83. data/lib/active_merchant/billing/gateways/eway_rapid.rb +578 -0
  84. data/lib/active_merchant/billing/gateways/exact.rb +219 -0
  85. data/lib/active_merchant/billing/gateways/ezic.rb +195 -0
  86. data/lib/active_merchant/billing/gateways/fat_zebra.rb +223 -0
  87. data/lib/active_merchant/billing/gateways/federated_canada.rb +158 -0
  88. data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
  89. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  90. data/lib/active_merchant/billing/gateways/first_pay.rb +182 -0
  91. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +452 -0
  92. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +505 -0
  93. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  94. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  95. data/lib/active_merchant/billing/gateways/fluidpay.rb +275 -0
  96. data/lib/active_merchant/billing/gateways/forte.rb +286 -0
  97. data/lib/active_merchant/billing/gateways/garanti.rb +256 -0
  98. data/lib/active_merchant/billing/gateways/global_collect.rb +580 -0
  99. data/lib/active_merchant/billing/gateways/global_transport.rb +193 -0
  100. data/lib/active_merchant/billing/gateways/hdfc.rb +205 -0
  101. data/lib/active_merchant/billing/gateways/hps.rb +472 -0
  102. data/lib/active_merchant/billing/gateways/iats_payments.rb +312 -0
  103. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  104. data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
  105. data/lib/active_merchant/billing/gateways/instapay.rb +159 -0
  106. data/lib/active_merchant/billing/gateways/ipg.rb +420 -0
  107. data/lib/active_merchant/billing/gateways/ipp.rb +176 -0
  108. data/lib/active_merchant/billing/gateways/iridium.rb +467 -0
  109. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  110. data/lib/active_merchant/billing/gateways/iveri.rb +290 -0
  111. data/lib/active_merchant/billing/gateways/ixopay.rb +320 -0
  112. data/lib/active_merchant/billing/gateways/jetpay.rb +395 -0
  113. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +432 -0
  114. data/lib/active_merchant/billing/gateways/klarna.rb +317 -0
  115. data/lib/active_merchant/billing/gateways/komoju.rb +115 -0
  116. data/lib/active_merchant/billing/gateways/kushki.rb +297 -0
  117. data/lib/active_merchant/billing/gateways/latitude19.rb +412 -0
  118. data/lib/active_merchant/billing/gateways/linkpoint.rb +448 -0
  119. data/lib/active_merchant/billing/gateways/litle.rb +643 -0
  120. data/lib/active_merchant/billing/gateways/mastercard.rb +286 -0
  121. data/lib/active_merchant/billing/gateways/maxipago.rb +220 -0
  122. data/lib/active_merchant/billing/gateways/mercado_pago.rb +348 -0
  123. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +228 -0
  124. data/lib/active_merchant/billing/gateways/merchant_one.rb +110 -0
  125. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  126. data/lib/active_merchant/billing/gateways/merchant_ware.rb +313 -0
  127. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +284 -0
  128. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +248 -0
  129. data/lib/active_merchant/billing/gateways/mercury.rb +352 -0
  130. data/lib/active_merchant/billing/gateways/metrics_global.rb +293 -0
  131. data/lib/active_merchant/billing/gateways/micropayment.rb +182 -0
  132. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  133. data/lib/active_merchant/billing/gateways/migs.rb +329 -0
  134. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  135. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  136. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +215 -0
  137. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  138. data/lib/active_merchant/billing/gateways/monei.rb +424 -0
  139. data/lib/active_merchant/billing/gateways/moneris.rb +488 -0
  140. data/lib/active_merchant/billing/gateways/money_movers.rb +150 -0
  141. data/lib/active_merchant/billing/gateways/mundipagg.rb +366 -0
  142. data/lib/active_merchant/billing/gateways/nab_transact.rb +299 -0
  143. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +163 -0
  144. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  145. data/lib/active_merchant/billing/gateways/netaxept.rb +180 -0
  146. data/lib/active_merchant/billing/gateways/netbanx.rb +376 -0
  147. data/lib/active_merchant/billing/gateways/netbilling.rb +229 -0
  148. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  149. data/lib/active_merchant/billing/gateways/network_merchants.rb +238 -0
  150. data/lib/active_merchant/billing/gateways/nmi.rb +396 -0
  151. data/lib/active_merchant/billing/gateways/ogone.rb +509 -0
  152. data/lib/active_merchant/billing/gateways/omise.rb +323 -0
  153. data/lib/active_merchant/billing/gateways/openpay.rb +246 -0
  154. data/lib/active_merchant/billing/gateways/opp.rb +394 -0
  155. data/lib/active_merchant/billing/gateways/optimal_payment.rb +331 -0
  156. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +45 -0
  157. data/lib/active_merchant/billing/gateways/orbital.rb +1267 -0
  158. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +206 -0
  159. data/lib/active_merchant/billing/gateways/pagarme.rb +239 -0
  160. data/lib/active_merchant/billing/gateways/pago_facil.rb +120 -0
  161. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  162. data/lib/active_merchant/billing/gateways/pay_conex.rb +245 -0
  163. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  164. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  165. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  166. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +206 -0
  167. data/lib/active_merchant/billing/gateways/pay_secure.rb +110 -0
  168. data/lib/active_merchant/billing/gateways/pay_trace.rb +450 -0
  169. data/lib/active_merchant/billing/gateways/paybox_direct.rb +224 -0
  170. data/lib/active_merchant/billing/gateways/payeezy.rb +513 -0
  171. data/lib/active_merchant/billing/gateways/payex.rb +409 -0
  172. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +235 -0
  173. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +42 -0
  174. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  175. data/lib/active_merchant/billing/gateways/payflow.rb +473 -0
  176. data/lib/active_merchant/billing/gateways/payflow_express.rb +220 -0
  177. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +14 -0
  178. data/lib/active_merchant/billing/gateways/payflow_uk.rb +20 -0
  179. data/lib/active_merchant/billing/gateways/payment_express.rb +373 -0
  180. data/lib/active_merchant/billing/gateways/paymentez.rb +365 -0
  181. data/lib/active_merchant/billing/gateways/paymill.rb +369 -0
  182. data/lib/active_merchant/billing/gateways/paynetworx.rb +228 -0
  183. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +718 -0
  184. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +69 -0
  185. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  186. data/lib/active_merchant/billing/gateways/paypal.rb +136 -0
  187. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  188. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  189. data/lib/active_merchant/billing/gateways/paypal_express.rb +272 -0
  190. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  191. data/lib/active_merchant/billing/gateways/paypal_standard.rb +281 -0
  192. data/lib/active_merchant/billing/gateways/paysafe.rb +420 -0
  193. data/lib/active_merchant/billing/gateways/payscout.rb +159 -0
  194. data/lib/active_merchant/billing/gateways/paystation.rb +204 -0
  195. data/lib/active_merchant/billing/gateways/payu_in.rb +249 -0
  196. data/lib/active_merchant/billing/gateways/payu_latam.rb +482 -0
  197. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  198. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  199. data/lib/active_merchant/billing/gateways/pin.rb +273 -0
  200. data/lib/active_merchant/billing/gateways/pixxels.rb +263 -0
  201. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  202. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  203. data/lib/active_merchant/billing/gateways/priority.rb +392 -0
  204. data/lib/active_merchant/billing/gateways/pro_pay.rb +325 -0
  205. data/lib/active_merchant/billing/gateways/psigate.rb +227 -0
  206. data/lib/active_merchant/billing/gateways/psl_card.rb +295 -0
  207. data/lib/active_merchant/billing/gateways/qbms.rb +302 -0
  208. data/lib/active_merchant/billing/gateways/quantum.rb +274 -0
  209. data/lib/active_merchant/billing/gateways/quickbooks.rb +377 -0
  210. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +184 -0
  211. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +297 -0
  212. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +226 -0
  213. data/lib/active_merchant/billing/gateways/quickpay.rb +24 -0
  214. data/lib/active_merchant/billing/gateways/qvalent.rb +305 -0
  215. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  216. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  217. data/lib/active_merchant/billing/gateways/realex.rb +400 -0
  218. data/lib/active_merchant/billing/gateways/redsys.rb +723 -0
  219. data/lib/active_merchant/billing/gateways/s5.rb +247 -0
  220. data/lib/active_merchant/billing/gateways/safe_charge.rb +298 -0
  221. data/lib/active_merchant/billing/gateways/sage.rb +446 -0
  222. data/lib/active_merchant/billing/gateways/sage_pay.rb +434 -0
  223. data/lib/active_merchant/billing/gateways/sallie_mae.rb +141 -0
  224. data/lib/active_merchant/billing/gateways/secure_net.rb +260 -0
  225. data/lib/active_merchant/billing/gateways/secure_pay.rb +191 -0
  226. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +290 -0
  227. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +103 -0
  228. data/lib/active_merchant/billing/gateways/securion_pay.rb +305 -0
  229. data/lib/active_merchant/billing/gateways/shift4.rb +345 -0
  230. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  231. data/lib/active_merchant/billing/gateways/skip_jack.rb +450 -0
  232. data/lib/active_merchant/billing/gateways/smart_ps.rb +274 -0
  233. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  234. data/lib/active_merchant/billing/gateways/spreedly_core.rb +354 -0
  235. data/lib/active_merchant/billing/gateways/stripe.rb +866 -0
  236. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +602 -0
  237. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +151 -0
  238. data/lib/active_merchant/billing/gateways/telr.rb +273 -0
  239. data/lib/active_merchant/billing/gateways/tns.rb +23 -0
  240. data/lib/active_merchant/billing/gateways/trans_first.rb +240 -0
  241. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +612 -0
  242. data/lib/active_merchant/billing/gateways/transact_pro.rb +222 -0
  243. data/lib/active_merchant/billing/gateways/transax.rb +21 -0
  244. data/lib/active_merchant/billing/gateways/transnational.rb +9 -0
  245. data/lib/active_merchant/billing/gateways/trexle.rb +221 -0
  246. data/lib/active_merchant/billing/gateways/trust_commerce.rb +500 -0
  247. data/lib/active_merchant/billing/gateways/usa_epay.rb +24 -0
  248. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1612 -0
  249. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +367 -0
  250. data/lib/active_merchant/billing/gateways/vanco.rb +303 -0
  251. data/lib/active_merchant/billing/gateways/verifi.rb +224 -0
  252. data/lib/active_merchant/billing/gateways/viaklix.rb +171 -0
  253. data/lib/active_merchant/billing/gateways/visanet_peru.rb +250 -0
  254. data/lib/active_merchant/billing/gateways/vpos.rb +223 -0
  255. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  256. data/lib/active_merchant/billing/gateways/wepay.rb +235 -0
  257. data/lib/active_merchant/billing/gateways/wirecard.rb +430 -0
  258. data/lib/active_merchant/billing/gateways/wompi.rb +197 -0
  259. data/lib/active_merchant/billing/gateways/world_net.rb +345 -0
  260. data/lib/active_merchant/billing/gateways/worldpay.rb +1050 -0
  261. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +208 -0
  262. data/lib/active_merchant/billing/gateways/worldpay_us.rb +221 -0
  263. data/lib/active_merchant/billing/gateways.rb +14 -0
  264. data/lib/active_merchant/billing/model.rb +30 -0
  265. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +39 -0
  266. data/lib/active_merchant/billing/payment_token.rb +21 -0
  267. data/lib/active_merchant/billing/rails.rb +3 -0
  268. data/lib/active_merchant/billing/response.rb +121 -0
  269. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  270. data/lib/active_merchant/billing.rb +16 -0
  271. data/lib/active_merchant/connection.rb +194 -0
  272. data/lib/active_merchant/country.rb +338 -0
  273. data/lib/active_merchant/empty.rb +20 -0
  274. data/lib/active_merchant/errors.rb +38 -0
  275. data/lib/active_merchant/net_http_ssl_connection.rb +11 -0
  276. data/lib/active_merchant/network_connection_retries.rb +78 -0
  277. data/lib/active_merchant/post_data.rb +26 -0
  278. data/lib/active_merchant/posts_data.rb +92 -0
  279. data/lib/active_merchant/version.rb +3 -0
  280. data/lib/active_merchant.rb +63 -0
  281. data/lib/activemerchant.rb +1 -0
  282. data/lib/certs/cacert.pem +3214 -0
  283. data/lib/support/gateway_support.rb +69 -0
  284. data/lib/support/outbound_hosts.rb +28 -0
  285. data/lib/support/ssl_verify.rb +88 -0
  286. data/lib/support/ssl_version.rb +86 -0
  287. metadata +506 -0
@@ -0,0 +1,1125 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant
4
+ module Billing
5
+ class AuthorizeNetGateway < Gateway
6
+ include Empty
7
+
8
+ self.test_url = 'https://apitest.authorize.net/xml/v1/request.api'
9
+ self.live_url = 'https://api2.authorize.net/xml/v1/request.api'
10
+
11
+ self.supported_countries = %w(AU CA US)
12
+ self.default_currency = 'USD'
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = %i[visa master american_express discover diners_club jcb maestro]
15
+
16
+ self.homepage_url = 'http://www.authorize.net/'
17
+ self.display_name = 'Authorize.Net'
18
+
19
+ # Authorize.net has slightly different definitions for returned AVS codes
20
+ # that have been mapped to the closest equivalent AM standard AVSResult codes
21
+ # Authorize.net's descriptions noted below
22
+ STANDARD_AVS_CODE_MAPPING = {
23
+ 'A' => 'A', # Street Address: Match -- First 5 Digits of ZIP: No Match
24
+ 'B' => 'I', # Address not provided for AVS check or street address match, postal code could not be verified
25
+ 'E' => 'E', # AVS Error
26
+ 'G' => 'G', # Non U.S. Card Issuing Bank
27
+ 'N' => 'N', # Street Address: No Match -- First 5 Digits of ZIP: No Match
28
+ 'P' => 'I', # AVS not applicable for this transaction
29
+ 'R' => 'R', # Retry, System Is Unavailable
30
+ 'S' => 'S', # AVS Not Supported by Card Issuing Bank
31
+ 'U' => 'U', # Address Information For This Cardholder Is Unavailable
32
+ 'W' => 'W', # Street Address: No Match -- All 9 Digits of ZIP: Match
33
+ 'X' => 'X', # Street Address: Match -- All 9 Digits of ZIP: Match
34
+ 'Y' => 'Y', # Street Address: Match - First 5 Digits of ZIP: Match
35
+ 'Z' => 'Z' # Street Address: No Match - First 5 Digits of ZIP: Match
36
+ }
37
+
38
+ STANDARD_ERROR_CODE_MAPPING = {
39
+ '2127' => STANDARD_ERROR_CODE[:incorrect_address],
40
+ '22' => STANDARD_ERROR_CODE[:card_declined],
41
+ '227' => STANDARD_ERROR_CODE[:incorrect_address],
42
+ '23' => STANDARD_ERROR_CODE[:card_declined],
43
+ '2315' => STANDARD_ERROR_CODE[:invalid_number],
44
+ '2316' => STANDARD_ERROR_CODE[:invalid_expiry_date],
45
+ '2317' => STANDARD_ERROR_CODE[:expired_card],
46
+ '235' => STANDARD_ERROR_CODE[:processing_error],
47
+ '237' => STANDARD_ERROR_CODE[:invalid_number],
48
+ '24' => STANDARD_ERROR_CODE[:pickup_card],
49
+ '244' => STANDARD_ERROR_CODE[:incorrect_cvc],
50
+ '300' => STANDARD_ERROR_CODE[:config_error],
51
+ '3153' => STANDARD_ERROR_CODE[:processing_error],
52
+ '3155' => STANDARD_ERROR_CODE[:unsupported_feature],
53
+ '36' => STANDARD_ERROR_CODE[:incorrect_number],
54
+ '37' => STANDARD_ERROR_CODE[:invalid_expiry_date],
55
+ '378' => STANDARD_ERROR_CODE[:invalid_cvc],
56
+ '38' => STANDARD_ERROR_CODE[:expired_card],
57
+ '384' => STANDARD_ERROR_CODE[:config_error]
58
+ }
59
+
60
+ MARKET_TYPE = {
61
+ moto: '1',
62
+ retail: '2'
63
+ }
64
+
65
+ DEVICE_TYPE = {
66
+ unknown: '1',
67
+ unattended_terminal: '2',
68
+ self_service_terminal: '3',
69
+ electronic_cash_register: '4',
70
+ personal_computer_terminal: '5',
71
+ airpay: '6',
72
+ wireless_pos: '7',
73
+ website: '8',
74
+ dial_terminal: '9',
75
+ virtual_terminal: '10'
76
+ }
77
+
78
+ class_attribute :duplicate_window
79
+
80
+ APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
81
+ TRANSACTION_ALREADY_ACTIONED = %w(310 311)
82
+
83
+ CARD_CODE_ERRORS = %w(N S)
84
+ AVS_ERRORS = %w(A E I N R W Z)
85
+ AVS_REASON_CODES = %w(27 45)
86
+
87
+ TRACKS = {
88
+ 1 => /^%(?<format_code>.)(?<pan>[\d]{1,19}+)\^(?<name>.{2,26})\^(?<expiration>[\d]{0,4}|\^)(?<service_code>[\d]{0,3}|\^)(?<discretionary_data>.*)\?\Z/,
89
+ 2 => /\A;(?<pan>[\d]{1,19}+)=(?<expiration>[\d]{0,4}|=)(?<service_code>[\d]{0,3}|=)(?<discretionary_data>.*)\?\Z/
90
+ }.freeze
91
+
92
+ APPLE_PAY_DATA_DESCRIPTOR = 'COMMON.APPLE.INAPP.PAYMENT'
93
+ PAYMENT_METHOD_NOT_SUPPORTED_ERROR = '155'
94
+ INELIGIBLE_FOR_ISSUING_CREDIT_ERROR = '54'
95
+
96
+ def initialize(options = {})
97
+ requires!(options, :login, :password)
98
+ super
99
+ end
100
+
101
+ def purchase(amount, payment, options = {})
102
+ if payment.is_a?(String)
103
+ commit(:cim_purchase, options) do |xml|
104
+ add_cim_auth_purchase(xml, 'profileTransAuthCapture', amount, payment, options)
105
+ end
106
+ else
107
+ commit(:purchase) do |xml|
108
+ add_auth_purchase(xml, 'authCaptureTransaction', amount, payment, options)
109
+ end
110
+ end
111
+ end
112
+
113
+ def authorize(amount, payment, options = {})
114
+ if payment.is_a?(String)
115
+ commit(:cim_authorize, options) do |xml|
116
+ add_cim_auth_purchase(xml, 'profileTransAuthOnly', amount, payment, options)
117
+ end
118
+ else
119
+ commit(:authorize) do |xml|
120
+ add_auth_purchase(xml, 'authOnlyTransaction', amount, payment, options)
121
+ end
122
+ end
123
+ end
124
+
125
+ def capture(amount, authorization, options = {})
126
+ if auth_was_for_cim?(authorization)
127
+ cim_capture(amount, authorization, options)
128
+ else
129
+ normal_capture(amount, authorization, options)
130
+ end
131
+ end
132
+
133
+ def refund(amount, authorization, options = {})
134
+ response =
135
+ if auth_was_for_cim?(authorization)
136
+ cim_refund(amount, authorization, options)
137
+ else
138
+ normal_refund(amount, authorization, options)
139
+ end
140
+
141
+ return response if response.success?
142
+ return response unless options[:force_full_refund_if_unsettled]
143
+
144
+ if response.params['response_reason_code'] == INELIGIBLE_FOR_ISSUING_CREDIT_ERROR
145
+ void(authorization, options)
146
+ else
147
+ response
148
+ end
149
+ end
150
+
151
+ def void(authorization, options = {})
152
+ if auth_was_for_cim?(authorization)
153
+ cim_void(authorization, options)
154
+ else
155
+ normal_void(authorization, options)
156
+ end
157
+ end
158
+
159
+ def credit(amount, payment, options = {})
160
+ raise ArgumentError, 'Reference credits are not supported. Please supply the original credit card or use the #refund method.' if payment.is_a?(String)
161
+
162
+ commit(:credit) do |xml|
163
+ add_order_id(xml, options)
164
+ xml.transactionRequest do
165
+ xml.transactionType('refundTransaction')
166
+ xml.amount(amount(amount))
167
+
168
+ add_payment_source(xml, payment, options, :credit)
169
+ xml.refTransId(transaction_id_from(options[:transaction_id])) if options[:transaction_id]
170
+ add_invoice(xml, 'refundTransaction', options)
171
+ add_customer_data(xml, payment, options)
172
+ add_settings(xml, payment, options)
173
+ add_user_fields(xml, amount, options)
174
+ end
175
+ end
176
+ end
177
+
178
+ def verify(payment_method, options = {})
179
+ amount = amount_for_verify(options)
180
+
181
+ MultiResponse.run(:use_first_response) do |r|
182
+ r.process { authorize(amount, payment_method, options) }
183
+ r.process(:ignore_result) { void(r.authorization, options) } unless amount == 0
184
+ end
185
+ rescue ArgumentError => e
186
+ Response.new(false, e.message)
187
+ end
188
+
189
+ def amount_for_verify(options)
190
+ return 100 unless options[:verify_amount].present?
191
+
192
+ amount = options[:verify_amount]
193
+ raise ArgumentError.new 'verify_amount value must be an integer' unless amount.is_a?(Integer) && !amount.negative? || amount.is_a?(String) && amount.match?(/^\d+$/) && !amount.to_i.negative?
194
+ raise ArgumentError.new 'Billing address including zip code is required for a 0 amount verify' if amount.to_i.zero? && !validate_billing_address_values?(options)
195
+
196
+ amount.to_i
197
+ end
198
+
199
+ def validate_billing_address_values?(options)
200
+ options.dig(:billing_address, :zip).present? && options.dig(:billing_address, :address1).present?
201
+ end
202
+
203
+ def store(credit_card, options = {})
204
+ if options[:customer_profile_id]
205
+ create_customer_payment_profile(credit_card, options)
206
+ else
207
+ create_customer_profile(credit_card, options)
208
+ end
209
+ end
210
+
211
+ def unstore(authorization)
212
+ customer_profile_id, = split_authorization(authorization)
213
+
214
+ delete_customer_profile(customer_profile_id)
215
+ end
216
+
217
+ def verify_credentials
218
+ response = commit(:verify_credentials) {}
219
+ response.success?
220
+ end
221
+
222
+ def supports_scrubbing?
223
+ true
224
+ end
225
+
226
+ def scrub(transcript)
227
+ transcript.
228
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
229
+ gsub(%r((<transactionKey>).+(</transactionKey>)), '\1[FILTERED]\2').
230
+ gsub(%r((<cardNumber>).+(</cardNumber>)), '\1[FILTERED]\2').
231
+ gsub(%r((<cardCode>).+(</cardCode>)), '\1[FILTERED]\2').
232
+ gsub(%r((<track1>).+(</track1>)), '\1[FILTERED]\2').
233
+ gsub(%r((<track2>).+(</track2>)), '\1[FILTERED]\2').
234
+ gsub(/(<routingNumber>).+(<\/routingNumber>)/, '\1[FILTERED]\2').
235
+ gsub(/(<accountNumber>).+(<\/accountNumber>)/, '\1[FILTERED]\2').
236
+ gsub(%r((<cryptogram>).+(</cryptogram>)), '\1[FILTERED]\2')
237
+ end
238
+
239
+ def supports_network_tokenization?
240
+ card = Billing::NetworkTokenizationCreditCard.new({
241
+ number: '4111111111111111',
242
+ month: 12,
243
+ year: 20,
244
+ first_name: 'John',
245
+ last_name: 'Smith',
246
+ brand: 'visa',
247
+ payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk='
248
+ })
249
+
250
+ request = post_data(:authorize) do |xml|
251
+ add_auth_purchase(xml, 'authOnlyTransaction', 1, card, {})
252
+ end
253
+ raw_response = ssl_post(url, request, headers)
254
+ response = parse(:authorize, raw_response)
255
+ response[:response_reason_code].to_s != PAYMENT_METHOD_NOT_SUPPORTED_ERROR
256
+ end
257
+
258
+ private
259
+
260
+ def add_auth_purchase(xml, transaction_type, amount, payment, options)
261
+ add_order_id(xml, options)
262
+ xml.transactionRequest do
263
+ xml.transactionType(transaction_type)
264
+ xml.amount(amount(amount))
265
+ add_payment_source(xml, payment, options)
266
+ add_invoice(xml, transaction_type, options)
267
+ add_tax_fields(xml, options)
268
+ add_duty_fields(xml, options)
269
+ add_shipping_fields(xml, options)
270
+ add_tax_exempt_status(xml, options)
271
+ add_po_number(xml, options)
272
+ add_customer_data(xml, payment, options)
273
+ add_market_type_device_type(xml, payment, options)
274
+ add_settings(xml, payment, options)
275
+ add_user_fields(xml, amount, options)
276
+ add_ship_from_address(xml, options)
277
+ add_processing_options(xml, options)
278
+ add_subsequent_auth_information(xml, options)
279
+ end
280
+ end
281
+
282
+ def add_cim_auth_purchase(xml, transaction_type, amount, payment, options)
283
+ add_order_id(xml, options)
284
+ xml.transaction do
285
+ xml.send(transaction_type) do
286
+ xml.amount(amount(amount))
287
+ add_tax_fields(xml, options)
288
+ add_shipping_fields(xml, options)
289
+ add_duty_fields(xml, options)
290
+ add_payment_source(xml, payment, options)
291
+ add_invoice(xml, transaction_type, options)
292
+ add_tax_exempt_status(xml, options)
293
+ end
294
+ end
295
+ add_extra_options_for_cim(xml, options)
296
+ end
297
+
298
+ def cim_capture(amount, authorization, options)
299
+ commit(:cim_capture, options) do |xml|
300
+ add_order_id(xml, options)
301
+ xml.transaction do
302
+ xml.profileTransPriorAuthCapture do
303
+ xml.amount(amount(amount))
304
+ add_tax_fields(xml, options)
305
+ add_shipping_fields(xml, options)
306
+ add_duty_fields(xml, options)
307
+ xml.transId(transaction_id_from(authorization))
308
+ end
309
+ end
310
+ add_extra_options_for_cim(xml, options)
311
+ end
312
+ end
313
+
314
+ def normal_capture(amount, authorization, options)
315
+ commit(:capture) do |xml|
316
+ add_order_id(xml, options)
317
+ xml.transactionRequest do
318
+ xml.transactionType('priorAuthCaptureTransaction')
319
+ xml.amount(amount(amount))
320
+ add_tax_fields(xml, options)
321
+ add_duty_fields(xml, options)
322
+ add_shipping_fields(xml, options)
323
+ add_tax_exempt_status(xml, options)
324
+ add_po_number(xml, options)
325
+ xml.refTransId(transaction_id_from(authorization))
326
+ add_invoice(xml, 'capture', options)
327
+ add_user_fields(xml, amount, options)
328
+ end
329
+ end
330
+ end
331
+
332
+ def cim_refund(amount, authorization, options)
333
+ transaction_id, card_number, = split_authorization(authorization)
334
+
335
+ commit(:cim_refund, options) do |xml|
336
+ add_order_id(xml, options)
337
+ xml.transaction do
338
+ xml.profileTransRefund do
339
+ xml.amount(amount(amount))
340
+ add_tax_fields(xml, options)
341
+ add_shipping_fields(xml, options)
342
+ add_duty_fields(xml, options)
343
+ xml.creditCardNumberMasked(card_number)
344
+ add_invoice(xml, 'profileTransRefund', options)
345
+ xml.transId(transaction_id)
346
+ end
347
+ end
348
+ add_extra_options_for_cim(xml, options)
349
+ end
350
+ end
351
+
352
+ def normal_refund(amount, authorization, options)
353
+ transaction_id, card_number, = split_authorization(authorization)
354
+
355
+ commit(:refund) do |xml|
356
+ xml.transactionRequest do
357
+ xml.transactionType('refundTransaction')
358
+ xml.amount(amount.nil? ? 0 : amount(amount))
359
+ xml.payment do
360
+ if options[:routing_number]
361
+ xml.bankAccount do
362
+ xml.accountType(options[:account_type])
363
+ xml.routingNumber(options[:routing_number])
364
+ xml.accountNumber(options[:account_number])
365
+ xml.nameOnAccount(truncate("#{options[:first_name]} #{options[:last_name]}", 22))
366
+ end
367
+ else
368
+ xml.creditCard do
369
+ xml.cardNumber(card_number || options[:card_number])
370
+ xml.expirationDate('XXXX')
371
+ end
372
+ end
373
+ end
374
+ xml.refTransId(transaction_id)
375
+
376
+ add_invoice(xml, 'refundTransaction', options)
377
+ add_tax_fields(xml, options)
378
+ add_duty_fields(xml, options)
379
+ add_shipping_fields(xml, options)
380
+ add_tax_exempt_status(xml, options)
381
+ add_po_number(xml, options)
382
+ add_customer_data(xml, nil, options)
383
+ add_user_fields(xml, amount, options)
384
+ end
385
+ end
386
+ end
387
+
388
+ def cim_void(authorization, options)
389
+ commit(:cim_void, options) do |xml|
390
+ add_order_id(xml, options)
391
+ xml.transaction do
392
+ xml.profileTransVoid do
393
+ xml.transId(transaction_id_from(authorization))
394
+ end
395
+ end
396
+ add_extra_options_for_cim(xml, options)
397
+ end
398
+ end
399
+
400
+ def normal_void(authorization, options)
401
+ commit(:void) do |xml|
402
+ add_order_id(xml, options)
403
+ xml.transactionRequest do
404
+ xml.transactionType('voidTransaction')
405
+ xml.refTransId(transaction_id_from(authorization))
406
+ end
407
+ end
408
+ end
409
+
410
+ def add_payment_source(xml, source, options, action = nil)
411
+ return unless source
412
+
413
+ if source.is_a?(String)
414
+ add_token_payment_method(xml, source, options)
415
+ elsif card_brand(source) == 'check'
416
+ add_check(xml, source)
417
+ elsif card_brand(source) == 'apple_pay'
418
+ add_apple_pay_payment_token(xml, source)
419
+ else
420
+ add_credit_card(xml, source, action)
421
+ end
422
+ end
423
+
424
+ def camel_case_lower(key)
425
+ String(key).split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
426
+ end
427
+
428
+ def add_settings(xml, source, options)
429
+ xml.transactionSettings do
430
+ if options[:recurring] || subsequent_recurring_transaction?(options)
431
+ xml.setting do
432
+ xml.settingName('recurringBilling')
433
+ xml.settingValue('true')
434
+ end
435
+ end
436
+ if options[:disable_partial_auth]
437
+ xml.setting do
438
+ xml.settingName('allowPartialAuth')
439
+ xml.settingValue('false')
440
+ end
441
+ end
442
+ if options[:duplicate_window]
443
+ set_duplicate_window(xml, options[:duplicate_window])
444
+ elsif self.class.duplicate_window
445
+ ActiveMerchant.deprecated 'Using the duplicate_window class_attribute is deprecated. Use the transaction options hash instead.'
446
+ set_duplicate_window(xml, self.class.duplicate_window)
447
+ end
448
+ if options.key?(:email_customer)
449
+ xml.setting do
450
+ xml.settingName('emailCustomer')
451
+ xml.settingValue(options[:email_customer] ? 'true' : 'false')
452
+ end
453
+ end
454
+ if options[:header_email_receipt]
455
+ xml.setting do
456
+ xml.settingName('headerEmailReceipt')
457
+ xml.settingValue(options[:header_email_receipt])
458
+ end
459
+ end
460
+ if options[:test_request]
461
+ xml.setting do
462
+ xml.settingName('testRequest')
463
+ xml.settingValue('1')
464
+ end
465
+ end
466
+ end
467
+ end
468
+
469
+ def set_duplicate_window(xml, value)
470
+ xml.setting do
471
+ xml.settingName('duplicateWindow')
472
+ xml.settingValue(value)
473
+ end
474
+ end
475
+
476
+ def add_user_fields(xml, amount, options)
477
+ xml.userFields do
478
+ if currency = (options[:currency] || currency(amount))
479
+ xml.userField do
480
+ xml.name('x_currency_code')
481
+ xml.value(currency)
482
+ end
483
+ end
484
+ if application_id.present?
485
+ xml.userField do
486
+ xml.name('x_solution_id')
487
+ xml.value(application_id)
488
+ end
489
+ end
490
+ end
491
+ end
492
+
493
+ def add_credit_card(xml, credit_card, action)
494
+ if credit_card.track_data
495
+ add_swipe_data(xml, credit_card)
496
+ else
497
+ xml.payment do
498
+ xml.creditCard do
499
+ xml.cardNumber(truncate(credit_card.number, 16))
500
+ xml.expirationDate(format(credit_card.month, :two_digits) + '/' + format(credit_card.year, :four_digits))
501
+ xml.cardCode(credit_card.verification_value) if credit_card.valid_card_verification_value?(credit_card.verification_value, credit_card.brand)
502
+ xml.cryptogram(credit_card.payment_cryptogram) if credit_card.is_a?(NetworkTokenizationCreditCard) && action != :credit
503
+ end
504
+ end
505
+ end
506
+ end
507
+
508
+ def add_swipe_data(xml, credit_card)
509
+ TRACKS.each do |key, regex|
510
+ if regex.match?(credit_card.track_data)
511
+ @valid_track_data = true
512
+ xml.payment do
513
+ xml.trackData do
514
+ xml.public_send(:"track#{key}", credit_card.track_data)
515
+ end
516
+ end
517
+ end
518
+ end
519
+ end
520
+
521
+ def add_token_payment_method(xml, token, options)
522
+ customer_profile_id, customer_payment_profile_id, = split_authorization(token)
523
+ customer_profile_id = options[:customer_profile_id] if options[:customer_profile_id]
524
+ customer_payment_profile_id = options[:customer_payment_profile_id] if options[:customer_payment_profile_id]
525
+ xml.customerProfileId(customer_profile_id)
526
+ xml.customerPaymentProfileId(customer_payment_profile_id)
527
+ end
528
+
529
+ def add_apple_pay_payment_token(xml, apple_pay_payment_token)
530
+ xml.payment do
531
+ xml.opaqueData do
532
+ xml.dataDescriptor(APPLE_PAY_DATA_DESCRIPTOR)
533
+ xml.dataValue(Base64.strict_encode64(apple_pay_payment_token.payment_data.to_json))
534
+ end
535
+ end
536
+ end
537
+
538
+ def add_market_type_device_type(xml, payment, options)
539
+ return if payment.is_a?(String) || card_brand(payment) == 'check' || card_brand(payment) == 'apple_pay'
540
+
541
+ if valid_track_data
542
+ xml.retail do
543
+ xml.marketType(options[:market_type] || MARKET_TYPE[:retail])
544
+ xml.deviceType(options[:device_type] || DEVICE_TYPE[:wireless_pos])
545
+ end
546
+ elsif payment.manual_entry
547
+ xml.retail do
548
+ xml.marketType(options[:market_type] || MARKET_TYPE[:moto])
549
+ end
550
+ else
551
+ if options[:market_type]
552
+ xml.retail do
553
+ xml.marketType(options[:market_type])
554
+ end
555
+ end
556
+ end
557
+ end
558
+
559
+ def valid_track_data
560
+ @valid_track_data ||= false
561
+ end
562
+
563
+ def add_check(xml, check)
564
+ xml.payment do
565
+ xml.bankAccount do
566
+ xml.accountType(check.account_type)
567
+ xml.routingNumber(check.routing_number)
568
+ xml.accountNumber(check.account_number)
569
+ xml.nameOnAccount(truncate(check.name, 22))
570
+ xml.bankName(check.bank_name)
571
+ xml.checkNumber(check.number)
572
+ end
573
+ end
574
+ end
575
+
576
+ def add_customer_data(xml, payment_source, options)
577
+ xml.customer do
578
+ xml.id(options[:customer]) unless empty?(options[:customer]) || options[:customer] !~ /^\w+$/
579
+ xml.email(options[:email]) unless empty?(options[:email])
580
+ end
581
+
582
+ add_billing_address(xml, payment_source, options)
583
+ add_shipping_address(xml, options)
584
+
585
+ xml.customerIP(options[:ip]) unless empty?(options[:ip])
586
+
587
+ if !empty?(options.fetch(:three_d_secure, {})) || options[:authentication_indicator] || options[:cardholder_authentication_value]
588
+ xml.cardholderAuthentication do
589
+ three_d_secure = options.fetch(:three_d_secure, {})
590
+ xml.authenticationIndicator(
591
+ options[:authentication_indicator] || three_d_secure[:eci]
592
+ )
593
+ xml.cardholderAuthenticationValue(
594
+ options[:cardholder_authentication_value] || three_d_secure[:cavv]
595
+ )
596
+ end
597
+ end
598
+ end
599
+
600
+ def add_billing_address(xml, payment_source, options)
601
+ address = options[:billing_address] || options[:address] || {}
602
+
603
+ xml.billTo do
604
+ first_name, last_name = names_from(payment_source, address, options)
605
+ state = state_from(address, options)
606
+ full_address = "#{address[:address1]} #{address[:address2]}".strip
607
+ phone = address[:phone] || address[:phone_number] || ''
608
+
609
+ xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
610
+ xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
611
+ xml.company(truncate(address[:company], 50)) unless empty?(address[:company])
612
+ xml.address(truncate(full_address, 60))
613
+ xml.city(truncate(address[:city], 40))
614
+ xml.state(truncate(state, 40))
615
+ xml.zip(truncate((address[:zip] || options[:zip]), 20))
616
+ xml.country(truncate(address[:country], 60))
617
+ xml.phoneNumber(truncate(phone, 25)) unless empty?(phone)
618
+ xml.faxNumber(truncate(address[:fax], 25)) unless empty?(address[:fax])
619
+ end
620
+ end
621
+
622
+ def add_shipping_address(xml, options, root_node = 'shipTo')
623
+ address = options[:shipping_address] || options[:address]
624
+ return unless address
625
+
626
+ xml.send(root_node) do
627
+ first_name, last_name =
628
+ if address[:name]
629
+ split_names(address[:name])
630
+ else
631
+ [address[:first_name], address[:last_name]]
632
+ end
633
+ full_address = "#{address[:address1]} #{address[:address2]}".strip
634
+
635
+ xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
636
+ xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
637
+ xml.company(truncate(address[:company], 50)) unless empty?(address[:company])
638
+ xml.address(truncate(full_address, 60))
639
+ xml.city(truncate(address[:city], 40))
640
+ xml.state(truncate(address[:state], 40))
641
+ xml.zip(truncate(address[:zip], 20))
642
+ xml.country(truncate(address[:country], 60))
643
+ end
644
+ end
645
+
646
+ def add_ship_from_address(xml, options, root_node = 'shipFrom')
647
+ address = options[:ship_from_address]
648
+ return unless address
649
+
650
+ xml.send(root_node) do
651
+ xml.zip(truncate(address[:zip], 20)) unless empty?(address[:zip])
652
+ xml.country(truncate(address[:country], 60)) unless empty?(address[:country])
653
+ end
654
+ end
655
+
656
+ def add_order_id(xml, options)
657
+ xml.refId(truncate(options[:order_id], 20))
658
+ end
659
+
660
+ def add_invoice(xml, transaction_type, options)
661
+ xml.order do
662
+ xml.invoiceNumber(truncate(options[:order_id], 20))
663
+ xml.description(truncate(options[:description], 255))
664
+ xml.purchaseOrderNumber(options[:po_number]) if options[:po_number] && transaction_type.start_with?('profileTrans')
665
+ xml.summaryCommodityCode(truncate(options[:summary_commodity_code], 4)) if options[:summary_commodity_code] && !transaction_type.start_with?('profileTrans')
666
+ end
667
+
668
+ # Authorize.net API requires lineItems to be placed directly after order tag
669
+ if options[:line_items]
670
+ xml.lineItems do
671
+ options[:line_items].each do |line_item|
672
+ xml.lineItem do
673
+ line_item.each do |key, value|
674
+ xml.send(camel_case_lower(key), value)
675
+ end
676
+ end
677
+ end
678
+ end
679
+ end
680
+ end
681
+
682
+ def add_tax_fields(xml, options)
683
+ tax = options[:tax]
684
+ if tax.is_a?(Hash)
685
+ xml.tax do
686
+ xml.amount(amount(tax[:amount].to_i))
687
+ xml.name(tax[:name])
688
+ xml.description(tax[:description])
689
+ end
690
+ end
691
+ end
692
+
693
+ def add_duty_fields(xml, options)
694
+ duty = options[:duty]
695
+ if duty.is_a?(Hash)
696
+ xml.duty do
697
+ xml.amount(amount(duty[:amount].to_i))
698
+ xml.name(duty[:name])
699
+ xml.description(duty[:description])
700
+ end
701
+ end
702
+ end
703
+
704
+ def add_shipping_fields(xml, options)
705
+ shipping = options[:shipping]
706
+ if shipping.is_a?(Hash)
707
+ xml.shipping do
708
+ xml.amount(amount(shipping[:amount].to_i))
709
+ xml.name(shipping[:name])
710
+ xml.description(shipping[:description])
711
+ end
712
+ end
713
+ end
714
+
715
+ def add_tax_exempt_status(xml, options)
716
+ xml.taxExempt(options[:tax_exempt]) if options[:tax_exempt]
717
+ end
718
+
719
+ def add_po_number(xml, options)
720
+ xml.poNumber(options[:po_number]) if options[:po_number]
721
+ end
722
+
723
+ def add_extra_options_for_cim(xml, options)
724
+ xml.extraOptions("x_delim_char=#{options[:delimiter]}") if options[:delimiter]
725
+ end
726
+
727
+ def add_processing_options(xml, options)
728
+ return unless options[:stored_credential]
729
+
730
+ xml.processingOptions do
731
+ if options[:stored_credential][:initial_transaction] && options[:stored_credential][:reason_type] == 'recurring'
732
+ xml.isFirstRecurringPayment 'true'
733
+ elsif options[:stored_credential][:initial_transaction]
734
+ xml.isFirstSubsequentAuth 'true'
735
+ elsif options[:stored_credential][:initiator] == 'cardholder'
736
+ xml.isStoredCredentials 'true'
737
+ else
738
+ xml.isSubsequentAuth 'true'
739
+ end
740
+ end
741
+ end
742
+
743
+ def add_subsequent_auth_information(xml, options)
744
+ return unless options.dig(:stored_credential, :initiator) == 'merchant'
745
+
746
+ xml.subsequentAuthInformation do
747
+ xml.reason options[:stored_credential_reason_type_override] if options[:stored_credential_reason_type_override]
748
+ xml.originalNetworkTransId options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
749
+ end
750
+ end
751
+
752
+ def create_customer_payment_profile(credit_card, options)
753
+ commit(:cim_store_update, options) do |xml|
754
+ xml.customerProfileId options[:customer_profile_id]
755
+ xml.paymentProfile do
756
+ add_billing_address(xml, credit_card, options)
757
+ xml.payment do
758
+ xml.creditCard do
759
+ xml.cardNumber(truncate(credit_card.number, 16))
760
+ xml.expirationDate(format(credit_card.year, :four_digits) + '-' + format(credit_card.month, :two_digits))
761
+ xml.cardCode(credit_card.verification_value) if credit_card.verification_value
762
+ end
763
+ end
764
+ end
765
+ end
766
+ end
767
+
768
+ def create_customer_profile(credit_card, options)
769
+ commit(:cim_store, options) do |xml|
770
+ xml.profile do
771
+ xml.merchantCustomerId(truncate(options[:merchant_customer_id], 20) || SecureRandom.hex(10))
772
+ xml.description(truncate(options[:description], 255)) unless empty?(options[:description])
773
+ xml.email(options[:email]) unless empty?(options[:email])
774
+
775
+ xml.paymentProfiles do
776
+ xml.customerType('individual')
777
+ add_billing_address(xml, credit_card, options)
778
+ add_shipping_address(xml, options, 'shipToList')
779
+ xml.payment do
780
+ xml.creditCard do
781
+ xml.cardNumber(truncate(credit_card.number, 16))
782
+ xml.expirationDate(format(credit_card.year, :four_digits) + '-' + format(credit_card.month, :two_digits))
783
+ xml.cardCode(credit_card.verification_value) if credit_card.verification_value
784
+ end
785
+ end
786
+ end
787
+ end
788
+ end
789
+ end
790
+
791
+ def delete_customer_profile(customer_profile_id)
792
+ commit(:cim_store_delete_customer, options) do |xml|
793
+ xml.customerProfileId(customer_profile_id)
794
+ end
795
+ end
796
+
797
+ def names_from(payment_source, address, options)
798
+ if payment_source && !payment_source.is_a?(PaymentToken) && !payment_source.is_a?(String)
799
+ first_name, last_name = split_names(address[:name])
800
+ [(payment_source.first_name || first_name), (payment_source.last_name || last_name)]
801
+ else
802
+ [options[:first_name], options[:last_name]]
803
+ end
804
+ end
805
+
806
+ def state_from(address, options)
807
+ if %w[US CA].include?(address[:country])
808
+ address[:state] || 'NC'
809
+ else
810
+ address[:state] || 'n/a'
811
+ end
812
+ end
813
+
814
+ def subsequent_recurring_transaction?(options)
815
+ options.dig(:stored_credential, :reason_type) == 'recurring' && !options.dig(:stored_credential, :initial_transaction)
816
+ end
817
+
818
+ def headers
819
+ { 'Content-Type' => 'text/xml' }
820
+ end
821
+
822
+ def url
823
+ test? ? test_url : live_url
824
+ end
825
+
826
+ def parse(action, raw_response, options = {})
827
+ if cim_action?(action) || action == :verify_credentials
828
+ parse_cim(raw_response, options)
829
+ else
830
+ parse_normal(action, raw_response)
831
+ end
832
+ end
833
+
834
+ def commit(action, options = {}, &payload)
835
+ raw_response = ssl_post(url, post_data(action, &payload), headers)
836
+ response = parse(action, raw_response, options)
837
+
838
+ avs_result_code = response[:avs_result_code].upcase if response[:avs_result_code]
839
+ avs_result = AVSResult.new(code: STANDARD_AVS_CODE_MAPPING[avs_result_code])
840
+ cvv_result = CVVResult.new(response[:card_code])
841
+ if using_live_gateway_in_test_mode?(response)
842
+ Response.new(false, 'Using a live Authorize.net account in Test Mode is not permitted.')
843
+ else
844
+ Response.new(
845
+ success_from(action, response),
846
+ message_from(action, response, avs_result, cvv_result),
847
+ response,
848
+ authorization: authorization_from(action, response),
849
+ test: test?,
850
+ avs_result: avs_result,
851
+ cvv_result: cvv_result,
852
+ fraud_review: fraud_review?(response),
853
+ error_code: map_error_code(response[:response_code], response[:response_reason_code])
854
+ )
855
+ end
856
+ end
857
+
858
+ def cim_action?(action)
859
+ action.to_s.start_with?('cim')
860
+ end
861
+
862
+ def post_data(action)
863
+ Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
864
+ xml.send(root_for(action), 'xmlns' => 'AnetApi/xml/v1/schema/AnetApiSchema.xsd') do
865
+ add_authentication(xml)
866
+ yield(xml)
867
+ end
868
+ end.to_xml(indent: 0)
869
+ end
870
+
871
+ def root_for(action)
872
+ if action == :cim_store
873
+ 'createCustomerProfileRequest'
874
+ elsif action == :cim_store_update
875
+ 'createCustomerPaymentProfileRequest'
876
+ elsif action == :cim_store_delete_customer
877
+ 'deleteCustomerProfileRequest'
878
+ elsif action == :verify_credentials
879
+ 'authenticateTestRequest'
880
+ elsif cim_action?(action)
881
+ 'createCustomerProfileTransactionRequest'
882
+ else
883
+ 'createTransactionRequest'
884
+ end
885
+ end
886
+
887
+ def add_authentication(xml)
888
+ xml.merchantAuthentication do
889
+ xml.name(@options[:login])
890
+ xml.transactionKey(@options[:password])
891
+ end
892
+ end
893
+
894
+ def parse_normal(action, body)
895
+ doc = Nokogiri::XML(body)
896
+ doc.remove_namespaces!
897
+
898
+ response = { action: action }
899
+
900
+ response[:response_code] = if (element = doc.at_xpath('//transactionResponse/responseCode'))
901
+ empty?(element.content) ? nil : element.content.to_i
902
+ end
903
+
904
+ if (element = doc.at_xpath('//errors/error'))
905
+ response[:response_reason_code] = element.at_xpath('errorCode').content[/0*(\d+)$/, 1]
906
+ response[:response_reason_text] = element.at_xpath('errorText').content.chomp('.')
907
+ elsif (element = doc.at_xpath('//transactionResponse/messages/message'))
908
+ response[:response_reason_code] = element.at_xpath('code').content[/0*(\d+)$/, 1]
909
+ response[:response_reason_text] = element.at_xpath('description').content.chomp('.')
910
+ elsif (element = doc.at_xpath('//messages/message'))
911
+ response[:response_reason_code] = element.at_xpath('code').content[/0*(\d+)$/, 1]
912
+ response[:response_reason_text] = element.at_xpath('text').content.chomp('.')
913
+ else
914
+ response[:response_reason_code] = nil
915
+ response[:response_reason_text] = ''
916
+ end
917
+
918
+ response[:avs_result_code] =
919
+ if (element = doc.at_xpath('//avsResultCode'))
920
+ empty?(element.content) ? nil : element.content
921
+ end
922
+
923
+ response[:transaction_id] =
924
+ if element = doc.at_xpath('//transId')
925
+ empty?(element.content) ? nil : element.content
926
+ end
927
+
928
+ response[:card_code] =
929
+ if element = doc.at_xpath('//cvvResultCode')
930
+ empty?(element.content) ? nil : element.content
931
+ end
932
+
933
+ response[:authorization_code] =
934
+ if element = doc.at_xpath('//authCode')
935
+ empty?(element.content) ? nil : element.content
936
+ end
937
+
938
+ response[:cardholder_authentication_code] =
939
+ if element = doc.at_xpath('//cavvResultCode')
940
+ empty?(element.content) ? nil : element.content
941
+ end
942
+
943
+ response[:account_number] =
944
+ if element = doc.at_xpath('//accountNumber')
945
+ empty?(element.content) ? nil : element.content[-4..-1]
946
+ end
947
+
948
+ response[:test_request] =
949
+ if element = doc.at_xpath('//testRequest')
950
+ empty?(element.content) ? nil : element.content
951
+ end
952
+
953
+ response[:full_response_code] =
954
+ if element = doc.at_xpath('//messages/message/code')
955
+ empty?(element.content) ? nil : element.content
956
+ end
957
+
958
+ response[:network_trans_id] =
959
+ if element = doc.at_xpath('//networkTransId')
960
+ empty?(element.content) ? nil : element.content
961
+ end
962
+
963
+ response
964
+ end
965
+
966
+ def parse_cim(body, options)
967
+ response = {}
968
+
969
+ doc = Nokogiri::XML(body).remove_namespaces!
970
+
971
+ if element = doc.at_xpath('//messages/message')
972
+ response[:message_code] = element.at_xpath('code').content[/0*(\d+)$/, 1]
973
+ response[:message_text] = element.at_xpath('text').content.chomp('.')
974
+ end
975
+
976
+ response[:result_code] =
977
+ if element = doc.at_xpath('//messages/resultCode')
978
+ empty?(element.content) ? nil : element.content
979
+ end
980
+
981
+ response[:test_request] =
982
+ if element = doc.at_xpath('//testRequest')
983
+ empty?(element.content) ? nil : element.content
984
+ end
985
+
986
+ response[:customer_profile_id] =
987
+ if element = doc.at_xpath('//customerProfileId')
988
+ empty?(element.content) ? nil : element.content
989
+ end
990
+
991
+ response[:customer_payment_profile_id] =
992
+ if element = doc.at_xpath('//customerPaymentProfileIdList/numericString')
993
+ empty?(element.content) ? nil : element.content
994
+ end
995
+
996
+ response[:customer_payment_profile_id] =
997
+ if element = doc.at_xpath('//customerPaymentProfileIdList/numericString') ||
998
+ doc.at_xpath('//customerPaymentProfileId')
999
+ empty?(element.content) ? nil : element.content
1000
+ end
1001
+
1002
+ response[:direct_response] =
1003
+ if element = doc.at_xpath('//directResponse')
1004
+ empty?(element.content) ? nil : element.content
1005
+ end
1006
+
1007
+ response.merge!(parse_direct_response_elements(response, options))
1008
+
1009
+ response
1010
+ end
1011
+
1012
+ def success_from(action, response)
1013
+ if cim?(action) || (action == :verify_credentials)
1014
+ response[:result_code] == 'Ok'
1015
+ else
1016
+ [APPROVED, FRAUD_REVIEW].include?(response[:response_code]) && TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
1017
+ end
1018
+ end
1019
+
1020
+ def message_from(action, response, avs_result, cvv_result)
1021
+ if response[:response_code] == DECLINED
1022
+ if CARD_CODE_ERRORS.include?(cvv_result.code)
1023
+ return cvv_result.message
1024
+ elsif AVS_REASON_CODES.include?(response[:response_reason_code]) && AVS_ERRORS.include?(avs_result.code)
1025
+ return avs_result.message
1026
+ end
1027
+ end
1028
+
1029
+ response[:response_reason_text] || response[:message_text]
1030
+ end
1031
+
1032
+ def authorization_from(action, response)
1033
+ if cim?(action)
1034
+ [response[:customer_profile_id], response[:customer_payment_profile_id], action].join('#')
1035
+ else
1036
+ [response[:transaction_id], response[:account_number], action].join('#')
1037
+ end
1038
+ end
1039
+
1040
+ def split_authorization(authorization)
1041
+ authorization.split('#')
1042
+ end
1043
+
1044
+ def cim?(action)
1045
+ (action == :cim_store) || (action == :cim_store_update) || (action == :cim_store_delete_customer)
1046
+ end
1047
+
1048
+ def transaction_id_from(authorization)
1049
+ transaction_id, = split_authorization(authorization)
1050
+ transaction_id
1051
+ end
1052
+
1053
+ def fraud_review?(response)
1054
+ (response[:response_code] == FRAUD_REVIEW)
1055
+ end
1056
+
1057
+ def using_live_gateway_in_test_mode?(response)
1058
+ !test? && response[:test_request] == '1'
1059
+ end
1060
+
1061
+ def map_error_code(response_code, response_reason_code)
1062
+ STANDARD_ERROR_CODE_MAPPING["#{response_code}#{response_reason_code}"]
1063
+ end
1064
+
1065
+ def auth_was_for_cim?(authorization)
1066
+ _, _, action = split_authorization(authorization)
1067
+ action && cim_action?(action)
1068
+ end
1069
+
1070
+ def parse_direct_response_elements(response, options)
1071
+ params = response[:direct_response]&.tr('"', '')
1072
+ return {} unless params
1073
+
1074
+ parts = params.split(options[:delimiter] || ',')
1075
+ {
1076
+ response_code: parts[0].to_i,
1077
+ response_subcode: parts[1],
1078
+ response_reason_code: parts[2],
1079
+ response_reason_text: parts[3],
1080
+ approval_code: parts[4],
1081
+ avs_result_code: parts[5],
1082
+ transaction_id: parts[6],
1083
+ invoice_number: parts[7],
1084
+ order_description: parts[8],
1085
+ amount: parts[9],
1086
+ method: parts[10],
1087
+ transaction_type: parts[11],
1088
+ customer_id: parts[12],
1089
+ first_name: parts[13],
1090
+ last_name: parts[14],
1091
+ company: parts[15],
1092
+ address: parts[16],
1093
+ city: parts[17],
1094
+ state: parts[18],
1095
+ zip_code: parts[19],
1096
+ country: parts[20],
1097
+ phone: parts[21],
1098
+ fax: parts[22],
1099
+ email_address: parts[23],
1100
+ ship_to_first_name: parts[24],
1101
+ ship_to_last_name: parts[25],
1102
+ ship_to_company: parts[26],
1103
+ ship_to_address: parts[27],
1104
+ ship_to_city: parts[28],
1105
+ ship_to_state: parts[29],
1106
+ ship_to_zip_code: parts[30],
1107
+ ship_to_country: parts[31],
1108
+ tax: parts[32],
1109
+ duty: parts[33],
1110
+ freight: parts[34],
1111
+ tax_exempt: parts[35],
1112
+ purchase_order_number: parts[36],
1113
+ md5_hash: parts[37],
1114
+ card_code: parts[38],
1115
+ cardholder_authentication_verification_response: parts[39],
1116
+ account_number: parts[50] || '',
1117
+ card_type: parts[51] || '',
1118
+ split_tender_id: parts[52] || '',
1119
+ requested_amount: parts[53] || '',
1120
+ balance_on_card: parts[54] || ''
1121
+ }
1122
+ end
1123
+ end
1124
+ end
1125
+ end