activemerchant 1.38.0 → 1.78.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (397) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1344 -3
  3. data/CONTRIBUTORS +154 -0
  4. data/README.md +157 -144
  5. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  6. data/lib/active_merchant/billing/base.rb +21 -17
  7. data/lib/active_merchant/billing/check.rb +32 -22
  8. data/lib/active_merchant/billing/compatibility.rb +120 -0
  9. data/lib/active_merchant/billing/credit_card.rb +215 -67
  10. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -1
  11. data/lib/active_merchant/billing/credit_card_methods.rb +149 -52
  12. data/lib/active_merchant/billing/cvv_result.rb +15 -15
  13. data/lib/active_merchant/billing/gateway.rb +170 -24
  14. data/lib/active_merchant/billing/gateways/adyen.rb +284 -0
  15. data/lib/active_merchant/billing/gateways/allied_wallet.rb +206 -0
  16. data/lib/active_merchant/billing/gateways/authorize_net.rb +899 -606
  17. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +43 -18
  19. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  20. data/lib/active_merchant/billing/gateways/balanced.rb +134 -346
  21. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  22. data/lib/active_merchant/billing/gateways/banwire.rb +13 -2
  23. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +325 -0
  24. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  25. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +96 -15
  26. data/lib/active_merchant/billing/gateways/beanstream.rb +52 -9
  27. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +12 -8
  28. data/lib/active_merchant/billing/gateways/blue_pay.rb +520 -501
  29. data/lib/active_merchant/billing/gateways/blue_snap.rb +343 -0
  30. data/lib/active_merchant/billing/gateways/bogus.rb +94 -50
  31. data/lib/active_merchant/billing/gateways/borgun.rb +222 -0
  32. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  33. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +14 -2
  34. data/lib/active_merchant/billing/gateways/braintree.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/braintree_blue.rb +372 -137
  36. data/lib/active_merchant/billing/gateways/braintree_orange.rb +4 -4
  37. data/lib/active_merchant/billing/gateways/bridge_pay.rb +245 -0
  38. data/lib/active_merchant/billing/gateways/cams.rb +230 -0
  39. data/lib/active_merchant/billing/gateways/card_connect.rb +286 -0
  40. data/lib/active_merchant/billing/gateways/card_stream.rb +269 -118
  41. data/lib/active_merchant/billing/gateways/cardknox.rb +328 -0
  42. data/lib/active_merchant/billing/gateways/cardprocess.rb +254 -0
  43. data/lib/active_merchant/billing/gateways/cashnet.rb +219 -0
  44. data/lib/active_merchant/billing/gateways/cc5.rb +45 -0
  45. data/lib/active_merchant/billing/gateways/cecabank.rb +239 -0
  46. data/lib/active_merchant/billing/gateways/cenpos.rb +327 -0
  47. data/lib/active_merchant/billing/gateways/checkout.rb +214 -0
  48. data/lib/active_merchant/billing/gateways/checkout_v2.rb +226 -0
  49. data/lib/active_merchant/billing/gateways/citrus_pay.rb +23 -0
  50. data/lib/active_merchant/billing/gateways/clearhaus.rb +222 -0
  51. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  52. data/lib/active_merchant/billing/gateways/conekta.rb +224 -0
  53. data/lib/active_merchant/billing/gateways/creditcall.rb +272 -0
  54. data/lib/active_merchant/billing/gateways/credorax.rb +345 -0
  55. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  56. data/lib/active_merchant/billing/gateways/cyber_source.rb +228 -98
  57. data/lib/active_merchant/billing/gateways/data_cash.rb +41 -314
  58. data/lib/active_merchant/billing/gateways/dibs.rb +205 -0
  59. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  60. data/lib/active_merchant/billing/gateways/ebanx.rb +296 -0
  61. data/lib/active_merchant/billing/gateways/efsnet.rb +3 -14
  62. data/lib/active_merchant/billing/gateways/elavon.rb +143 -142
  63. data/lib/active_merchant/billing/gateways/element.rb +356 -0
  64. data/lib/active_merchant/billing/gateways/epay.rb +23 -12
  65. data/lib/active_merchant/billing/gateways/eway.rb +12 -12
  66. data/lib/active_merchant/billing/gateways/eway_managed.rb +1 -1
  67. data/lib/active_merchant/billing/gateways/eway_rapid.rb +417 -204
  68. data/lib/active_merchant/billing/gateways/exact.rb +10 -1
  69. data/lib/active_merchant/billing/gateways/ezic.rb +196 -0
  70. data/lib/active_merchant/billing/gateways/fat_zebra.rb +65 -37
  71. data/lib/active_merchant/billing/gateways/federated_canada.rb +1 -8
  72. data/lib/active_merchant/billing/gateways/finansbank.rb +3 -2
  73. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  74. data/lib/active_merchant/billing/gateways/first_pay.rb +109 -124
  75. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +155 -29
  76. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  77. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  78. data/lib/active_merchant/billing/gateways/forte.rb +256 -0
  79. data/lib/active_merchant/billing/gateways/garanti.rb +11 -5
  80. data/lib/active_merchant/billing/gateways/global_collect.rb +334 -0
  81. data/lib/active_merchant/billing/gateways/global_transport.rb +194 -0
  82. data/lib/active_merchant/billing/gateways/hps.rb +305 -0
  83. data/lib/active_merchant/billing/gateways/iats_payments.rb +271 -16
  84. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +2 -5
  85. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +0 -0
  86. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +1 -1
  87. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  88. data/lib/active_merchant/billing/gateways/inspire.rb +8 -10
  89. data/lib/active_merchant/billing/gateways/instapay.rb +0 -0
  90. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  91. data/lib/active_merchant/billing/gateways/iridium.rb +210 -4
  92. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  93. data/lib/active_merchant/billing/gateways/jetpay.rb +176 -49
  94. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +437 -0
  95. data/lib/active_merchant/billing/gateways/komoju.rb +115 -0
  96. data/lib/active_merchant/billing/gateways/kushki.rb +227 -0
  97. data/lib/active_merchant/billing/gateways/latitude19.rb +416 -0
  98. data/lib/active_merchant/billing/gateways/linkpoint.rb +17 -13
  99. data/lib/active_merchant/billing/gateways/litle.rb +329 -439
  100. data/lib/active_merchant/billing/gateways/mastercard.rb +268 -0
  101. data/lib/active_merchant/billing/gateways/maxipago.rb +220 -0
  102. data/lib/active_merchant/billing/gateways/mercado_pago.rb +262 -0
  103. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +15 -7
  104. data/lib/active_merchant/billing/gateways/merchant_one.rb +0 -1
  105. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  106. data/lib/active_merchant/billing/gateways/merchant_ware.rb +12 -15
  107. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +24 -13
  108. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +21 -14
  109. data/lib/active_merchant/billing/gateways/mercury.rb +74 -29
  110. data/lib/active_merchant/billing/gateways/metrics_global.rb +2 -21
  111. data/lib/active_merchant/billing/gateways/micropayment.rb +185 -0
  112. data/lib/active_merchant/billing/gateways/migs.rb +74 -13
  113. data/lib/active_merchant/billing/gateways/modern_payments.rb +1 -1
  114. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +1 -3
  115. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  116. data/lib/active_merchant/billing/gateways/moneris.rb +119 -36
  117. data/lib/active_merchant/billing/gateways/moneris_us.rb +146 -45
  118. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  119. data/lib/active_merchant/billing/gateways/nab_transact.rb +78 -53
  120. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
  121. data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
  122. data/lib/active_merchant/billing/gateways/netbanx.rb +289 -0
  123. data/lib/active_merchant/billing/gateways/netbilling.rb +61 -26
  124. data/lib/active_merchant/billing/gateways/netpay.rb +1 -1
  125. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  126. data/lib/active_merchant/billing/gateways/nmi.rb +265 -10
  127. data/lib/active_merchant/billing/gateways/ogone.rb +85 -27
  128. data/lib/active_merchant/billing/gateways/omise.rb +324 -0
  129. data/lib/active_merchant/billing/gateways/openpay.rb +227 -0
  130. data/lib/active_merchant/billing/gateways/opp.rb +372 -0
  131. data/lib/active_merchant/billing/gateways/optimal_payment.rb +59 -28
  132. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +22 -21
  133. data/lib/active_merchant/billing/gateways/orbital.rb +346 -56
  134. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  135. data/lib/active_merchant/billing/gateways/pagarme.rb +248 -0
  136. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  137. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  138. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +30 -14
  139. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  140. data/lib/active_merchant/billing/gateways/pay_junction.rb +19 -25
  141. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
  142. data/lib/active_merchant/billing/gateways/pay_secure.rb +0 -7
  143. data/lib/active_merchant/billing/gateways/paybox_direct.rb +16 -12
  144. data/lib/active_merchant/billing/gateways/payeezy.rb +386 -0
  145. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  146. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +38 -17
  147. data/lib/active_merchant/billing/gateways/payflow.rb +100 -19
  148. data/lib/active_merchant/billing/gateways/payflow_express.rb +22 -22
  149. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +2 -2
  150. data/lib/active_merchant/billing/gateways/payflow_uk.rb +6 -6
  151. data/lib/active_merchant/billing/gateways/payment_express.rb +15 -3
  152. data/lib/active_merchant/billing/gateways/paymentez.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/paymill.rb +237 -48
  154. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +41 -8
  155. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  156. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +18 -4
  157. data/lib/active_merchant/billing/gateways/paypal.rb +49 -20
  158. data/lib/active_merchant/billing/gateways/paypal_ca.rb +1 -1
  159. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +6 -5
  160. data/lib/active_merchant/billing/gateways/paypal_express.rb +32 -4
  161. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +3 -3
  162. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  163. data/lib/active_merchant/billing/gateways/paystation.rb +22 -24
  164. data/lib/active_merchant/billing/gateways/payu_in.rb +248 -0
  165. data/lib/active_merchant/billing/gateways/payu_latam.rb +440 -0
  166. data/lib/active_merchant/billing/gateways/pin.rb +68 -13
  167. data/lib/active_merchant/billing/gateways/plugnpay.rb +1 -12
  168. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  169. data/lib/active_merchant/billing/gateways/psigate.rb +3 -14
  170. data/lib/active_merchant/billing/gateways/psl_card.rb +3 -3
  171. data/lib/active_merchant/billing/gateways/qbms.rb +1 -1
  172. data/lib/active_merchant/billing/gateways/quantum.rb +2 -2
  173. data/lib/active_merchant/billing/gateways/quickbooks.rb +290 -0
  174. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  175. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +299 -0
  176. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  177. data/lib/active_merchant/billing/gateways/quickpay.rb +10 -319
  178. data/lib/active_merchant/billing/gateways/qvalent.rb +236 -0
  179. data/lib/active_merchant/billing/gateways/realex.rb +27 -25
  180. data/lib/active_merchant/billing/gateways/redsys.rb +212 -80
  181. data/lib/active_merchant/billing/gateways/s5.rb +247 -0
  182. data/lib/active_merchant/billing/gateways/safe_charge.rb +258 -0
  183. data/lib/active_merchant/billing/gateways/sage.rb +412 -119
  184. data/lib/active_merchant/billing/gateways/sage_pay.rb +176 -59
  185. data/lib/active_merchant/billing/gateways/secure_net.rb +35 -29
  186. data/lib/active_merchant/billing/gateways/secure_pay.rb +182 -9
  187. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +21 -7
  188. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +0 -7
  189. data/lib/active_merchant/billing/gateways/securion_pay.rb +267 -0
  190. data/lib/active_merchant/billing/gateways/skip_jack.rb +1 -3
  191. data/lib/active_merchant/billing/gateways/smart_ps.rb +13 -2
  192. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  193. data/lib/active_merchant/billing/gateways/spreedly_core.rb +36 -11
  194. data/lib/active_merchant/billing/gateways/stripe.rb +461 -82
  195. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +156 -0
  196. data/lib/active_merchant/billing/gateways/telr.rb +275 -0
  197. data/lib/active_merchant/billing/gateways/tns.rb +22 -0
  198. data/lib/active_merchant/billing/gateways/trans_first.rb +142 -28
  199. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +608 -0
  200. data/lib/active_merchant/billing/gateways/transact_pro.rb +224 -0
  201. data/lib/active_merchant/billing/gateways/transnational.rb +2 -231
  202. data/lib/active_merchant/billing/gateways/trexle.rb +217 -0
  203. data/lib/active_merchant/billing/gateways/trust_commerce.rb +17 -11
  204. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +193 -75
  205. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +150 -63
  206. data/lib/active_merchant/billing/gateways/vanco.rb +294 -0
  207. data/lib/active_merchant/billing/gateways/verifi.rb +1 -8
  208. data/lib/active_merchant/billing/gateways/viaklix.rb +1 -15
  209. data/lib/active_merchant/billing/gateways/visanet_peru.rb +209 -0
  210. data/lib/active_merchant/billing/gateways/webpay.rb +45 -28
  211. data/lib/active_merchant/billing/gateways/wepay.rb +238 -0
  212. data/lib/active_merchant/billing/gateways/wirecard.rb +167 -49
  213. data/lib/active_merchant/billing/gateways/world_net.rb +344 -0
  214. data/lib/active_merchant/billing/gateways/worldpay.rb +131 -36
  215. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +218 -0
  216. data/lib/active_merchant/billing/gateways/worldpay_us.rb +221 -0
  217. data/lib/active_merchant/billing/gateways.rb +8 -11
  218. data/lib/active_merchant/billing/model.rb +30 -0
  219. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +39 -0
  220. data/lib/active_merchant/billing/payment_token.rb +21 -0
  221. data/lib/active_merchant/billing/rails.rb +3 -0
  222. data/lib/active_merchant/billing/response.rb +24 -17
  223. data/lib/active_merchant/billing.rb +7 -1
  224. data/lib/active_merchant/connection.rb +177 -0
  225. data/lib/active_merchant/country.rb +334 -0
  226. data/lib/active_merchant/empty.rb +20 -0
  227. data/lib/active_merchant/errors.rb +35 -0
  228. data/lib/active_merchant/network_connection_retries.rb +79 -0
  229. data/lib/active_merchant/post_data.rb +24 -0
  230. data/lib/active_merchant/posts_data.rb +84 -0
  231. data/lib/active_merchant/version.rb +1 -1
  232. data/lib/active_merchant.rb +24 -21
  233. data/lib/certs/cacert.pem +3951 -0
  234. data/lib/support/gateway_support.rb +16 -10
  235. data/lib/support/outbound_hosts.rb +13 -10
  236. metadata +161 -306
  237. data/gem-public_cert.pem +0 -20
  238. data/lib/active_merchant/billing/expiry_date.rb +0 -34
  239. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
  240. data/lib/active_merchant/billing/gateways/card_stream_modern.rb +0 -155
  241. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -277
  242. data/lib/active_merchant/billing/gateways/orbital/avs_result.rb +0 -93
  243. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -93
  244. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -114
  245. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -102
  246. data/lib/active_merchant/billing/gateways/samurai.rb +0 -118
  247. data/lib/active_merchant/billing/gateways/vindicia.rb +0 -361
  248. data/lib/active_merchant/billing/integrations/a1agregator/helper.rb +0 -31
  249. data/lib/active_merchant/billing/integrations/a1agregator/notification.rb +0 -186
  250. data/lib/active_merchant/billing/integrations/a1agregator/status.rb +0 -38
  251. data/lib/active_merchant/billing/integrations/a1agregator.rb +0 -26
  252. data/lib/active_merchant/billing/integrations/action_view_helper.rb +0 -73
  253. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +0 -229
  254. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +0 -340
  255. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +0 -38
  256. data/lib/active_merchant/billing/integrations/bogus/helper.rb +0 -17
  257. data/lib/active_merchant/billing/integrations/bogus/notification.rb +0 -11
  258. data/lib/active_merchant/billing/integrations/bogus/return.rb +0 -10
  259. data/lib/active_merchant/billing/integrations/bogus.rb +0 -23
  260. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +0 -120
  261. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +0 -158
  262. data/lib/active_merchant/billing/integrations/chronopay/return.rb +0 -10
  263. data/lib/active_merchant/billing/integrations/chronopay.rb +0 -23
  264. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +0 -200
  265. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +0 -76
  266. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +0 -32
  267. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +0 -37
  268. data/lib/active_merchant/billing/integrations/direc_pay.rb +0 -41
  269. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +0 -90
  270. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +0 -120
  271. data/lib/active_merchant/billing/integrations/directebanking/return.rb +0 -11
  272. data/lib/active_merchant/billing/integrations/directebanking.rb +0 -47
  273. data/lib/active_merchant/billing/integrations/dotpay/helper.rb +0 -77
  274. data/lib/active_merchant/billing/integrations/dotpay/notification.rb +0 -86
  275. data/lib/active_merchant/billing/integrations/dotpay/return.rb +0 -11
  276. data/lib/active_merchant/billing/integrations/dotpay.rb +0 -22
  277. data/lib/active_merchant/billing/integrations/dwolla/common.rb +0 -23
  278. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +0 -43
  279. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +0 -64
  280. data/lib/active_merchant/billing/integrations/dwolla/return.rb +0 -49
  281. data/lib/active_merchant/billing/integrations/dwolla.rb +0 -23
  282. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +0 -34
  283. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +0 -84
  284. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +0 -48
  285. data/lib/active_merchant/billing/integrations/easy_pay/common.rb +0 -40
  286. data/lib/active_merchant/billing/integrations/easy_pay/helper.rb +0 -36
  287. data/lib/active_merchant/billing/integrations/easy_pay/notification.rb +0 -59
  288. data/lib/active_merchant/billing/integrations/easy_pay.rb +0 -30
  289. data/lib/active_merchant/billing/integrations/epay/helper.rb +0 -55
  290. data/lib/active_merchant/billing/integrations/epay/notification.rb +0 -110
  291. data/lib/active_merchant/billing/integrations/epay.rb +0 -21
  292. data/lib/active_merchant/billing/integrations/first_data/helper.rb +0 -61
  293. data/lib/active_merchant/billing/integrations/first_data/notification.rb +0 -56
  294. data/lib/active_merchant/billing/integrations/first_data.rb +0 -38
  295. data/lib/active_merchant/billing/integrations/gestpay/common.rb +0 -42
  296. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +0 -70
  297. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +0 -85
  298. data/lib/active_merchant/billing/integrations/gestpay/return.rb +0 -10
  299. data/lib/active_merchant/billing/integrations/gestpay.rb +0 -25
  300. data/lib/active_merchant/billing/integrations/helper.rb +0 -117
  301. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +0 -58
  302. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +0 -59
  303. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +0 -68
  304. data/lib/active_merchant/billing/integrations/hi_trust.rb +0 -27
  305. data/lib/active_merchant/billing/integrations/ipay88/helper.rb +0 -114
  306. data/lib/active_merchant/billing/integrations/ipay88/return.rb +0 -95
  307. data/lib/active_merchant/billing/integrations/ipay88.rb +0 -19
  308. data/lib/active_merchant/billing/integrations/liqpay/helper.rb +0 -43
  309. data/lib/active_merchant/billing/integrations/liqpay/notification.rb +0 -89
  310. data/lib/active_merchant/billing/integrations/liqpay/return.rb +0 -83
  311. data/lib/active_merchant/billing/integrations/liqpay.rb +0 -30
  312. data/lib/active_merchant/billing/integrations/maksuturva/helper.rb +0 -119
  313. data/lib/active_merchant/billing/integrations/maksuturva/notification.rb +0 -48
  314. data/lib/active_merchant/billing/integrations/maksuturva.rb +0 -86
  315. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +0 -75
  316. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +0 -129
  317. data/lib/active_merchant/billing/integrations/moneybookers.rb +0 -26
  318. data/lib/active_merchant/billing/integrations/nochex/helper.rb +0 -68
  319. data/lib/active_merchant/billing/integrations/nochex/notification.rb +0 -94
  320. data/lib/active_merchant/billing/integrations/nochex/return.rb +0 -10
  321. data/lib/active_merchant/billing/integrations/nochex.rb +0 -88
  322. data/lib/active_merchant/billing/integrations/notification.rb +0 -71
  323. data/lib/active_merchant/billing/integrations/paxum/common.rb +0 -24
  324. data/lib/active_merchant/billing/integrations/paxum/helper.rb +0 -42
  325. data/lib/active_merchant/billing/integrations/paxum/notification.rb +0 -33
  326. data/lib/active_merchant/billing/integrations/paxum.rb +0 -44
  327. data/lib/active_merchant/billing/integrations/pay_fast/common.rb +0 -42
  328. data/lib/active_merchant/billing/integrations/pay_fast/helper.rb +0 -50
  329. data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +0 -134
  330. data/lib/active_merchant/billing/integrations/pay_fast/return.rb +0 -10
  331. data/lib/active_merchant/billing/integrations/pay_fast.rb +0 -70
  332. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +0 -116
  333. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +0 -78
  334. data/lib/active_merchant/billing/integrations/payflow_link.rb +0 -21
  335. data/lib/active_merchant/billing/integrations/paypal/helper.rb +0 -119
  336. data/lib/active_merchant/billing/integrations/paypal/notification.rb +0 -227
  337. data/lib/active_merchant/billing/integrations/paypal/return.rb +0 -10
  338. data/lib/active_merchant/billing/integrations/paypal.rb +0 -39
  339. data/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb +0 -15
  340. data/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb +0 -20
  341. data/lib/active_merchant/billing/integrations/paysbuy/helper.rb +0 -15
  342. data/lib/active_merchant/billing/integrations/paysbuy/notification.rb +0 -28
  343. data/lib/active_merchant/billing/integrations/paysbuy.rb +0 -36
  344. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +0 -74
  345. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +0 -165
  346. data/lib/active_merchant/billing/integrations/payu_in/return.rb +0 -36
  347. data/lib/active_merchant/billing/integrations/payu_in.rb +0 -43
  348. data/lib/active_merchant/billing/integrations/platron/helper.rb +0 -32
  349. data/lib/active_merchant/billing/integrations/platron/notification.rb +0 -113
  350. data/lib/active_merchant/billing/integrations/platron.rb +0 -28
  351. data/lib/active_merchant/billing/integrations/pxpay/helper.rb +0 -112
  352. data/lib/active_merchant/billing/integrations/pxpay/notification.rb +0 -157
  353. data/lib/active_merchant/billing/integrations/pxpay/return.rb +0 -25
  354. data/lib/active_merchant/billing/integrations/pxpay.rb +0 -31
  355. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +0 -74
  356. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +0 -137
  357. data/lib/active_merchant/billing/integrations/quickpay.rb +0 -21
  358. data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +0 -23
  359. data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +0 -91
  360. data/lib/active_merchant/billing/integrations/rbkmoney.rb +0 -17
  361. data/lib/active_merchant/billing/integrations/return.rb +0 -42
  362. data/lib/active_merchant/billing/integrations/robokassa/common.rb +0 -19
  363. data/lib/active_merchant/billing/integrations/robokassa/helper.rb +0 -50
  364. data/lib/active_merchant/billing/integrations/robokassa/notification.rb +0 -55
  365. data/lib/active_merchant/billing/integrations/robokassa/return.rb +0 -17
  366. data/lib/active_merchant/billing/integrations/robokassa.rb +0 -49
  367. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +0 -33
  368. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +0 -136
  369. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +0 -210
  370. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +0 -31
  371. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +0 -37
  372. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +0 -91
  373. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +0 -139
  374. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +0 -17
  375. data/lib/active_merchant/billing/integrations/two_checkout.rb +0 -44
  376. data/lib/active_merchant/billing/integrations/valitor/helper.rb +0 -86
  377. data/lib/active_merchant/billing/integrations/valitor/notification.rb +0 -13
  378. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +0 -97
  379. data/lib/active_merchant/billing/integrations/valitor/return.rb +0 -13
  380. data/lib/active_merchant/billing/integrations/valitor.rb +0 -33
  381. data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +0 -88
  382. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +0 -59
  383. data/lib/active_merchant/billing/integrations/verkkomaksut.rb +0 -20
  384. data/lib/active_merchant/billing/integrations/web_pay/common.rb +0 -50
  385. data/lib/active_merchant/billing/integrations/web_pay/helper.rb +0 -68
  386. data/lib/active_merchant/billing/integrations/web_pay/notification.rb +0 -51
  387. data/lib/active_merchant/billing/integrations/web_pay.rb +0 -45
  388. data/lib/active_merchant/billing/integrations/webmoney/common.rb +0 -17
  389. data/lib/active_merchant/billing/integrations/webmoney/helper.rb +0 -40
  390. data/lib/active_merchant/billing/integrations/webmoney/notification.rb +0 -47
  391. data/lib/active_merchant/billing/integrations/webmoney.rb +0 -43
  392. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +0 -101
  393. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +0 -160
  394. data/lib/active_merchant/billing/integrations/world_pay.rb +0 -34
  395. data/lib/active_merchant/billing/integrations.rb +0 -17
  396. data.tar.gz.sig +0 -0
  397. metadata.gz.sig +0 -0
@@ -1,725 +1,1018 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
3
- # For more information on the Authorize.Net Gateway please visit their {Integration Center}[http://developer.authorize.net/]
4
- #
5
- # The login and password are not the username and password you use to
6
- # login to the Authorize.Net Merchant Interface. Instead, you will
7
- # use the API Login ID as the login and Transaction Key as the
8
- # password.
9
- #
10
- # ==== How to Get Your API Login ID and Transaction Key
11
- #
12
- # 1. Log into the Merchant Interface
13
- # 2. Select Settings from the Main Menu
14
- # 3. Click on API Login ID and Transaction Key in the Security section
15
- # 4. Type in the answer to the secret question configured on setup
16
- # 5. Click Submit
17
- #
18
- # ==== Automated Recurring Billing (ARB)
19
- #
20
- # Automated Recurring Billing (ARB) is an optional service for submitting and managing recurring, or subscription-based, transactions.
21
- #
22
- # To use recurring, update_recurring, cancel_recurring and status_recurring ARB must be enabled for your account.
23
- #
24
- # Information about ARB is available on the {Authorize.Net website}[http://www.authorize.net/solutions/merchantsolutions/merchantservices/automatedrecurringbilling/].
25
- # Information about the ARB API is available at the {Authorize.Net Integration Center}[http://developer.authorize.net/]
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant
4
+ module Billing
26
5
  class AuthorizeNetGateway < Gateway
27
- API_VERSION = '3.1'
6
+ include Empty
28
7
 
29
- class_attribute :arb_test_url, :arb_live_url
8
+ self.test_url = 'https://apitest.authorize.net/xml/v1/request.api'
9
+ self.live_url = 'https://api2.authorize.net/xml/v1/request.api'
30
10
 
31
- self.test_url = "https://test.authorize.net/gateway/transact.dll"
32
- self.live_url = "https://secure.authorize.net/gateway/transact.dll"
11
+ self.supported_countries = %w(AD AT AU BE BG CA CH CY CZ DE DK EE ES FI FR GB GI GR HU IE IL IS IT LI LT LU LV MC MT NL NO PL PT RO SE SI SK SM TR US VA)
12
+ self.default_currency = 'USD'
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro]
33
15
 
34
- self.arb_test_url = 'https://apitest.authorize.net/xml/v1/request.api'
35
- self.arb_live_url = 'https://api.authorize.net/xml/v1/request.api'
16
+ self.homepage_url = 'http://www.authorize.net/'
17
+ self.display_name = 'Authorize.Net'
36
18
 
37
- class_attribute :duplicate_window
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
+ }
38
37
 
39
- APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
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
+ }
40
59
 
41
- RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT, AUTHORIZATION_CODE = 0, 2, 3, 4
42
- AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38
60
+ MARKET_TYPE = {
61
+ :moto => '1',
62
+ :retail => '2'
63
+ }
43
64
 
44
- self.default_currency = 'USD'
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
+ }
45
77
 
46
- self.supported_countries = ['US', 'CA', 'GB']
47
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
48
- self.homepage_url = 'http://www.authorize.net/'
49
- self.display_name = 'Authorize.Net'
78
+ class_attribute :duplicate_window
50
79
 
51
- CARD_CODE_ERRORS = %w( N S )
52
- AVS_ERRORS = %w( A E N R W Z )
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)
53
85
  AVS_REASON_CODES = %w(27 45)
54
86
 
55
- AUTHORIZE_NET_ARB_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'
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
56
91
 
57
- RECURRING_ACTIONS = {
58
- :create => 'ARBCreateSubscription',
59
- :update => 'ARBUpdateSubscription',
60
- :cancel => 'ARBCancelSubscription',
61
- :status => 'ARBGetSubscriptionStatus'
62
- }
92
+ APPLE_PAY_DATA_DESCRIPTOR = "COMMON.APPLE.INAPP.PAYMENT"
93
+
94
+ PAYMENT_METHOD_NOT_SUPPORTED_ERROR = "155"
95
+ INELIGIBLE_FOR_ISSUING_CREDIT_ERROR = "54"
63
96
 
64
- # Creates a new AuthorizeNetGateway
65
- #
66
- # The gateway requires that a valid login and password be passed
67
- # in the +options+ hash.
68
- #
69
- # ==== Options
70
- #
71
- # * <tt>:login</tt> -- The Authorize.Net API Login ID (REQUIRED)
72
- # * <tt>:password</tt> -- The Authorize.Net Transaction Key. (REQUIRED)
73
- # * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
74
- # Otherwise, perform transactions against the production server.
75
- def initialize(options = {})
97
+ def initialize(options={})
76
98
  requires!(options, :login, :password)
77
99
  super
78
100
  end
79
101
 
80
- # Performs an authorization, which reserves the funds on the customer's credit card, but does not
81
- # charge the card.
82
- #
83
- # ==== Parameters
84
- #
85
- # * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
86
- # * <tt>paysource</tt> -- The CreditCard or Check details for the transaction.
87
- # * <tt>options</tt> -- A hash of optional parameters.
88
- def authorize(money, paysource, options = {})
89
- post = {}
90
- add_currency_code(post, money, options)
91
- add_invoice(post, options)
92
- add_payment_source(post, paysource, options)
93
- add_address(post, options)
94
- add_customer_data(post, options)
95
- add_duplicate_window(post)
96
-
97
- commit('AUTH_ONLY', money, post)
98
- end
99
-
100
- # Perform a purchase, which is essentially an authorization and capture in a single operation.
101
- #
102
- # ==== Parameters
103
- #
104
- # * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
105
- # * <tt>paysource</tt> -- The CreditCard or Check details for the transaction.
106
- # * <tt>options</tt> -- A hash of optional parameters.
107
- def purchase(money, paysource, options = {})
108
- post = {}
109
- add_currency_code(post, money, options)
110
- add_invoice(post, options)
111
- add_payment_source(post, paysource, options)
112
- add_address(post, options)
113
- add_customer_data(post, options)
114
- add_duplicate_window(post)
115
-
116
- commit('AUTH_CAPTURE', money, post)
117
- end
118
-
119
- # Captures the funds from an authorized transaction.
120
- #
121
- # ==== Parameters
122
- #
123
- # * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
124
- # * <tt>authorization</tt> -- The authorization returned from the previous authorize request.
125
- def capture(money, authorization, options = {})
126
- post = {:trans_id => authorization}
127
- add_customer_data(post, options)
128
- add_invoice(post, options)
129
- commit('PRIOR_AUTH_CAPTURE', money, post)
130
- end
131
-
132
- # Void a previous transaction
133
- #
134
- # ==== Parameters
135
- #
136
- # * <tt>authorization</tt> - The authorization returned from the previous authorize request.
137
- def void(authorization, options = {})
138
- post = {:trans_id => authorization}
139
- add_duplicate_window(post)
140
- commit('VOID', nil, post)
141
- end
142
-
143
- # Refund a transaction.
144
- #
145
- # This transaction indicates to the gateway that
146
- # money should flow from the merchant to the customer.
147
- #
148
- # ==== Parameters
149
- #
150
- # * <tt>money</tt> -- The amount to be credited to the customer as an Integer value in cents.
151
- # * <tt>identification</tt> -- The ID of the original transaction against which the refund is being issued.
152
- # * <tt>options</tt> -- A hash of parameters.
153
- #
154
- # ==== Options
155
- #
156
- # * <tt>:card_number</tt> -- The credit card number the refund is being issued to. (REQUIRED)
157
- # You can either pass the last four digits of the card number or the full card number.
158
- # * <tt>:first_name</tt> -- The first name of the account being refunded.
159
- # * <tt>:last_name</tt> -- The last name of the account being refunded.
160
- # * <tt>:zip</tt> -- The postal code of the account being refunded.
161
- def refund(money, identification, options = {})
162
- requires!(options, :card_number)
163
-
164
- post = { :trans_id => identification,
165
- :card_num => options[:card_number]
166
- }
167
-
168
- post[:first_name] = options[:first_name] if options[:first_name]
169
- post[:last_name] = options[:last_name] if options[:last_name]
170
- post[:zip] = options[:zip] if options[:zip]
171
-
172
- add_invoice(post, options)
173
- add_duplicate_window(post)
174
-
175
- commit('CREDIT', money, post)
176
- end
177
-
178
- def credit(money, identification, options = {})
179
- deprecated CREDIT_DEPRECATION_MESSAGE
180
- refund(money, identification, options)
181
- end
182
-
183
- # Create a recurring payment.
184
- #
185
- # This transaction creates a new Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled.
186
- #
187
- # ==== Parameters
188
- #
189
- # * <tt>money</tt> -- The amount to be charged to the customer at each interval as an Integer value in cents.
190
- # * <tt>creditcard</tt> -- The CreditCard details for the transaction.
191
- # * <tt>options</tt> -- A hash of parameters.
192
- #
193
- # ==== Options
194
- #
195
- # * <tt>:interval</tt> -- A hash containing information about the interval of time between payments. Must
196
- # contain the keys <tt>:length</tt> and <tt>:unit</tt>. <tt>:unit</tt> can be either <tt>:months</tt> or <tt>:days</tt>.
197
- # If <tt>:unit</tt> is <tt>:months</tt> then <tt>:length</tt> must be an integer between 1 and 12 inclusive.
198
- # If <tt>:unit</tt> is <tt>:days</tt> then <tt>:length</tt> must be an integer between 7 and 365 inclusive.
199
- # For example, to charge the customer once every three months the hash would be
200
- # +:interval => { :unit => :months, :length => 3 }+ (REQUIRED)
201
- # * <tt>:duration</tt> -- A hash containing keys for the <tt>:start_date</tt> the subscription begins (also the date the
202
- # initial billing occurs) and the total number of billing <tt>:occurences</tt> or payments for the subscription. (REQUIRED)
203
- def recurring(money, creditcard, options={})
204
- requires!(options, :interval, :duration, :billing_address)
205
- requires!(options[:interval], :length, [:unit, :days, :months])
206
- requires!(options[:duration], :start_date, :occurrences)
207
- requires!(options[:billing_address], :first_name, :last_name)
208
-
209
- options[:credit_card] = creditcard
210
- options[:amount] = money
211
-
212
- request = build_recurring_request(:create, options)
213
- recurring_commit(:create, request)
214
- end
215
-
216
- # Update a recurring payment's details.
217
- #
218
- # This transaction updates an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled
219
- # and the subscription must have already been created previously by calling +recurring()+. The ability to change certain
220
- # details about a recurring payment is dependent on transaction history and cannot be determined until after calling
221
- # +update_recurring()+. See the ARB XML Guide for such conditions.
222
- #
223
- # ==== Parameters
224
- #
225
- # * <tt>options</tt> -- A hash of parameters.
226
- #
227
- # ==== Options
228
- #
229
- # * <tt>:subscription_id</tt> -- A string containing the <tt>:subscription_id</tt> of the recurring payment already in place
230
- # for a given credit card. (REQUIRED)
231
- def update_recurring(options={})
232
- requires!(options, :subscription_id)
233
- request = build_recurring_request(:update, options)
234
- recurring_commit(:update, request)
235
- end
236
-
237
- # Cancel a recurring payment.
238
- #
239
- # This transaction cancels an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled
240
- # and the subscription must have already been created previously by calling recurring()
241
- #
242
- # ==== Parameters
243
- #
244
- # * <tt>subscription_id</tt> -- A string containing the +subscription_id+ of the recurring payment already in place
245
- # for a given credit card. (REQUIRED)
246
- def cancel_recurring(subscription_id)
247
- request = build_recurring_request(:cancel, :subscription_id => subscription_id)
248
- recurring_commit(:cancel, request)
249
- end
250
-
251
- # Get Subscription Status of a recurring payment.
252
- #
253
- # This transaction gets the status of an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled.
254
- #
255
- # ==== Parameters
256
- #
257
- # * <tt>subscription_id</tt> -- A string containing the +subscription_id+ of the recurring payment already in place
258
- # for a given credit card. (REQUIRED)
259
- def status_recurring(subscription_id)
260
- request = build_recurring_request(:status, :subscription_id => subscription_id)
261
- recurring_commit(:status, request)
102
+ def purchase(amount, payment, options = {})
103
+ if payment.is_a?(String)
104
+ commit(:cim_purchase) do |xml|
105
+ add_cim_auth_purchase(xml, "profileTransAuthCapture", amount, payment, options)
106
+ end
107
+ else
108
+ commit(:purchase) do |xml|
109
+ add_auth_purchase(xml, "authCaptureTransaction", amount, payment, options)
110
+ end
111
+ end
262
112
  end
263
113
 
264
- private
114
+ def authorize(amount, payment, options={})
115
+ if payment.is_a?(String)
116
+ commit(:cim_authorize) do |xml|
117
+ add_cim_auth_purchase(xml, "profileTransAuthOnly", amount, payment, options)
118
+ end
119
+ else
120
+ commit(:authorize) do |xml|
121
+ add_auth_purchase(xml, "authOnlyTransaction", amount, payment, options)
122
+ end
123
+ end
124
+ end
265
125
 
266
- def commit(action, money, parameters)
267
- parameters[:amount] = amount(money) unless action == 'VOID'
126
+ def capture(amount, authorization, options={})
127
+ if auth_was_for_cim?(authorization)
128
+ cim_capture(amount, authorization, options)
129
+ else
130
+ normal_capture(amount, authorization, options)
131
+ end
132
+ end
133
+
134
+ def refund(amount, authorization, options={})
135
+ response = if auth_was_for_cim?(authorization)
136
+ cim_refund(amount, authorization, options)
137
+ else
138
+ normal_refund(amount, authorization, options)
139
+ end
268
140
 
269
- # Only activate the test_request when the :test option is passed in
270
- parameters[:test_request] = @options[:test] ? 'TRUE' : 'FALSE'
141
+ return response if response.success?
142
+ return response unless options[:force_full_refund_if_unsettled]
271
143
 
272
- url = test? ? self.test_url : self.live_url
273
- data = ssl_post url, post_data(action, parameters)
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
274
158
 
275
- response = parse(data)
276
- response[:action] = action
159
+ def credit(amount, payment, options={})
160
+ if payment.is_a?(String)
161
+ raise ArgumentError, "Reference credits are not supported. Please supply the original credit card or use the #refund method."
162
+ end
277
163
 
278
- message = message_from(response)
164
+ commit(:credit) do |xml|
165
+ add_order_id(xml, options)
166
+ xml.transactionRequest do
167
+ xml.transactionType('refundTransaction')
168
+ xml.amount(amount(amount))
169
+
170
+ add_payment_source(xml, payment)
171
+ xml.refTransId(transaction_id_from(options[:transaction_id])) if options[:transaction_id]
172
+ add_invoice(xml, 'refundTransaction', options)
173
+ add_customer_data(xml, payment, options)
174
+ add_settings(xml, payment, options)
175
+ add_user_fields(xml, amount, options)
176
+ end
177
+ end
178
+ end
279
179
 
280
- # Return the response. The authorization can be taken out of the transaction_id
281
- # Test Mode on/off is something we have to parse from the response text.
282
- # It usually looks something like this
283
- #
284
- # (TESTMODE) Successful Sale
285
- test_mode = test? || message =~ /TESTMODE/
180
+ def verify(credit_card, options = {})
181
+ MultiResponse.run(:use_first_response) do |r|
182
+ r.process { authorize(100, credit_card, options) }
183
+ r.process(:ignore_result) { void(r.authorization, options) }
184
+ end
185
+ end
286
186
 
287
- Response.new(success?(response), message, response,
288
- :test => test_mode,
289
- :authorization => response[:transaction_id],
290
- :fraud_review => fraud_review?(response),
291
- :avs_result => { :code => response[:avs_result_code] },
292
- :cvv_result => response[:card_code]
293
- )
187
+ def store(credit_card, options = {})
188
+ if options[:customer_profile_id]
189
+ create_customer_payment_profile(credit_card, options)
190
+ else
191
+ create_customer_profile(credit_card, options)
192
+ end
294
193
  end
295
194
 
296
- def success?(response)
297
- response[:response_code] == APPROVED
195
+ def unstore(authorization)
196
+ customer_profile_id, _, _ = split_authorization(authorization)
197
+
198
+ delete_customer_profile(customer_profile_id)
298
199
  end
299
200
 
300
- def fraud_review?(response)
301
- response[:response_code] == FRAUD_REVIEW
201
+ def verify_credentials
202
+ response = commit(:verify_credentials) { }
203
+ response.success?
302
204
  end
303
205
 
304
- def parse(body)
305
- fields = split(body)
206
+ def supports_scrubbing?
207
+ true
208
+ end
306
209
 
307
- results = {
308
- :response_code => fields[RESPONSE_CODE].to_i,
309
- :response_reason_code => fields[RESPONSE_REASON_CODE],
310
- :response_reason_text => fields[RESPONSE_REASON_TEXT],
311
- :avs_result_code => fields[AVS_RESULT_CODE],
312
- :transaction_id => fields[TRANSACTION_ID],
313
- :card_code => fields[CARD_CODE_RESPONSE_CODE],
314
- :authorization_code => fields[AUTHORIZATION_CODE]
315
- }
316
- results
210
+ def scrub(transcript)
211
+ transcript.
212
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
213
+ gsub(%r((<transactionKey>).+(</transactionKey>)), '\1[FILTERED]\2').
214
+ gsub(%r((<cardNumber>).+(</cardNumber>)), '\1[FILTERED]\2').
215
+ gsub(%r((<cardCode>).+(</cardCode>)), '\1[FILTERED]\2').
216
+ gsub(%r((<track1>).+(</track1>)), '\1[FILTERED]\2').
217
+ gsub(%r((<track2>).+(</track2>)), '\1[FILTERED]\2').
218
+ gsub(/(<routingNumber>).+(<\/routingNumber>)/, '\1[FILTERED]\2').
219
+ gsub(/(<accountNumber>).+(<\/accountNumber>)/, '\1[FILTERED]\2').
220
+ gsub(%r((<cryptogram>).+(</cryptogram>)), '\1[FILTERED]\2')
317
221
  end
318
222
 
319
- def post_data(action, parameters = {})
320
- post = {}
223
+ def supports_network_tokenization?
224
+ card = Billing::NetworkTokenizationCreditCard.new({
225
+ :number => "4111111111111111",
226
+ :month => 12,
227
+ :year => 20,
228
+ :first_name => 'John',
229
+ :last_name => 'Smith',
230
+ :brand => 'visa',
231
+ :payment_cryptogram => 'EHuWW9PiBkWvqE5juRwDzAUFBAk='
232
+ })
321
233
 
322
- post[:version] = API_VERSION
323
- post[:login] = @options[:login]
324
- post[:tran_key] = @options[:password]
325
- post[:relay_response] = "FALSE"
326
- post[:type] = action
327
- post[:delim_data] = "TRUE"
328
- post[:delim_char] = ","
329
- post[:encap_char] = "$"
330
- post[:solution_ID] = application_id if application_id.present? && application_id != "ActiveMerchant"
234
+ request = post_data(:authorize) do |xml|
235
+ add_auth_purchase(xml, "authOnlyTransaction", 1, card, {})
236
+ end
237
+ raw_response = ssl_post(url, request, headers)
238
+ response = parse(:authorize, raw_response)
239
+ response[:response_reason_code].to_s != PAYMENT_METHOD_NOT_SUPPORTED_ERROR
240
+ end
241
+
242
+ private
243
+
244
+ def add_auth_purchase(xml, transaction_type, amount, payment, options)
245
+ add_order_id(xml, options)
246
+ xml.transactionRequest do
247
+ xml.transactionType(transaction_type)
248
+ xml.amount(amount(amount))
249
+ add_payment_source(xml, payment)
250
+ add_invoice(xml, transaction_type, options)
251
+ add_tax_fields(xml, options)
252
+ add_duty_fields(xml, options)
253
+ add_shipping_fields(xml, options)
254
+ add_tax_exempt_status(xml, options)
255
+ add_po_number(xml, options)
256
+ add_customer_data(xml, payment, options)
257
+ add_market_type_device_type(xml, payment, options)
258
+ add_settings(xml, payment, options)
259
+ add_user_fields(xml, amount, options)
260
+ end
261
+ end
331
262
 
332
- request = post.merge(parameters).collect { |key, value| "x_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
333
- request
263
+ def add_cim_auth_purchase(xml, transaction_type, amount, payment, options)
264
+ add_order_id(xml, options)
265
+ xml.transaction do
266
+ xml.send(transaction_type) do
267
+ xml.amount(amount(amount))
268
+ add_tax_fields(xml, options)
269
+ add_shipping_fields(xml, options)
270
+ add_duty_fields(xml, options)
271
+ add_payment_source(xml, payment)
272
+ add_invoice(xml, transaction_type, options)
273
+ add_tax_exempt_status(xml, options)
274
+ end
275
+ end
334
276
  end
335
277
 
336
- def add_currency_code(post, money, options)
337
- post[:currency_code] = options[:currency] || currency(money)
278
+ def cim_capture(amount, authorization, options)
279
+ commit(:cim_capture) do |xml|
280
+ add_order_id(xml, options)
281
+ xml.transaction do
282
+ xml.profileTransPriorAuthCapture do
283
+ xml.amount(amount(amount))
284
+ add_tax_fields(xml, options)
285
+ add_shipping_fields(xml, options)
286
+ add_duty_fields(xml, options)
287
+ xml.transId(transaction_id_from(authorization))
288
+ end
289
+ end
290
+ end
338
291
  end
339
292
 
340
- def add_invoice(post, options)
341
- post[:invoice_num] = options[:order_id]
342
- post[:description] = options[:description]
293
+ def normal_capture(amount, authorization, options)
294
+ commit(:capture) do |xml|
295
+ add_order_id(xml, options)
296
+ xml.transactionRequest do
297
+ xml.transactionType('priorAuthCaptureTransaction')
298
+ xml.amount(amount(amount))
299
+ add_tax_fields(xml, options)
300
+ add_duty_fields(xml, options)
301
+ add_shipping_fields(xml, options)
302
+ add_tax_exempt_status(xml, options)
303
+ add_po_number(xml, options)
304
+ xml.refTransId(transaction_id_from(authorization))
305
+ add_invoice(xml, "capture", options)
306
+ add_user_fields(xml, amount, options)
307
+ end
308
+ end
343
309
  end
344
310
 
345
- def add_creditcard(post, creditcard, options={})
346
- post[:card_num] = creditcard.number
347
- post[:card_code] = creditcard.verification_value if creditcard.verification_value?
348
- post[:exp_date] = expdate(creditcard)
349
- post[:first_name] = creditcard.first_name
350
- post[:last_name] = creditcard.last_name
311
+ def cim_refund(amount, authorization, options)
312
+ transaction_id, card_number, _ = split_authorization(authorization)
313
+
314
+ commit(:cim_refund) do |xml|
315
+ add_order_id(xml, options)
316
+ xml.transaction do
317
+ xml.profileTransRefund do
318
+ xml.amount(amount(amount))
319
+ add_tax_fields(xml, options)
320
+ add_shipping_fields(xml, options)
321
+ add_duty_fields(xml, options)
322
+ xml.creditCardNumberMasked(card_number)
323
+ add_invoice(xml, "profileTransRefund", options)
324
+ xml.transId(transaction_id)
325
+ end
326
+ end
327
+ end
328
+ end
329
+
330
+ def normal_refund(amount, authorization, options)
331
+ transaction_id, card_number, _ = split_authorization(authorization)
332
+
333
+ commit(:refund) do |xml|
334
+ xml.transactionRequest do
335
+ xml.transactionType('refundTransaction')
336
+ xml.amount(amount.nil? ? 0 : amount(amount))
337
+ xml.payment do
338
+ xml.creditCard do
339
+ xml.cardNumber(card_number || options[:card_number])
340
+ xml.expirationDate('XXXX')
341
+ end
342
+ end
343
+ xml.refTransId(transaction_id)
344
+
345
+ add_invoice(xml, 'refundTransaction', options)
346
+ add_tax_fields(xml, options)
347
+ add_duty_fields(xml, options)
348
+ add_shipping_fields(xml, options)
349
+ add_tax_exempt_status(xml, options)
350
+ add_po_number(xml, options)
351
+ add_customer_data(xml, nil, options)
352
+ add_user_fields(xml, amount, options)
353
+ end
354
+ end
355
+ end
356
+
357
+ def cim_void(authorization, options)
358
+ commit(:cim_void) do |xml|
359
+ add_order_id(xml, options)
360
+ xml.transaction do
361
+ xml.profileTransVoid do
362
+ xml.transId(transaction_id_from(authorization))
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ def normal_void(authorization, options)
369
+ commit(:void) do |xml|
370
+ add_order_id(xml, options)
371
+ xml.transactionRequest do
372
+ xml.transactionType('voidTransaction')
373
+ xml.refTransId(transaction_id_from(authorization))
374
+ end
375
+ end
351
376
  end
352
377
 
353
- def add_payment_source(params, source, options={})
354
- if card_brand(source) == "check"
355
- add_check(params, source, options)
378
+ def add_payment_source(xml, source)
379
+ return unless source
380
+ if source.is_a?(String)
381
+ add_token_payment_method(xml, source)
382
+ elsif card_brand(source) == 'check'
383
+ add_check(xml, source)
384
+ elsif card_brand(source) == 'apple_pay'
385
+ add_apple_pay_payment_token(xml, source)
356
386
  else
357
- add_creditcard(params, source, options)
387
+ add_credit_card(xml, source)
358
388
  end
359
389
  end
360
390
 
361
- def add_check(post, check, options)
362
- post[:method] = "ECHECK"
363
- post[:bank_name] = check.bank_name
364
- post[:bank_aba_code] = check.routing_number
365
- post[:bank_acct_num] = check.account_number
366
- post[:bank_acct_type] = check.account_type
367
- post[:echeck_type] = "WEB"
368
- post[:bank_acct_name] = check.name
369
- post[:bank_check_number] = check.number if check.number.present?
370
- post[:recurring_billing] = (options[:recurring] ? "TRUE" : "FALSE")
391
+ def camel_case_lower(key)
392
+ String(key).split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
371
393
  end
372
394
 
373
- def add_customer_data(post, options)
374
- if options.has_key? :email
375
- post[:email] = options[:email]
376
- post[:email_customer] = false
395
+ def add_settings(xml, source, options)
396
+ xml.transactionSettings do
397
+ if options[:recurring]
398
+ xml.setting do
399
+ xml.settingName("recurringBilling")
400
+ xml.settingValue("true")
401
+ end
402
+ end
403
+ if options[:disable_partial_auth]
404
+ xml.setting do
405
+ xml.settingName("allowPartialAuth")
406
+ xml.settingValue("false")
407
+ end
408
+ end
409
+ if options[:duplicate_window]
410
+ set_duplicate_window(xml, options[:duplicate_window])
411
+ elsif self.class.duplicate_window
412
+ ActiveMerchant.deprecated "Using the duplicate_window class_attribute is deprecated. Use the transaction options hash instead."
413
+ set_duplicate_window(xml, self.class.duplicate_window)
414
+ end
415
+ if options[:email_customer]
416
+ xml.setting do
417
+ xml.settingName("emailCustomer")
418
+ xml.settingValue("true")
419
+ end
420
+ end
421
+ if options[:header_email_receipt]
422
+ xml.setting do
423
+ xml.settingName("headerEmailReceipt")
424
+ xml.settingValue(options[:header_email_receipt])
425
+ end
426
+ end
427
+ if options[:test_request]
428
+ xml.setting do
429
+ xml.settingName("testRequest")
430
+ xml.settingValue("1")
431
+ end
432
+ end
433
+ end
434
+ end
435
+
436
+ def set_duplicate_window(xml, value)
437
+ xml.setting do
438
+ xml.settingName("duplicateWindow")
439
+ xml.settingValue(value)
440
+ end
441
+ end
442
+
443
+ def add_user_fields(xml, amount, options)
444
+ xml.userFields do
445
+ if currency = (options[:currency] || currency(amount))
446
+ xml.userField do
447
+ xml.name("x_currency_code")
448
+ xml.value(currency)
449
+ end
450
+ end
451
+ if application_id.present?
452
+ xml.userField do
453
+ xml.name("x_solution_id")
454
+ xml.value(application_id)
455
+ end
456
+ end
377
457
  end
458
+ end
459
+
460
+ def add_credit_card(xml, credit_card)
461
+ if credit_card.track_data
462
+ add_swipe_data(xml, credit_card)
463
+ else
464
+ xml.payment do
465
+ xml.creditCard do
466
+ xml.cardNumber(truncate(credit_card.number, 16))
467
+ xml.expirationDate(format(credit_card.month, :two_digits) + '/' + format(credit_card.year, :four_digits))
468
+ if credit_card.valid_card_verification_value?(credit_card.verification_value, credit_card.brand)
469
+ xml.cardCode(credit_card.verification_value)
470
+ end
471
+ if credit_card.is_a?(NetworkTokenizationCreditCard)
472
+ xml.cryptogram(credit_card.payment_cryptogram)
473
+ end
474
+ end
475
+ end
476
+ end
477
+ end
478
+
479
+ def add_swipe_data(xml, credit_card)
480
+ TRACKS.each do |key, regex|
481
+ if regex.match(credit_card.track_data)
482
+ @valid_track_data = true
483
+ xml.payment do
484
+ xml.trackData do
485
+ xml.public_send(:"track#{key}", credit_card.track_data)
486
+ end
487
+ end
488
+ end
489
+ end
490
+ end
491
+
492
+ def add_token_payment_method(xml, token)
493
+ customer_profile_id, customer_payment_profile_id, _ = split_authorization(token)
494
+ xml.customerProfileId(customer_profile_id)
495
+ xml.customerPaymentProfileId(customer_payment_profile_id)
496
+ end
378
497
 
379
- if options.has_key? :customer
380
- post[:cust_id] = options[:customer] if Float(options[:customer]) rescue nil
498
+ def add_apple_pay_payment_token(xml, apple_pay_payment_token)
499
+ xml.payment do
500
+ xml.opaqueData do
501
+ xml.dataDescriptor(APPLE_PAY_DATA_DESCRIPTOR)
502
+ xml.dataValue(Base64.strict_encode64(apple_pay_payment_token.payment_data.to_json))
503
+ end
381
504
  end
505
+ end
382
506
 
383
- if options.has_key? :ip
384
- post[:customer_ip] = options[:ip]
507
+ def add_market_type_device_type(xml, payment, options)
508
+ return if payment.is_a?(String) || card_brand(payment) == 'check' || card_brand(payment) == 'apple_pay'
509
+ if valid_track_data
510
+ xml.retail do
511
+ xml.marketType(options[:market_type] || MARKET_TYPE[:retail])
512
+ xml.deviceType(options[:device_type] || DEVICE_TYPE[:wireless_pos])
513
+ end
514
+ elsif payment.manual_entry
515
+ xml.retail do
516
+ xml.marketType(options[:market_type] || MARKET_TYPE[:moto])
517
+ end
518
+ else
519
+ if options[:market_type]
520
+ xml.retail do
521
+ xml.marketType(options[:market_type])
522
+ end
523
+ end
385
524
  end
386
525
  end
387
526
 
388
- # x_duplicate_window won't be sent by default, because sending it changes the response.
389
- # "If this field is present in the request with or without a value, an enhanced duplicate transaction response will be sent."
390
- # (as of 2008-12-30) http://www.authorize.net/support/AIM_guide_SCC.pdf
391
- def add_duplicate_window(post)
392
- unless duplicate_window.nil?
393
- post[:duplicate_window] = duplicate_window
527
+ def valid_track_data
528
+ @valid_track_data ||= false
529
+ end
530
+
531
+ def add_check(xml, check)
532
+ xml.payment do
533
+ xml.bankAccount do
534
+ xml.routingNumber(check.routing_number)
535
+ xml.accountNumber(check.account_number)
536
+ xml.nameOnAccount(truncate(check.name, 22))
537
+ xml.bankName(check.bank_name)
538
+ xml.checkNumber(check.number)
539
+ end
394
540
  end
395
541
  end
396
542
 
397
- def add_address(post, options)
398
- if address = options[:billing_address] || options[:address]
399
- post[:address] = address[:address1].to_s
400
- post[:company] = address[:company].to_s
401
- post[:phone] = address[:phone].to_s
402
- post[:zip] = address[:zip].to_s
403
- post[:city] = address[:city].to_s
404
- post[:country] = address[:country].to_s
405
- post[:state] = address[:state].blank? ? 'n/a' : address[:state]
543
+ def add_customer_data(xml, payment_source, options)
544
+ xml.customer do
545
+ xml.id(options[:customer]) unless empty?(options[:customer]) || options[:customer] !~ /^\w+$/
546
+ xml.email(options[:email]) unless empty?(options[:email])
406
547
  end
407
548
 
408
- if address = options[:shipping_address]
409
- post[:ship_to_first_name] = address[:first_name].to_s
410
- post[:ship_to_last_name] = address[:last_name].to_s
411
- post[:ship_to_address] = address[:address1].to_s
412
- post[:ship_to_company] = address[:company].to_s
413
- post[:ship_to_phone] = address[:phone].to_s
414
- post[:ship_to_zip] = address[:zip].to_s
415
- post[:ship_to_city] = address[:city].to_s
416
- post[:ship_to_country] = address[:country].to_s
417
- post[:ship_to_state] = address[:state].blank? ? 'n/a' : address[:state]
549
+ add_billing_address(xml, payment_source, options)
550
+ add_shipping_address(xml, options)
551
+
552
+ xml.customerIP(options[:ip]) unless empty?(options[:ip])
553
+
554
+ xml.cardholderAuthentication do
555
+ xml.authenticationIndicator(options[:authentication_indicator])
556
+ xml.cardholderAuthenticationValue(options[:cardholder_authentication_value])
418
557
  end
419
558
  end
420
559
 
421
- # Make a ruby type out of the response string
422
- def normalize(field)
423
- case field
424
- when "true" then true
425
- when "false" then false
426
- when "" then nil
427
- when "null" then nil
428
- else field
560
+ def add_billing_address(xml, payment_source, options)
561
+ address = options[:billing_address] || options[:address] || {}
562
+
563
+ xml.billTo do
564
+ first_name, last_name = names_from(payment_source, address, options)
565
+ state = state_from(address, options)
566
+ full_address = "#{address[:address1]} #{address[:address2]}".strip
567
+
568
+ xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
569
+ xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
570
+ xml.company(truncate(address[:company], 50)) unless empty?(address[:company])
571
+ xml.address(truncate(full_address, 60))
572
+ xml.city(truncate(address[:city], 40))
573
+ xml.state(truncate(state, 40))
574
+ xml.zip(truncate((address[:zip] || options[:zip]), 20))
575
+ xml.country(truncate(address[:country], 60))
576
+ xml.phoneNumber(truncate(address[:phone], 25)) unless empty?(address[:phone])
577
+ xml.faxNumber(truncate(address[:fax], 25)) unless empty?(address[:fax])
429
578
  end
430
579
  end
431
580
 
432
- def message_from(results)
433
- if results[:response_code] == DECLINED
434
- return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
435
- if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
436
- return AVSResult.messages[ results[:avs_result_code] ]
581
+ def add_shipping_address(xml, options, root_node="shipTo")
582
+ address = options[:shipping_address] || options[:address]
583
+ return unless address
584
+
585
+ xml.send(root_node) do
586
+ first_name, last_name = if address[:name]
587
+ split_names(address[:name])
588
+ else
589
+ [address[:first_name], address[:last_name]]
437
590
  end
591
+ full_address = "#{address[:address1]} #{address[:address2]}".strip
592
+
593
+ xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
594
+ xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
595
+ xml.company(truncate(address[:company], 50)) unless empty?(address[:company])
596
+ xml.address(truncate(full_address, 60))
597
+ xml.city(truncate(address[:city], 40))
598
+ xml.state(truncate(address[:state], 40))
599
+ xml.zip(truncate(address[:zip], 20))
600
+ xml.country(truncate(address[:country], 60))
438
601
  end
439
602
 
440
- (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '')
441
603
  end
442
604
 
443
- def expdate(creditcard)
444
- year = sprintf("%.4i", creditcard.year)
445
- month = sprintf("%.2i", creditcard.month)
605
+ def add_order_id(xml, options)
606
+ xml.refId(truncate(options[:order_id], 20))
607
+ end
446
608
 
447
- "#{month}#{year[-2..-1]}"
609
+ def add_invoice(xml, transaction_type, options)
610
+ xml.order do
611
+ xml.invoiceNumber(truncate(options[:order_id], 20))
612
+ xml.description(truncate(options[:description], 255))
613
+ xml.purchaseOrderNumber(options[:po_number]) if options[:po_number] && transaction_type.start_with?("profileTrans")
614
+ end
615
+
616
+ # Authorize.net API requires lineItems to be placed directly after order tag
617
+ if options[:line_items]
618
+ xml.lineItems do
619
+ options[:line_items].each do |line_item|
620
+ xml.lineItem do
621
+ line_item.each do |key, value|
622
+ xml.send(camel_case_lower(key), value)
623
+ end
624
+ end
625
+ end
626
+ end
627
+ end
448
628
  end
449
629
 
450
- def split(response)
451
- response[1..-2].split(/\$,\$/)
630
+ def add_tax_fields(xml, options)
631
+ tax = options[:tax]
632
+ if tax.is_a?(Hash)
633
+ xml.tax do
634
+ xml.amount(amount(tax[:amount].to_i))
635
+ xml.name(tax[:name])
636
+ xml.description(tax[:description])
637
+ end
638
+ end
452
639
  end
453
640
 
454
- # ARB
641
+ def add_duty_fields(xml, options)
642
+ duty = options[:duty]
643
+ if duty.is_a?(Hash)
644
+ xml.duty do
645
+ xml.amount(amount(duty[:amount].to_i))
646
+ xml.name(duty[:name])
647
+ xml.description(duty[:description])
648
+ end
649
+ end
650
+ end
455
651
 
456
- # Builds recurring billing request
457
- def build_recurring_request(action, options = {})
458
- unless RECURRING_ACTIONS.include?(action)
459
- raise StandardError, "Invalid Automated Recurring Billing Action: #{action}"
652
+ def add_shipping_fields(xml, options)
653
+ shipping = options[:shipping]
654
+ if shipping.is_a?(Hash)
655
+ xml.shipping do
656
+ xml.amount(amount(shipping[:amount].to_i))
657
+ xml.name(shipping[:name])
658
+ xml.description(shipping[:description])
659
+ end
460
660
  end
661
+ end
461
662
 
462
- xml = Builder::XmlMarkup.new(:indent => 2)
463
- xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8')
464
- xml.tag!("#{RECURRING_ACTIONS[action]}Request", :xmlns => AUTHORIZE_NET_ARB_NAMESPACE) do
465
- add_arb_merchant_authentication(xml)
466
- # Merchant-assigned reference ID for the request
467
- xml.tag!('refId', options[:ref_id]) if options[:ref_id]
468
- send("build_arb_#{action}_subscription_request", xml, options)
663
+ def add_tax_exempt_status(xml, options)
664
+ xml.taxExempt(options[:tax_exempt]) if options[:tax_exempt]
665
+ end
666
+
667
+ def add_po_number(xml, options)
668
+ xml.poNumber(options[:po_number]) if options[:po_number]
669
+ end
670
+
671
+ def create_customer_payment_profile(credit_card, options)
672
+ commit(:cim_store_update) do |xml|
673
+ xml.customerProfileId options[:customer_profile_id]
674
+ xml.paymentProfile do
675
+ add_billing_address(xml, credit_card, options)
676
+ xml.payment do
677
+ xml.creditCard do
678
+ xml.cardNumber(truncate(credit_card.number, 16))
679
+ xml.expirationDate(format(credit_card.year, :four_digits) + '-' + format(credit_card.month, :two_digits))
680
+ xml.cardCode(credit_card.verification_value) if credit_card.verification_value
681
+ end
682
+ end
683
+ end
469
684
  end
470
685
  end
471
686
 
472
- # Contains the merchant’s payment gateway account authentication information
473
- def add_arb_merchant_authentication(xml)
474
- xml.tag!('merchantAuthentication') do
475
- xml.tag!('name', @options[:login])
476
- xml.tag!('transactionKey', @options[:password])
687
+ def create_customer_profile(credit_card, options)
688
+ commit(:cim_store) do |xml|
689
+ xml.profile do
690
+ xml.merchantCustomerId(truncate(options[:merchant_customer_id], 20) || SecureRandom.hex(10))
691
+ xml.description(truncate(options[:description], 255)) unless empty?(options[:description])
692
+ xml.email(options[:email]) unless empty?(options[:email])
693
+
694
+ xml.paymentProfiles do
695
+ xml.customerType("individual")
696
+ add_billing_address(xml, credit_card, options)
697
+ add_shipping_address(xml, options, "shipToList")
698
+ xml.payment do
699
+ xml.creditCard do
700
+ xml.cardNumber(truncate(credit_card.number, 16))
701
+ xml.expirationDate(format(credit_card.year, :four_digits) + '-' + format(credit_card.month, :two_digits))
702
+ xml.cardCode(credit_card.verification_value) if credit_card.verification_value
703
+ end
704
+ end
705
+ end
706
+ end
477
707
  end
478
708
  end
479
709
 
480
- # Builds body for ARBCreateSubscriptionRequest
481
- def build_arb_create_subscription_request(xml, options)
482
- # Subscription
483
- add_arb_subscription(xml, options)
710
+ def delete_customer_profile(customer_profile_id)
711
+ commit(:cim_store_delete_customer) do |xml|
712
+ xml.customerProfileId(customer_profile_id)
713
+ end
714
+ end
484
715
 
485
- xml.target!
716
+ def names_from(payment_source, address, options)
717
+ if payment_source && !payment_source.is_a?(PaymentToken) && !payment_source.is_a?(String)
718
+ first_name, last_name = split_names(address[:name])
719
+ [(payment_source.first_name || first_name), (payment_source.last_name || last_name)]
720
+ else
721
+ [options[:first_name], options[:last_name]]
722
+ end
486
723
  end
487
724
 
488
- # Builds body for ARBUpdateSubscriptionRequest
489
- def build_arb_update_subscription_request(xml, options)
490
- xml.tag!('subscriptionId', options[:subscription_id])
491
- # Adds Subscription
492
- add_arb_subscription(xml, options)
725
+ def state_from(address, options)
726
+ if ["US", "CA"].include?(address[:country])
727
+ address[:state] || 'NC'
728
+ else
729
+ address[:state] || 'n/a'
730
+ end
731
+ end
493
732
 
494
- xml.target!
733
+ def headers
734
+ { 'Content-Type' => 'text/xml' }
495
735
  end
496
736
 
497
- # Builds body for ARBCancelSubscriptionRequest
498
- def build_arb_cancel_subscription_request(xml, options)
499
- xml.tag!('subscriptionId', options[:subscription_id])
737
+ def url
738
+ test? ? test_url : live_url
739
+ end
500
740
 
501
- xml.target!
741
+ def parse(action, raw_response)
742
+ if is_cim_action?(action) || action == :verify_credentials
743
+ parse_cim(raw_response)
744
+ else
745
+ parse_normal(action, raw_response)
746
+ end
502
747
  end
503
748
 
504
- # Builds body for ARBGetSubscriptionStatusRequest
505
- def build_arb_status_subscription_request(xml, options)
506
- xml.tag!('subscriptionId', options[:subscription_id])
749
+ def commit(action, &payload)
750
+ raw_response = ssl_post(url, post_data(action, &payload), headers)
751
+ response = parse(action, raw_response)
507
752
 
508
- xml.target!
753
+ avs_result_code = response[:avs_result_code].upcase if response[:avs_result_code]
754
+ avs_result = AVSResult.new(code: STANDARD_AVS_CODE_MAPPING[avs_result_code])
755
+ cvv_result = CVVResult.new(response[:card_code])
756
+ if using_live_gateway_in_test_mode?(response)
757
+ Response.new(false, "Using a live Authorize.net account in Test Mode is not permitted.")
758
+ else
759
+ Response.new(
760
+ success_from(action, response),
761
+ message_from(action, response, avs_result, cvv_result),
762
+ response,
763
+ authorization: authorization_from(action, response),
764
+ test: test?,
765
+ avs_result: avs_result,
766
+ cvv_result: cvv_result,
767
+ fraud_review: fraud_review?(response),
768
+ error_code: map_error_code(response[:response_code], response[:response_reason_code])
769
+ )
770
+ end
771
+ end
772
+
773
+ def is_cim_action?(action)
774
+ action.to_s.start_with?("cim")
509
775
  end
510
776
 
511
- # Adds subscription information
512
- def add_arb_subscription(xml, options)
513
- xml.tag!('subscription') do
514
- # Merchant-assigned name for the subscription (optional)
515
- xml.tag!('name', options[:subscription_name]) if options[:subscription_name]
516
- # Contains information about the payment schedule
517
- add_arb_payment_schedule(xml, options)
518
- # The amount to be billed to the customer
519
- # for each payment in the subscription
520
- xml.tag!('amount', amount(options[:amount])) if options[:amount]
521
- if trial = options[:trial]
522
- # The amount to be charged for each payment during a trial period (conditional)
523
- xml.tag!('trialAmount', amount(trial[:amount])) if trial[:amount]
777
+ def post_data(action)
778
+ Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
779
+ xml.send(root_for(action), 'xmlns' => 'AnetApi/xml/v1/schema/AnetApiSchema.xsd') do
780
+ add_authentication(xml)
781
+ yield(xml)
524
782
  end
525
- # Contains either the customer’s credit card
526
- # or bank account payment information
527
- add_arb_payment(xml, options)
528
- # Contains order information (optional)
529
- add_arb_order(xml, options)
530
- # Contains information about the customer
531
- add_arb_customer(xml, options)
532
- # Contains the customer's billing address information
533
- add_arb_address(xml, 'billTo', options[:billing_address])
534
- # Contains the customer's shipping address information (optional)
535
- add_arb_address(xml, 'shipTo', options[:shipping_address])
783
+ end.to_xml(indent: 0)
784
+ end
785
+
786
+ def root_for(action)
787
+ if action == :cim_store
788
+ "createCustomerProfileRequest"
789
+ elsif action == :cim_store_update
790
+ "createCustomerPaymentProfileRequest"
791
+ elsif action == :cim_store_delete_customer
792
+ "deleteCustomerProfileRequest"
793
+ elsif action == :verify_credentials
794
+ "authenticateTestRequest"
795
+ elsif is_cim_action?(action)
796
+ "createCustomerProfileTransactionRequest"
797
+ else
798
+ "createTransactionRequest"
536
799
  end
537
800
  end
538
801
 
539
- # Adds information about the interval of time between payments
540
- def add_arb_interval(xml, options)
541
- interval = options[:interval]
542
- return unless interval
543
- xml.tag!('interval') do
544
- # The measurement of time, in association with the Interval Unit,
545
- # that is used to define the frequency of the billing occurrences
546
- xml.tag!('length', interval[:length])
547
- # The unit of time, in association with the Interval Length,
548
- # between each billing occurrence
549
- xml.tag!('unit', interval[:unit].to_s)
550
- end
802
+ def add_authentication(xml)
803
+ xml.merchantAuthentication do
804
+ xml.name(@options[:login])
805
+ xml.transactionKey(@options[:password])
806
+ end
807
+ end
808
+
809
+ def parse_normal(action, body)
810
+ doc = Nokogiri::XML(body)
811
+ doc.remove_namespaces!
812
+
813
+ response = {action: action}
814
+
815
+ response[:response_code] = if(element = doc.at_xpath("//transactionResponse/responseCode"))
816
+ (empty?(element.content) ? nil : element.content.to_i)
817
+ end
818
+
819
+ if(element = doc.at_xpath("//errors/error"))
820
+ response[:response_reason_code] = element.at_xpath("errorCode").content[/0*(\d+)$/, 1]
821
+ response[:response_reason_text] = element.at_xpath("errorText").content.chomp('.')
822
+ elsif(element = doc.at_xpath("//transactionResponse/messages/message"))
823
+ response[:response_reason_code] = element.at_xpath("code").content[/0*(\d+)$/, 1]
824
+ response[:response_reason_text] = element.at_xpath("description").content.chomp('.')
825
+ elsif(element = doc.at_xpath("//messages/message"))
826
+ response[:response_reason_code] = element.at_xpath("code").content[/0*(\d+)$/, 1]
827
+ response[:response_reason_text] = element.at_xpath("text").content.chomp('.')
828
+ else
829
+ response[:response_reason_code] = nil
830
+ response[:response_reason_text] = ""
831
+ end
832
+
833
+ response[:avs_result_code] = if(element = doc.at_xpath("//avsResultCode"))
834
+ (empty?(element.content) ? nil : element.content)
835
+ end
836
+
837
+ response[:transaction_id] = if(element = doc.at_xpath("//transId"))
838
+ (empty?(element.content) ? nil : element.content)
839
+ end
840
+
841
+ response[:card_code] = if(element = doc.at_xpath("//cvvResultCode"))
842
+ (empty?(element.content) ? nil : element.content)
843
+ end
844
+
845
+ response[:authorization_code] = if(element = doc.at_xpath("//authCode"))
846
+ (empty?(element.content) ? nil : element.content)
847
+ end
848
+
849
+ response[:cardholder_authentication_code] = if(element = doc.at_xpath("//cavvResultCode"))
850
+ (empty?(element.content) ? nil : element.content)
851
+ end
852
+
853
+ response[:account_number] = if(element = doc.at_xpath("//accountNumber"))
854
+ (empty?(element.content) ? nil : element.content[-4..-1])
855
+ end
856
+
857
+ response[:test_request] = if(element = doc.at_xpath("//testRequest"))
858
+ (empty?(element.content) ? nil : element.content)
859
+ end
860
+
861
+ response
551
862
  end
552
863
 
553
- # Adds information about the subscription duration
554
- def add_arb_duration(xml, options)
555
- duration = options[:duration]
556
- return unless duration
557
- # The date the subscription begins
558
- # (also the date the initial billing occurs)
559
- xml.tag!('startDate', duration[:start_date]) if duration[:start_date]
560
- # Number of billing occurrences or payments for the subscription
561
- xml.tag!('totalOccurrences', duration[:occurrences]) if duration[:occurrences]
562
- end
563
-
564
- def add_arb_payment_schedule(xml, options)
565
- return unless options[:interval] || options[:duration]
566
- xml.tag!('paymentSchedule') do
567
- # Contains information about the interval of time between payments
568
- add_arb_interval(xml, options)
569
- add_arb_duration(xml, options)
570
- if trial = options[:trial]
571
- # Number of billing occurrences or payments in the trial period (optional)
572
- xml.tag!('trialOccurrences', trial[:occurrences]) if trial[:occurrences]
573
- end
574
- end
575
- end
576
-
577
- # Adds customer's credit card or bank account payment information
578
- def add_arb_payment(xml, options)
579
- return unless options[:credit_card] || options[:bank_account]
580
- xml.tag!('payment') do
581
- # Contains the customer’s credit card information
582
- add_arb_credit_card(xml, options)
583
- # Contains the customer’s bank account information
584
- add_arb_bank_account(xml, options)
585
- end
586
- end
587
-
588
- # Adds customer’s credit card information
589
- # Note: This element should only be included
590
- # when the payment method is credit card.
591
- def add_arb_credit_card(xml, options)
592
- credit_card = options[:credit_card]
593
- return unless credit_card
594
- xml.tag!('creditCard') do
595
- # The credit card number used for payment of the subscription
596
- xml.tag!('cardNumber', credit_card.number)
597
- # The expiration date of the credit card used for the subscription
598
- xml.tag!('expirationDate', arb_expdate(credit_card))
599
- end
600
- end
601
-
602
- # Adds customer’s bank account information
603
- # Note: This element should only be included
604
- # when the payment method is bank account.
605
- def add_arb_bank_account(xml, options)
606
- bank_account = options[:bank_account]
607
- return unless bank_account
608
- xml.tag!('bankAccount') do
609
- # The type of bank account used for payment of the subscription
610
- xml.tag!('accountType', bank_account[:account_type])
611
- # The routing number of the customer’s bank
612
- xml.tag!('routingNumber', bank_account[:routing_number])
613
- # The bank account number used for payment of the subscription
614
- xml.tag!('accountNumber', bank_account[:account_number])
615
- # The full name of the individual associated
616
- # with the bank account number
617
- xml.tag!('nameOfAccount', bank_account[:name_of_account])
618
- # The full name of the individual associated
619
- # with the bank account number (optional)
620
- xml.tag!('bankName', bank_account[:bank_name]) if bank_account[:bank_name]
621
- # The type of electronic check transaction used for the subscription
622
- xml.tag!('echeckType', bank_account[:echeck_type])
623
- end
624
- end
625
-
626
- # Adds order information (optional)
627
- def add_arb_order(xml, options)
628
- order = options[:order]
629
- return unless order
630
- xml.tag!('order') do
631
- # Merchant-assigned invoice number for the subscription (optional)
632
- xml.tag!('invoiceNumber', order[:invoice_number])
633
- # Description of the subscription (optional)
634
- xml.tag!('description', order[:description])
635
- end
636
- end
637
-
638
- # Adds information about the customer
639
- def add_arb_customer(xml, options)
640
- customer = options[:customer]
641
- return unless customer
642
- xml.tag!('customer') do
643
- xml.tag!('type', customer[:type]) if customer[:type]
644
- xml.tag!('id', customer[:id]) if customer[:id]
645
- xml.tag!('email', customer[:email]) if customer[:email]
646
- xml.tag!('phoneNumber', customer[:phone_number]) if customer[:phone_number]
647
- xml.tag!('faxNumber', customer[:fax_number]) if customer[:fax_number]
648
- add_arb_drivers_license(xml, options)
649
- xml.tag!('taxId', customer[:tax_id]) if customer[:tax_id]
650
- end
651
- end
652
-
653
- # Adds the customer's driver's license information (conditional)
654
- def add_arb_drivers_license(xml, options)
655
- return unless customer = options[:customer]
656
- return unless drivers_license = customer[:drivers_license]
657
- xml.tag!('driversLicense') do
658
- # The customer's driver's license number
659
- xml.tag!('number', drivers_license[:number])
660
- # The customer's driver's license state
661
- xml.tag!('state', drivers_license[:state])
662
- # The customer's driver's license date of birth
663
- xml.tag!('dateOfBirth', drivers_license[:date_of_birth])
664
- end
665
- end
666
-
667
- # Adds address information
668
- def add_arb_address(xml, container_name, address)
669
- return if address.blank?
670
- xml.tag!(container_name) do
671
- xml.tag!('firstName', address[:first_name])
672
- xml.tag!('lastName', address[:last_name])
673
- xml.tag!('company', address[:company])
674
- xml.tag!('address', address[:address1])
675
- xml.tag!('city', address[:city])
676
- xml.tag!('state', address[:state])
677
- xml.tag!('zip', address[:zip])
678
- xml.tag!('country', address[:country])
679
- end
680
- end
681
-
682
- def arb_expdate(credit_card)
683
- sprintf('%04d-%02d', credit_card.year, credit_card.month)
684
- end
685
-
686
- def recurring_commit(action, request)
687
- url = test? ? arb_test_url : arb_live_url
688
- xml = ssl_post(url, request, "Content-Type" => "text/xml")
689
-
690
- response = recurring_parse(action, xml)
691
-
692
- message = response[:message] || response[:text]
693
- test_mode = test? || message =~ /Test Mode/
694
- success = response[:result_code] == 'Ok'
695
-
696
- Response.new(success, message, response,
697
- :test => test_mode,
698
- :authorization => response[:subscription_id]
699
- )
700
- end
701
-
702
- def recurring_parse(action, xml)
864
+ def parse_cim(body)
703
865
  response = {}
704
- xml = REXML::Document.new(xml)
705
- root = REXML::XPath.first(xml, "//#{RECURRING_ACTIONS[action]}Response") ||
706
- REXML::XPath.first(xml, "//ErrorResponse")
707
- if root
708
- root.elements.to_a.each do |node|
709
- recurring_parse_element(response, node)
710
- end
866
+
867
+ doc = Nokogiri::XML(body).remove_namespaces!
868
+
869
+ if (element = doc.at_xpath("//messages/message"))
870
+ response[:message_code] = element.at_xpath("code").content[/0*(\d+)$/, 1]
871
+ response[:message_text] = element.at_xpath("text").content.chomp('.')
711
872
  end
712
873
 
874
+ response[:result_code] = if(element = doc.at_xpath("//messages/resultCode"))
875
+ (empty?(element.content) ? nil : element.content)
876
+ end
877
+
878
+ response[:test_request] = if(element = doc.at_xpath("//testRequest"))
879
+ (empty?(element.content) ? nil : element.content)
880
+ end
881
+
882
+ response[:customer_profile_id] = if(element = doc.at_xpath("//customerProfileId"))
883
+ (empty?(element.content) ? nil : element.content)
884
+ end
885
+
886
+ response[:customer_payment_profile_id] = if(element = doc.at_xpath("//customerPaymentProfileIdList/numericString"))
887
+ (empty?(element.content) ? nil : element.content)
888
+ end
889
+
890
+ response[:customer_payment_profile_id] = if(element = doc.at_xpath("//customerPaymentProfileIdList/numericString") ||
891
+ doc.at_xpath("//customerPaymentProfileId"))
892
+ (empty?(element.content) ? nil : element.content)
893
+ end
894
+
895
+ response[:direct_response] = if(element = doc.at_xpath("//directResponse"))
896
+ (empty?(element.content) ? nil : element.content)
897
+ end
898
+
899
+ response.merge!(parse_direct_response_elements(response))
900
+
713
901
  response
714
902
  end
715
903
 
716
- def recurring_parse_element(response, node)
717
- if node.has_elements?
718
- node.elements.each{|e| recurring_parse_element(response, e) }
904
+ def success_from(action, response)
905
+ if cim?(action) || (action == :verify_credentials)
906
+ response[:result_code] == "Ok"
907
+ else
908
+ [APPROVED, FRAUD_REVIEW].include?(response[:response_code]) && TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
909
+ end
910
+ end
911
+
912
+ def message_from(action, response, avs_result, cvv_result)
913
+ if response[:response_code] == DECLINED
914
+ if CARD_CODE_ERRORS.include?(cvv_result.code)
915
+ return cvv_result.message
916
+ elsif(AVS_REASON_CODES.include?(response[:response_reason_code]) && AVS_ERRORS.include?(avs_result.code))
917
+ return avs_result.message
918
+ end
919
+ end
920
+
921
+ response[:response_reason_text] || response[:message_text]
922
+ end
923
+
924
+ def authorization_from(action, response)
925
+ if cim?(action)
926
+ [response[:customer_profile_id], response[:customer_payment_profile_id], action].join("#")
719
927
  else
720
- response[node.name.underscore.to_sym] = node.text
928
+ [response[:transaction_id], response[:account_number], action].join("#")
721
929
  end
722
930
  end
931
+
932
+ def split_authorization(authorization)
933
+ authorization.split("#")
934
+ end
935
+
936
+ def cim?(action)
937
+ (action == :cim_store) || (action == :cim_store_update) || (action == :cim_store_delete_customer)
938
+ end
939
+
940
+ def transaction_id_from(authorization)
941
+ transaction_id, _, _ = split_authorization(authorization)
942
+ transaction_id
943
+ end
944
+
945
+ def fraud_review?(response)
946
+ (response[:response_code] == FRAUD_REVIEW)
947
+ end
948
+
949
+ def using_live_gateway_in_test_mode?(response)
950
+ !test? && response[:test_request] == "1"
951
+ end
952
+
953
+ def map_error_code(response_code, response_reason_code)
954
+ STANDARD_ERROR_CODE_MAPPING["#{response_code}#{response_reason_code}"]
955
+ end
956
+
957
+ def auth_was_for_cim?(authorization)
958
+ _, _, action = split_authorization(authorization)
959
+ action && is_cim_action?(action)
960
+ end
961
+
962
+ def parse_direct_response_elements(response)
963
+ params = response[:direct_response]
964
+ return {} unless params
965
+
966
+ parts = params.split(',')
967
+ {
968
+ response_code: parts[0].to_i,
969
+ response_subcode: parts[1],
970
+ response_reason_code: parts[2],
971
+ response_reason_text: parts[3],
972
+ approval_code: parts[4],
973
+ avs_result_code: parts[5],
974
+ transaction_id: parts[6],
975
+ invoice_number: parts[7],
976
+ order_description: parts[8],
977
+ amount: parts[9],
978
+ method: parts[10],
979
+ transaction_type: parts[11],
980
+ customer_id: parts[12],
981
+ first_name: parts[13],
982
+ last_name: parts[14],
983
+ company: parts[15],
984
+ address: parts[16],
985
+ city: parts[17],
986
+ state: parts[18],
987
+ zip_code: parts[19],
988
+ country: parts[20],
989
+ phone: parts[21],
990
+ fax: parts[22],
991
+ email_address: parts[23],
992
+ ship_to_first_name: parts[24],
993
+ ship_to_last_name: parts[25],
994
+ ship_to_company: parts[26],
995
+ ship_to_address: parts[27],
996
+ ship_to_city: parts[28],
997
+ ship_to_state: parts[29],
998
+ ship_to_zip_code: parts[30],
999
+ ship_to_country: parts[31],
1000
+ tax: parts[32],
1001
+ duty: parts[33],
1002
+ freight: parts[34],
1003
+ tax_exempt: parts[35],
1004
+ purchase_order_number: parts[36],
1005
+ md5_hash: parts[37],
1006
+ card_code: parts[38],
1007
+ cardholder_authentication_verification_response: parts[39],
1008
+ account_number: parts[50] || '',
1009
+ card_type: parts[51] || '',
1010
+ split_tender_id: parts[52] || '',
1011
+ requested_amount: parts[53] || '',
1012
+ balance_on_card: parts[54] || '',
1013
+ }
1014
+ end
1015
+
723
1016
  end
724
1017
  end
725
1018
  end