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,1267 @@
1
+ require 'active_merchant/billing/gateways/orbital/orbital_soft_descriptors'
2
+ require 'rexml/document'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ # For more information on Orbital, visit the {integration center}[http://download.chasepaymentech.com]
7
+ #
8
+ # ==== Authentication Options
9
+ #
10
+ # The Orbital Gateway supports two methods of authenticating incoming requests:
11
+ # Source IP authentication and Connection Username/Password authentication
12
+ #
13
+ # In addition, these IP addresses/Connection Usernames must be affiliated with the Merchant IDs
14
+ # for which the client should be submitting transactions.
15
+ #
16
+ # This does allow Third Party Hosting service organizations presenting on behalf of other
17
+ # merchants to submit transactions. However, each time a new customer is added, the
18
+ # merchant or Third-Party hosting organization needs to ensure that the new Merchant IDs
19
+ # or Chain IDs are affiliated with the hosting companies IPs or Connection Usernames.
20
+ #
21
+ # If the merchant expects to have more than one merchant account with the Orbital
22
+ # Gateway, it should have its IP addresses/Connection Usernames affiliated at the Chain
23
+ # level hierarchy within the Orbital Gateway. Each time a new merchant ID is added, as
24
+ # long as it is placed within the same Chain, it will simply work. Otherwise, the additional
25
+ # MIDs will need to be affiliated with the merchant IPs or Connection Usernames respectively.
26
+ # For example, we generally affiliate all Salem accounts [BIN 000001] with
27
+ # their Company Number [formerly called MA #] number so all MIDs or Divisions under that
28
+ # Company will automatically be affiliated.
29
+
30
+ class OrbitalGateway < Gateway
31
+ include Empty
32
+
33
+ API_VERSION = '9.0'
34
+
35
+ POST_HEADERS = {
36
+ 'MIME-Version' => '1.1',
37
+ 'Content-Type' => "application/PTI#{API_VERSION.delete('.')}",
38
+ 'Content-transfer-encoding' => 'text',
39
+ 'Request-number' => '1',
40
+ 'Document-type' => 'Request',
41
+ 'Interface-Version' => 'Ruby|ActiveMerchant|Proprietary Gateway'
42
+ }
43
+
44
+ SUCCESS = '0'
45
+ APPROVAL_SUCCESS = '1'
46
+
47
+ APPROVED = [
48
+ '00', # Approved
49
+ '08', # Approved authorization, honor with ID
50
+ '11', # Approved authorization, VIP approval
51
+ '24', # Validated
52
+ '26', # Pre-noted
53
+ '27', # No reason to decline
54
+ '28', # Received and stored
55
+ '29', # Provided authorization
56
+ '31', # Request received
57
+ '32', # BIN alert
58
+ '34', # Approved for partial
59
+ '91', # Approved low fraud
60
+ '92', # Approved medium fraud
61
+ '93', # Approved high fraud
62
+ '94', # Approved fraud service unavailable
63
+ 'E7', # Stored
64
+ 'PA', # Partial approval
65
+ 'P1' # ECP - AVS - Account Status Verification and/or AOA data is in a positive status.
66
+ ]
67
+
68
+ class_attribute :secondary_test_url, :secondary_live_url
69
+
70
+ self.test_url = 'https://orbitalvar1.chasepaymentech.com/authorize'
71
+ self.secondary_test_url = 'https://orbitalvar2.chasepaymentech.com/authorize'
72
+
73
+ self.live_url = 'https://orbital1.chasepaymentech.com/authorize'
74
+ self.secondary_live_url = 'https://orbital2.chasepaymentech.com/authorize'
75
+
76
+ self.supported_countries = %w[US CA]
77
+ self.default_currency = 'CAD'
78
+ self.supported_cardtypes = %i[visa master american_express discover diners_club jcb]
79
+
80
+ self.display_name = 'Orbital Paymentech'
81
+ self.homepage_url = 'http://chasepaymentech.com/'
82
+
83
+ self.money_format = :cents
84
+
85
+ AVS_SUPPORTED_COUNTRIES = %w[US CA UK GB]
86
+
87
+ CURRENCY_CODES = {
88
+ 'AUD' => '036',
89
+ 'BRL' => '986',
90
+ 'CAD' => '124',
91
+ 'CLP' => '152',
92
+ 'CZK' => '203',
93
+ 'DKK' => '208',
94
+ 'HKD' => '344',
95
+ 'ICK' => '352',
96
+ 'JPY' => '392',
97
+ 'MXN' => '484',
98
+ 'NZD' => '554',
99
+ 'NOK' => '578',
100
+ 'SGD' => '702',
101
+ 'ZAR' => '710',
102
+ 'SEK' => '752',
103
+ 'CHF' => '756',
104
+ 'GBP' => '826',
105
+ 'USD' => '840',
106
+ 'EUR' => '978'
107
+ }
108
+
109
+ CURRENCY_EXPONENTS = {
110
+ 'AUD' => '2',
111
+ 'BRL' => '2',
112
+ 'CAD' => '2',
113
+ 'CLP' => '2',
114
+ 'CZK' => '2',
115
+ 'DKK' => '2',
116
+ 'HKD' => '2',
117
+ 'ICK' => '2',
118
+ 'JPY' => '0',
119
+ 'MXN' => '2',
120
+ 'NZD' => '2',
121
+ 'NOK' => '2',
122
+ 'SGD' => '2',
123
+ 'ZAR' => '2',
124
+ 'SEK' => '2',
125
+ 'CHF' => '2',
126
+ 'GBP' => '2',
127
+ 'USD' => '2',
128
+ 'EUR' => '2'
129
+ }
130
+
131
+ # INDUSTRY TYPES
132
+ ECOMMERCE_TRANSACTION = 'EC'
133
+ RECURRING_PAYMENT_TRANSACTION = 'RC'
134
+ MAIL_ORDER_TELEPHONE_ORDER_TRANSACTION = 'MO'
135
+ INTERACTIVE_VOICE_RESPONSE = 'IV'
136
+ # INTERACTIVE_VOICE_RESPONSE = 'IN'
137
+
138
+ # Auth Only No Capture
139
+ AUTH_ONLY = 'A'
140
+ # AC - Auth and Capture = 'AC'
141
+ AUTH_AND_CAPTURE = 'AC'
142
+ # F - Force Auth No Capture and no online authorization = 'F'
143
+ FORCE_AUTH_ONLY = 'F'
144
+ # FR - Force Auth No Capture and no online authorization = 'FR'
145
+ # FC - Force Auth and Capture no online authorization = 'FC'
146
+ FORCE_AUTH_AND_CAPTURE = 'FC'
147
+ # Refund and Capture no online authorization
148
+ REFUND = 'R'
149
+
150
+ # Tax Inds
151
+ TAX_NOT_PROVIDED = 0
152
+ TAX_INCLUDED = 1
153
+ NON_TAXABLE_TRANSACTION = 2
154
+
155
+ # Customer Profile Actions
156
+ CREATE = 'C'
157
+ RETRIEVE = 'R'
158
+ UPDATE = 'U'
159
+ DELETE = 'D'
160
+
161
+ RECURRING = 'R'
162
+ DEFERRED = 'D'
163
+
164
+ # Status
165
+ # Profile Status Flag
166
+ # This field is used to set the status of a Customer Profile.
167
+ ACTIVE = 'A'
168
+ INACTIVE = 'I'
169
+ MANUAL_SUSPEND = 'MS'
170
+
171
+ # CustomerProfileOrderOverrideInd
172
+ # Defines if any Order Data can be pre-populated from
173
+ # the Customer Reference Number (CustomerRefNum)
174
+ NO_MAPPING_TO_ORDER_DATA = 'NO'
175
+ USE_CRN_FOR_ORDER_ID = 'OI'
176
+ USE_CRN_FOR_COMMENTS = 'OD'
177
+ USE_CRN_FOR_ORDER_ID_AND_COMMENTS = 'OA'
178
+
179
+ # CustomerProfileFromOrderInd
180
+ # Method to use to Generate the Customer Profile Number
181
+ # When Customer Profile Action Type = Create, defines
182
+ # what the Customer Profile Number will be:
183
+ AUTO_GENERATE = 'A' # Auto-Generate the CustomerRefNum
184
+ USE_CUSTOMER_REF_NUM = 'S' # Use CustomerRefNum field
185
+ USE_ORDER_ID = 'O' # Use OrderID field
186
+ USE_COMMENTS = 'D' # Use Comments field
187
+
188
+ SENSITIVE_FIELDS = %i[account_num cc_account_num]
189
+
190
+ # Bank account types to be used for check processing
191
+ ACCOUNT_TYPE = {
192
+ 'savings' => 'S',
193
+ 'checking' => 'C'
194
+ }
195
+
196
+ def initialize(options = {})
197
+ requires!(options, :merchant_id)
198
+ requires!(options, :login, :password) unless options[:ip_authentication]
199
+ super
200
+ @options[:merchant_id] = @options[:merchant_id].to_s
201
+ @use_secondary_url = false
202
+ end
203
+
204
+ # A – Authorization request
205
+ def authorize(money, payment_source, options = {})
206
+ # ECP for Orbital requires $0 prenotes so ensure
207
+ # if we are doing a force capture with a check, that
208
+ # we do a purchase here
209
+ return purchase(money, payment_source, options) if force_capture_with_echeck?(payment_source, options)
210
+
211
+ order = build_new_auth_purchase_order(AUTH_ONLY, money, payment_source, options)
212
+
213
+ commit(order, :authorize, options[:retry_logic], options[:trace_number])
214
+ end
215
+
216
+ def verify(credit_card, options = {})
217
+ amount = options[:verify_amount] ? options[:verify_amount].to_i : default_verify_amount(credit_card)
218
+ MultiResponse.run(:use_first_response) do |r|
219
+ r.process { authorize(amount, credit_card, options) }
220
+ r.process(:ignore_result) { void(r.authorization) } unless amount == 0
221
+ end
222
+ end
223
+
224
+ # AC – Authorization and Capture
225
+ def purchase(money, payment_source, options = {})
226
+ action = options[:force_capture] ? FORCE_AUTH_AND_CAPTURE : AUTH_AND_CAPTURE
227
+ order = build_new_auth_purchase_order(action, money, payment_source, options)
228
+
229
+ commit(order, :purchase, options[:retry_logic], options[:trace_number])
230
+ end
231
+
232
+ # MFC - Mark For Capture
233
+ def capture(money, authorization, options = {})
234
+ commit(build_mark_for_capture_xml(money, authorization, options), :capture, options[:retry_logic], options[:trace_number])
235
+ end
236
+
237
+ # R – Refund request
238
+ def refund(money, authorization, options = {})
239
+ payment_method = options[:payment_method]
240
+ order = build_new_order_xml(REFUND, money, payment_method, options.merge(authorization: authorization)) do |xml|
241
+ add_payment_source(xml, payment_method, options)
242
+ xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn]
243
+ end
244
+
245
+ commit(order, :refund, options[:retry_logic], options[:trace_number])
246
+ end
247
+
248
+ def credit(money, payment_method, options = {})
249
+ order = build_new_order_xml(REFUND, money, payment_method, options) do |xml|
250
+ add_payment_source(xml, payment_method, options)
251
+ end
252
+
253
+ commit(order, :refund, options[:retry_logic], options[:trace_number])
254
+ end
255
+
256
+ def void(authorization, options = {}, deprecated = {})
257
+ if !options.kind_of?(Hash)
258
+ ActiveMerchant.deprecated('Calling the void method with an amount parameter is deprecated and will be removed in a future version.')
259
+ return void(options, deprecated.merge(amount: authorization))
260
+ end
261
+
262
+ order = build_void_request_xml(authorization, options)
263
+
264
+ commit(order, :void, options[:retry_logic], options[:trace_number])
265
+ end
266
+
267
+ def default_verify_amount(credit_card)
268
+ allow_zero_auth?(credit_card) ? 0 : 100
269
+ end
270
+
271
+ def allow_zero_auth?(credit_card)
272
+ # Discover does not support a $0.00 authorization instead use $1.00
273
+ %w(visa master american_express diners_club jcb).include?(credit_card.brand)
274
+ end
275
+
276
+ # ==== Customer Profiles
277
+ # :customer_ref_num should be set unless you're happy with Orbital providing one
278
+ #
279
+ # :customer_profile_order_override_ind can be set to map
280
+ # the CustomerRefNum to OrderID or Comments. Defaults to 'NO' - no mapping
281
+ #
282
+ # 'NO' - No mapping to order data
283
+ # 'OI' - Use <CustomerRefNum> for <OrderID>
284
+ # 'OD' - Use <CustomerRefNum> for <Comments>
285
+ # 'OA' - Use <CustomerRefNum> for <OrderID> and <Comments>
286
+ #
287
+ # :order_default_description can be set optionally. 64 char max.
288
+ #
289
+ # :order_default_amount can be set optionally. integer as cents.
290
+ #
291
+ # :status defaults to Active
292
+ #
293
+ # 'A' - Active
294
+ # 'I' - Inactive
295
+ # 'MS' - Manual Suspend
296
+
297
+ def add_customer_profile(credit_card, options = {})
298
+ options[:customer_profile_action] = CREATE
299
+ order = build_customer_request_xml(credit_card, options)
300
+ commit(order, :add_customer_profile)
301
+ end
302
+
303
+ def update_customer_profile(credit_card, options = {})
304
+ options[:customer_profile_action] = UPDATE
305
+ order = build_customer_request_xml(credit_card, options)
306
+ commit(order, :update_customer_profile)
307
+ end
308
+
309
+ def retrieve_customer_profile(customer_ref_num)
310
+ options = { customer_profile_action: RETRIEVE, customer_ref_num: customer_ref_num }
311
+ order = build_customer_request_xml(nil, options)
312
+ commit(order, :retrieve_customer_profile)
313
+ end
314
+
315
+ def delete_customer_profile(customer_ref_num)
316
+ options = { customer_profile_action: DELETE, customer_ref_num: customer_ref_num }
317
+ order = build_customer_request_xml(nil, options)
318
+ commit(order, :delete_customer_profile)
319
+ end
320
+
321
+ def supports_network_tokenization?
322
+ true
323
+ end
324
+
325
+ def supports_scrubbing?
326
+ true
327
+ end
328
+
329
+ def scrub(transcript)
330
+ transcript.
331
+ gsub(%r((<OrbitalConnectionUsername>).+(</OrbitalConnectionUsername>)), '\1[FILTERED]\2').
332
+ gsub(%r((<OrbitalConnectionPassword>).+(</OrbitalConnectionPassword>)), '\1[FILTERED]\2').
333
+ gsub(%r((<AccountNum>).+(</AccountNum>)), '\1[FILTERED]\2').
334
+ # the response sometimes contains a new line that cuts off the end of the closing tag
335
+ gsub(%r((<CCAccountNum>).+(</CC)), '\1[FILTERED]\2').
336
+ gsub(%r((<CardSecVal>).+(</CardSecVal>)), '\1[FILTERED]\2').
337
+ gsub(%r((<MerchantID>).+(</MerchantID>)), '\1[FILTERED]\2').
338
+ gsub(%r((<CustomerMerchantID>).+(</CustomerMerchantID>)), '\1[FILTERED]\2').
339
+ gsub(%r((<CustomerProfileMessage>).+(</CustomerProfileMessage>)), '\1[FILTERED]\2').
340
+ gsub(%r((<CheckDDA>).+(</CheckDDA>)), '\1[FILTERED]\2').
341
+ gsub(%r((<BCRtNum>).+(</BCRtNum>)), '\1[FILTERED]\2').
342
+ gsub(%r((<DigitalTokenCryptogram>).+(</DigitalTokenCryptogram>)), '\1[FILTERED]\2')
343
+ end
344
+
345
+ private
346
+
347
+ def force_capture_with_echeck?(payment_source, options)
348
+ return false unless options[:force_capture]
349
+ return false unless payment_source.is_a?(Check)
350
+
351
+ %w(W8 W9 ND).include?(options[:action_code])
352
+ end
353
+
354
+ #=====REFERENCE FIELDS=====
355
+
356
+ def add_customer_data(xml, credit_card, options)
357
+ add_customer_ref_num(xml, options)
358
+
359
+ return if options[:profile_txn]
360
+
361
+ xml.tag! :CustomerProfileFromOrderInd, profile_number(options) if add_profile_number?(options, credit_card)
362
+ xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA
363
+ end
364
+
365
+ def add_profile_number?(options, credit_card)
366
+ return true unless options[:customer_ref_num] && credit_card.nil?
367
+ end
368
+
369
+ def profile_number(options)
370
+ options[:customer_ref_num] ? USE_CUSTOMER_REF_NUM : AUTO_GENERATE
371
+ end
372
+
373
+ def add_customer_ref_num(xml, options)
374
+ xml.tag! :CustomerRefNum, options[:customer_ref_num] if options[:customer_ref_num]
375
+ end
376
+
377
+ def add_tx_ref_num(xml, authorization)
378
+ return unless authorization
379
+
380
+ xml.tag! :TxRefNum, split_authorization(authorization).first
381
+ end
382
+
383
+ def authorization_string(*args)
384
+ args.compact.join(';')
385
+ end
386
+
387
+ def split_authorization(authorization)
388
+ authorization.split(';')
389
+ end
390
+
391
+ #=====DESCRIPTOR FIELDS=====
392
+
393
+ def add_soft_descriptors(xml, descriptors)
394
+ return unless descriptors
395
+
396
+ add_soft_descriptors_from_specialized_class(xml, descriptors) if descriptors.is_a?(OrbitalSoftDescriptors)
397
+ add_soft_descriptors_from_hash(xml, descriptors) if descriptors.is_a?(Hash)
398
+ end
399
+
400
+ def add_payment_action_ind(xml, payment_action_ind)
401
+ return unless payment_action_ind
402
+
403
+ xml.tag! :PaymentActionInd, payment_action_ind
404
+ end
405
+
406
+ def add_soft_descriptors_from_specialized_class(xml, soft_desc)
407
+ xml.tag! :SDMerchantName, soft_desc.merchant_name if soft_desc.merchant_name
408
+ xml.tag! :SDProductDescription, soft_desc.product_description if soft_desc.product_description
409
+ xml.tag! :SDMerchantCity, soft_desc.merchant_city if soft_desc.merchant_city
410
+ xml.tag! :SDMerchantPhone, soft_desc.merchant_phone if soft_desc.merchant_phone
411
+ xml.tag! :SDMerchantURL, soft_desc.merchant_url if soft_desc.merchant_url
412
+ xml.tag! :SDMerchantEmail, soft_desc.merchant_email if soft_desc.merchant_email
413
+ end
414
+
415
+ def add_soft_descriptors_from_hash(xml, soft_desc)
416
+ xml.tag! :SDMerchantName, soft_desc[:merchant_name] || nil
417
+ xml.tag! :SDProductDescription, soft_desc[:product_description] || nil
418
+ xml.tag! :SDMerchantCity, soft_desc[:merchant_city] || nil
419
+ xml.tag! :SDMerchantPhone, soft_desc[:merchant_phone] || nil
420
+ xml.tag! :SDMerchantURL, soft_desc[:merchant_url] || nil
421
+ xml.tag! :SDMerchantEmail, soft_desc[:merchant_email] || nil
422
+ end
423
+
424
+ def add_level2_tax(xml, options = {})
425
+ if (level2 = options[:level_2_data])
426
+ xml.tag! :TaxInd, level2[:tax_indicator] if [TAX_NOT_PROVIDED, TAX_INCLUDED, NON_TAXABLE_TRANSACTION].include?(level2[:tax_indicator].to_i)
427
+ xml.tag! :Tax, level2[:tax].to_i if level2[:tax]
428
+ end
429
+ end
430
+
431
+ def add_level3_tax(xml, options = {})
432
+ if (level3 = options[:level_3_data])
433
+ xml.tag! :PC3VATtaxAmt, byte_limit(level3[:vat_tax], 12) if level3[:vat_tax]
434
+ xml.tag! :PC3VATtaxRate, byte_limit(level3[:vat_rate], 4) if level3[:vat_rate]
435
+ xml.tag! :PC3AltTaxInd, byte_limit(level3[:alt_ind], 15) if level3[:alt_ind]
436
+ xml.tag! :PC3AltTaxAmt, byte_limit(level3[:alt_tax], 9) if level3[:alt_tax]
437
+ end
438
+ end
439
+
440
+ def add_level2_advice_addendum(xml, options = {})
441
+ if (level2 = options[:level_2_data])
442
+ xml.tag! :AMEXTranAdvAddn1, byte_limit(level2[:advice_addendum_1], 40) if level2[:advice_addendum_1]
443
+ xml.tag! :AMEXTranAdvAddn2, byte_limit(level2[:advice_addendum_2], 40) if level2[:advice_addendum_2]
444
+ xml.tag! :AMEXTranAdvAddn3, byte_limit(level2[:advice_addendum_3], 40) if level2[:advice_addendum_3]
445
+ xml.tag! :AMEXTranAdvAddn4, byte_limit(level2[:advice_addendum_4], 40) if level2[:advice_addendum_4]
446
+ end
447
+ end
448
+
449
+ def add_level2_purchase(xml, options = {})
450
+ if (level2 = options[:level_2_data])
451
+ xml.tag! :PCOrderNum, byte_limit(level2[:purchase_order], 17) if level2[:purchase_order]
452
+ xml.tag! :PCDestZip, byte_limit(format_address_field(level2[:zip]), 10) if level2[:zip]
453
+ xml.tag! :PCDestName, byte_limit(format_address_field(level2[:name]), 30) if level2[:name]
454
+ xml.tag! :PCDestAddress1, byte_limit(format_address_field(level2[:address1]), 30) if level2[:address1]
455
+ xml.tag! :PCDestAddress2, byte_limit(format_address_field(level2[:address2]), 30) if level2[:address2]
456
+ xml.tag! :PCDestCity, byte_limit(format_address_field(level2[:city]), 20) if level2[:city]
457
+ xml.tag! :PCDestState, byte_limit(format_address_field(level2[:state]), 2) if level2[:state]
458
+ end
459
+ end
460
+
461
+ def add_level3_purchase(xml, options = {})
462
+ if (level3 = options[:level_3_data])
463
+ xml.tag! :PC3FreightAmt, byte_limit(level3[:freight_amount], 12) if level3[:freight_amount]
464
+ xml.tag! :PC3DutyAmt, byte_limit(level3[:duty_amount], 12) if level3[:duty_amount]
465
+ xml.tag! :PC3DestCountryCd, byte_limit(level3[:dest_country], 3) if level3[:dest_country]
466
+ xml.tag! :PC3ShipFromZip, byte_limit(level3[:ship_from_zip], 10) if level3[:ship_from_zip]
467
+ xml.tag! :PC3DiscAmt, byte_limit(level3[:discount_amount], 12) if level3[:discount_amount]
468
+ end
469
+ end
470
+
471
+ def add_line_items(xml, options = {})
472
+ xml.tag! :PC3LineItemCount, byte_limit(options[:line_items].count, 2)
473
+ xml.tag! :PC3LineItemArray do
474
+ options[:line_items].each_with_index do |line_item, index|
475
+ xml.tag! :PC3LineItem do
476
+ xml.tag! :PC3DtlIndex, byte_limit(index + 1, 2)
477
+ line_item.each do |key, value|
478
+ if [:line_tot, 'line_tot'].include? key
479
+ formatted_key = :PC3Dtllinetot
480
+ else
481
+ formatted_key = "PC3Dtl#{key.to_s.camelize}".to_sym
482
+ end
483
+ xml.tag! formatted_key, value
484
+ end
485
+ end
486
+ end
487
+ end
488
+ end
489
+
490
+ #=====ADDRESS FIELDS=====
491
+
492
+ def add_address(xml, payment_source, options)
493
+ return unless (address = get_address(options))
494
+
495
+ if avs_supported?(address[:country]) || empty?(address[:country])
496
+ xml.tag! :AVSzip, byte_limit(format_address_field(address[:zip]), 10)
497
+ xml.tag! :AVSaddress1, byte_limit(format_address_field(address[:address1]), 30)
498
+ xml.tag! :AVSaddress2, byte_limit(format_address_field(address[:address2]), 30)
499
+ xml.tag! :AVScity, byte_limit(format_address_field(address[:city]), 20)
500
+ xml.tag! :AVSstate, byte_limit(format_address_field(address[:state]), 2)
501
+ xml.tag! :AVSphoneNum, (address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil)
502
+ end
503
+
504
+ xml.tag! :AVSname, billing_name(payment_source, options)
505
+ xml.tag! :AVScountryCode, byte_limit(format_address_field(filter_unsupported_countries(address[:country])), 2)
506
+
507
+ # Needs to come after AVScountryCode
508
+ add_destination_address(xml, address) if avs_supported?(address[:country]) || empty?(address[:country])
509
+ end
510
+
511
+ def add_destination_address(xml, address)
512
+ return unless address[:dest_zip]
513
+
514
+ xml.tag! :AVSDestzip, byte_limit(format_address_field(address[:dest_zip]), 10)
515
+ xml.tag! :AVSDestaddress1, byte_limit(format_address_field(address[:dest_address1]), 30)
516
+ xml.tag! :AVSDestaddress2, byte_limit(format_address_field(address[:dest_address2]), 30)
517
+ xml.tag! :AVSDestcity, byte_limit(format_address_field(address[:dest_city]), 20)
518
+ xml.tag! :AVSDeststate, byte_limit(format_address_field(address[:dest_state]), 2)
519
+ xml.tag! :AVSDestphoneNum, (address[:dest_phone] ? address[:dest_phone].scan(/\d/).join.to_s[0..13] : nil)
520
+ xml.tag! :AVSDestname, byte_limit(address[:dest_name], 30)
521
+ xml.tag! :AVSDestcountryCode, filter_unsupported_countries(address[:dest_country])
522
+ end
523
+
524
+ # For Profile requests
525
+ def add_customer_address(xml, options)
526
+ return unless (address = get_address(options))
527
+
528
+ xml.tag! :CustomerAddress1, byte_limit(format_address_field(address[:address1]), 30)
529
+ xml.tag! :CustomerAddress2, byte_limit(format_address_field(address[:address2]), 30)
530
+ xml.tag! :CustomerCity, byte_limit(format_address_field(address[:city]), 20)
531
+ xml.tag! :CustomerState, byte_limit(format_address_field(address[:state]), 2)
532
+ xml.tag! :CustomerZIP, byte_limit(format_address_field(address[:zip]), 10)
533
+ xml.tag! :CustomerEmail, byte_limit(address[:email], 50) if address[:email]
534
+ xml.tag! :CustomerPhone, (address[:phone] ? address[:phone].scan(/\d/).join.to_s : nil)
535
+ xml.tag! :CustomerCountryCode, filter_unsupported_countries(address[:country])
536
+ end
537
+
538
+ def billing_name(payment_source, options)
539
+ if payment_source&.name.present?
540
+ payment_source.name[0..29]
541
+ elsif options[:billing_address][:name].present?
542
+ options[:billing_address][:name][0..29]
543
+ end
544
+ end
545
+
546
+ def avs_supported?(address)
547
+ AVS_SUPPORTED_COUNTRIES.include?(address.to_s)
548
+ end
549
+
550
+ def filter_unsupported_countries(address)
551
+ avs_supported?(address) ? address.to_s : ''
552
+ end
553
+
554
+ def get_address(options)
555
+ options[:billing_address] || options[:address]
556
+ end
557
+
558
+ #=====PAYMENT SOURCE FIELDS=====
559
+
560
+ # Payment can be done through either Credit Card or Electronic Check
561
+ def add_payment_source(xml, payment_source, options = {})
562
+ payment_source.is_a?(Check) ? add_echeck(xml, payment_source, options) : add_credit_card(xml, payment_source, options)
563
+ end
564
+
565
+ def add_echeck(xml, check, options = {})
566
+ return unless check
567
+
568
+ xml.tag! :CardBrand, 'EC'
569
+ add_currency_fields(xml, options[:currency])
570
+ xml.tag! :BCRtNum, check.routing_number
571
+ xml.tag! :CheckDDA, check.account_number if check.account_number
572
+ add_bank_account_type(xml, check)
573
+ xml.tag! :ECPAuthMethod, options[:auth_method] if options[:auth_method]
574
+ xml.tag! :BankPmtDelv, options[:payment_delivery] || 'B'
575
+ xml.tag! :AVSname, (check&.name ? check.name[0..29] : nil) if get_address(options).blank?
576
+ end
577
+
578
+ def add_credit_card(xml, credit_card, options)
579
+ xml.tag! :AccountNum, credit_card.number if credit_card
580
+ xml.tag! :Exp, expiry_date(credit_card) if credit_card
581
+ add_currency_fields(xml, options[:currency])
582
+ add_verification_value(xml, credit_card) if credit_card
583
+ end
584
+
585
+ def add_verification_value(xml, credit_card)
586
+ return unless credit_card&.verification_value?
587
+
588
+ # If you are trying to collect a Card Verification Number
589
+ # (CardSecVal) for a Visa or Discover transaction, pass one of these values:
590
+ # 1 Value is Present
591
+ # 2 Value on card but illegible
592
+ # 9 Cardholder states data not available
593
+ # If the transaction is not a Visa or Discover transaction:
594
+ # Null-fill this attribute OR
595
+ # Do not submit the attribute at all.
596
+ # - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
597
+ xml.tag! :CardSecValInd, '1' if %w(visa discover diners_club).include?(credit_card.brand)
598
+ xml.tag! :CardSecVal, credit_card.verification_value
599
+ end
600
+
601
+ def add_currency_fields(xml, currency)
602
+ xml.tag! :CurrencyCode, currency_code(currency)
603
+ xml.tag! :CurrencyExponent, currency_exponents(currency)
604
+ end
605
+
606
+ def add_bank_account_type(xml, check)
607
+ bank_account_type =
608
+ if check.account_holder_type == 'business'
609
+ 'X'
610
+ else
611
+ ACCOUNT_TYPE[check.account_type]
612
+ end
613
+
614
+ xml.tag! :BankAccountType, bank_account_type if bank_account_type
615
+ end
616
+
617
+ def add_card_indicators(xml, options)
618
+ xml.tag! :CardIndicators, options[:card_indicators] if options[:card_indicators]
619
+ end
620
+
621
+ def currency_code(currency)
622
+ CURRENCY_CODES[(currency || self.default_currency)].to_s
623
+ end
624
+
625
+ def currency_exponents(currency)
626
+ CURRENCY_EXPONENTS[(currency || self.default_currency)].to_s
627
+ end
628
+
629
+ def expiry_date(credit_card)
630
+ "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
631
+ end
632
+
633
+ def bin
634
+ @options[:bin] || (salem_mid? ? '000001' : '000002')
635
+ end
636
+
637
+ def salem_mid?
638
+ @options[:merchant_id].length == 6
639
+ end
640
+
641
+ #=====BRAND-SPECIFIC FIELDS=====
642
+
643
+ def add_cavv(xml, credit_card, three_d_secure)
644
+ return unless three_d_secure && credit_card.brand == 'visa'
645
+
646
+ xml.tag!(:CAVV, three_d_secure[:cavv])
647
+ end
648
+
649
+ def add_aav(xml, credit_card, three_d_secure)
650
+ return unless three_d_secure && credit_card.brand == 'master'
651
+
652
+ xml.tag!(:AAV, three_d_secure[:cavv])
653
+ end
654
+
655
+ def add_aevv(xml, credit_card, three_d_secure)
656
+ return unless three_d_secure && credit_card.brand == 'american_express'
657
+
658
+ xml.tag!(:AEVV, three_d_secure[:cavv])
659
+ end
660
+
661
+ def add_xid(xml, credit_card, three_d_secure)
662
+ return unless three_d_secure && credit_card.brand == 'visa'
663
+
664
+ xml.tag!(:XID, three_d_secure[:xid]) if three_d_secure[:xid]
665
+ end
666
+
667
+ def add_pymt_brand_program_code(xml, credit_card, three_d_secure)
668
+ return unless three_d_secure && credit_card.brand == 'american_express'
669
+
670
+ xml.tag!(:PymtBrandProgramCode, 'ASK')
671
+ end
672
+
673
+ def mastercard?(payment_source)
674
+ payment_source.is_a?(CreditCard) && payment_source.brand == 'master'
675
+ end
676
+
677
+ def add_mastercard_fields(xml, credit_card, parameters, three_d_secure)
678
+ add_mc_sca_merchant_initiated(xml, credit_card, parameters, three_d_secure)
679
+ add_mc_sca_recurring(xml, credit_card, parameters, three_d_secure)
680
+ add_mc_program_protocol(xml, credit_card, three_d_secure)
681
+ add_mc_directory_trans_id(xml, credit_card, three_d_secure)
682
+ add_mc_ucafind(xml, credit_card, three_d_secure)
683
+ end
684
+
685
+ def add_mc_sca_merchant_initiated(xml, credit_card, parameters, three_d_secure)
686
+ return unless parameters.try(:[], :sca_merchant_initiated)
687
+ return unless three_d_secure.try(:[], :eci) == '7'
688
+
689
+ xml.tag!(:SCAMerchantInitiatedTransaction, parameters[:sca_merchant_initiated])
690
+ end
691
+
692
+ def add_mc_sca_recurring(xml, credit_card, parameters, three_d_secure)
693
+ return unless parameters.try(:[], :sca_recurring)
694
+ return unless three_d_secure.try(:[], :eci) == '7'
695
+
696
+ xml.tag!(:SCARecurringPayment, parameters[:sca_recurring])
697
+ end
698
+
699
+ def add_mc_program_protocol(xml, credit_card, three_d_secure)
700
+ return unless version = three_d_secure.try(:[], :version)
701
+
702
+ xml.tag!(:MCProgramProtocol, version.to_s[0])
703
+ end
704
+
705
+ def add_mc_directory_trans_id(xml, credit_card, three_d_secure)
706
+ return unless three_d_secure
707
+
708
+ xml.tag!(:MCDirectoryTransID, three_d_secure[:ds_transaction_id]) if three_d_secure[:ds_transaction_id]
709
+ end
710
+
711
+ def add_mc_ucafind(xml, credit_card, three_d_secure)
712
+ return unless three_d_secure
713
+
714
+ xml.tag! :UCAFInd, '4'
715
+ end
716
+
717
+ #=====SCA (STORED CREDENTIAL) FIELDS=====
718
+
719
+ def add_stored_credentials(xml, parameters)
720
+ return unless parameters[:mit_stored_credential_ind] == 'Y' || parameters[:stored_credential] && !parameters[:stored_credential].values.all?(&:nil?)
721
+
722
+ if msg_type = get_msg_type(parameters)
723
+ xml.tag! :MITMsgType, msg_type
724
+ end
725
+ xml.tag! :MITStoredCredentialInd, 'Y'
726
+ if parameters[:mit_submitted_transaction_id]
727
+ xml.tag! :MITSubmittedTransactionID, parameters[:mit_submitted_transaction_id]
728
+ elsif parameters.dig(:stored_credential, :network_transaction_id) && parameters.dig(:stored_credential, :initiator) == 'merchant'
729
+ xml.tag! :MITSubmittedTransactionID, parameters[:stored_credential][:network_transaction_id]
730
+ end
731
+ end
732
+
733
+ def get_msg_type(parameters)
734
+ return parameters[:mit_msg_type] if parameters[:mit_msg_type]
735
+ return 'CSTO' if parameters[:stored_credential][:initial_transaction]
736
+ return unless parameters[:stored_credential][:initiator] && parameters[:stored_credential][:reason_type]
737
+
738
+ initiator =
739
+ case parameters[:stored_credential][:initiator]
740
+ when 'cardholder', 'customer' then 'C'
741
+ when 'merchant' then 'M'
742
+ end
743
+ reason =
744
+ case parameters[:stored_credential][:reason_type]
745
+ when 'recurring' then 'REC'
746
+ when 'installment' then 'INS'
747
+ when 'unscheduled' then 'USE'
748
+ end
749
+
750
+ "#{initiator}#{reason}"
751
+ end
752
+
753
+ #=====NETWORK TOKENIZATION FIELDS=====
754
+
755
+ def add_eci(xml, credit_card, three_d_secure)
756
+ eci = if three_d_secure
757
+ three_d_secure[:eci]
758
+ elsif credit_card.is_a?(NetworkTokenizationCreditCard)
759
+ credit_card.eci
760
+ end
761
+
762
+ xml.tag!(:AuthenticationECIInd, eci) if eci
763
+ end
764
+
765
+ def add_dpanind(xml, credit_card, industry_type = nil)
766
+ return unless credit_card.is_a?(NetworkTokenizationCreditCard)
767
+
768
+ xml.tag! :DPANInd, 'Y' unless industry_type == 'RC'
769
+ end
770
+
771
+ def add_digital_token_cryptogram(xml, credit_card, three_d_secure)
772
+ return unless credit_card.is_a?(NetworkTokenizationCreditCard) || three_d_secure && credit_card.brand == 'discover'
773
+
774
+ cryptogram =
775
+ if three_d_secure && credit_card.brand == 'discover'
776
+ three_d_secure[:cavv]
777
+ else
778
+ credit_card.payment_cryptogram
779
+ end
780
+
781
+ xml.tag!(:DigitalTokenCryptogram, cryptogram)
782
+ end
783
+
784
+ #=====OTHER FIELDS=====
785
+
786
+ # For Canadian transactions on PNS Tampa on New Order
787
+ # RF - First Recurring Transaction
788
+ # RS - Subsequent Recurring Transactions
789
+ def set_recurring_ind(xml, parameters)
790
+ return unless parameters[:recurring_ind]
791
+ raise 'RecurringInd must be set to either "RF" or "RS"' unless %w(RF RS).include?(parameters[:recurring_ind])
792
+
793
+ xml.tag! :RecurringInd, parameters[:recurring_ind]
794
+ end
795
+
796
+ def add_managed_billing(xml, options)
797
+ return unless mb = options[:managed_billing]
798
+
799
+ ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE
800
+
801
+ # default to recurring (R). Other option is deferred (D).
802
+ xml.tag! :MBType, mb[:type] || RECURRING
803
+ # default to Customer Reference Number
804
+ xml.tag! :MBOrderIdGenerationMethod, mb[:order_id_generation_method] || 'IO'
805
+ # By default use MBRecurringEndDate, set to N.
806
+ # MMDDYYYY
807
+ xml.tag! :MBRecurringStartDate, mb[:start_date].scan(/\d/).join.to_s if mb[:start_date]
808
+ # MMDDYYYY
809
+ xml.tag! :MBRecurringEndDate, mb[:end_date].scan(/\d/).join.to_s if mb[:end_date]
810
+ # By default listen to any value set in MBRecurringEndDate.
811
+ xml.tag! :MBRecurringNoEndDateFlag, mb[:no_end_date_flag] || 'N' # 'Y' || 'N' (Yes or No).
812
+ xml.tag! :MBRecurringMaxBillings, mb[:max_billings] if mb[:max_billings]
813
+ xml.tag! :MBRecurringFrequency, mb[:frequency] if mb[:frequency]
814
+ xml.tag! :MBDeferredBillDate, mb[:deferred_bill_date] if mb[:deferred_bill_date]
815
+ xml.tag! :MBMicroPaymentMaxDollarValue, mb[:max_dollar_value] if mb[:max_dollar_value]
816
+ xml.tag! :MBMicroPaymentMaxBillingDays, mb[:max_billing_days] if mb[:max_billing_days]
817
+ xml.tag! :MBMicroPaymentMaxTransactions, mb[:max_transactions] if mb[:max_transactions]
818
+ end
819
+
820
+ def add_ews_details(xml, payment_source, parameters = {})
821
+ split_name = payment_source.first_name.split if payment_source.first_name
822
+ xml.tag! :EWSFirstName, split_name[0]
823
+ xml.tag! :EWSMiddleName, split_name[1..-1].join(' ')
824
+ xml.tag! :EWSLastName, payment_source.last_name
825
+ xml.tag! :EWSBusinessName, parameters[:company] if payment_source.first_name.empty? && payment_source.last_name.empty?
826
+
827
+ if (address = (parameters[:billing_address] || parameters[:address]))
828
+ xml.tag! :EWSAddressLine1, byte_limit(format_address_field(address[:address1]), 30)
829
+ xml.tag! :EWSAddressLine2, byte_limit(format_address_field(address[:address2]), 30)
830
+ xml.tag! :EWSCity, byte_limit(format_address_field(address[:city]), 20)
831
+ xml.tag! :EWSState, byte_limit(format_address_field(address[:state]), 2)
832
+ xml.tag! :EWSZip, byte_limit(format_address_field(address[:zip]), 10)
833
+ end
834
+
835
+ xml.tag! :EWSPhoneType, parameters[:phone_type]
836
+ xml.tag! :EWSPhoneNumber, parameters[:phone_number]
837
+ xml.tag! :EWSCheckSerialNumber, payment_source.account_number unless parameters[:auth_method].eql?('I')
838
+ end
839
+
840
+ # Adds ECP conditional attributes depending on other attribute values
841
+ def add_ecp_details(xml, payment_source, parameters = {})
842
+ requires!(payment_source.account_number) if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
843
+ xml.tag! :ECPActionCode, parameters[:action_code] if parameters[:action_code]
844
+ xml.tag! :ECPCheckSerialNumber, payment_source.account_number if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
845
+ if parameters[:auth_method]&.eql?('P')
846
+ xml.tag! :ECPTerminalCity, parameters[:terminal_city] if parameters[:terminal_city]
847
+ xml.tag! :ECPTerminalState, parameters[:terminal_state] if parameters[:terminal_state]
848
+ xml.tag! :ECPImageReferenceNumber, parameters[:image_reference_number] if parameters[:image_reference_number]
849
+ end
850
+ if parameters[:action_code]&.eql?('W3') || parameters[:action_code]&.eql?('W5') ||
851
+ parameters[:action_code]&.eql?('W7') || parameters[:action_code]&.eql?('W9')
852
+ add_ews_details(xml, payment_source, parameters)
853
+ end
854
+ end
855
+
856
+ def add_xml_credentials(xml)
857
+ unless ip_authentication?
858
+ xml.tag! :OrbitalConnectionUsername, @options[:login]
859
+ xml.tag! :OrbitalConnectionPassword, @options[:password]
860
+ end
861
+ end
862
+
863
+ def add_bin_merchant_and_terminal(xml, parameters)
864
+ xml.tag! :BIN, bin
865
+ xml.tag! :MerchantID, @options[:merchant_id]
866
+ xml.tag! :TerminalID, parameters[:terminal_id] || '001'
867
+ end
868
+
869
+ #=====REQUEST/RESPONSE METHODS=====
870
+
871
+ def commit(order, message_type, retry_logic = nil, trace_number = nil)
872
+ headers = POST_HEADERS.merge('Content-length' => order.size.to_s)
873
+ if (@options[:retry_logic] || retry_logic) && trace_number
874
+ headers['Trace-number'] = trace_number.to_s
875
+ headers['Merchant-Id'] = @options[:merchant_id]
876
+ end
877
+ request = ->(url) { parse(ssl_post(url, order, headers)) }
878
+
879
+ # Failover URL will be attempted in the event of a connection error
880
+ response =
881
+ begin
882
+ raise ConnectionError.new 'Should use secondary url', 500 if @use_secondary_url
883
+
884
+ request.call(remote_url)
885
+ rescue ConnectionError
886
+ request.call(remote_url(:secondary))
887
+ end
888
+
889
+ Response.new(success?(response, message_type), message_from(response), response,
890
+ {
891
+ authorization: authorization_string(response[:tx_ref_num], response[:order_id]),
892
+ test: self.test?,
893
+ avs_result: OrbitalGateway::AVSResult.new(response[:avs_resp_code]),
894
+ cvv_result: OrbitalGateway::CVVResult.new(response[:cvv2_resp_code])
895
+ })
896
+ end
897
+
898
+ def remote_url(url = :primary)
899
+ if url == :primary
900
+ (self.test? ? self.test_url : self.live_url)
901
+ else
902
+ (self.test? ? self.secondary_test_url : self.secondary_live_url)
903
+ end
904
+ end
905
+
906
+ def parse(body)
907
+ response = {}
908
+ xml = REXML::Document.new(strip_invalid_xml_chars(body))
909
+ root = REXML::XPath.first(xml, '//Response') ||
910
+ REXML::XPath.first(xml, '//ErrorResponse')
911
+ if root
912
+ root.elements.to_a.each do |node|
913
+ recurring_parse_element(response, node)
914
+ end
915
+ end
916
+
917
+ response.delete_if { |k, _| SENSITIVE_FIELDS.include?(k) }
918
+ end
919
+
920
+ def recurring_parse_element(response, node)
921
+ if node.has_elements?
922
+ node.elements.each { |e| recurring_parse_element(response, e) }
923
+ else
924
+ response[node.name.underscore.to_sym] = node.text
925
+ end
926
+ end
927
+
928
+ def success?(response, message_type)
929
+ if %i[void].include?(message_type)
930
+ response[:proc_status] == SUCCESS
931
+ elsif %i[refund].include?(message_type)
932
+ response[:proc_status] == SUCCESS && response[:approval_status] == APPROVAL_SUCCESS
933
+ elsif response[:customer_profile_action]
934
+ response[:profile_proc_status] == SUCCESS
935
+ else
936
+ response[:proc_status] == SUCCESS &&
937
+ APPROVED.include?(response[:resp_code])
938
+ end
939
+ end
940
+
941
+ def message_from(response)
942
+ response[:resp_msg] || response[:status_msg] || response[:customer_profile_message]
943
+ end
944
+
945
+ def ip_authentication?
946
+ @options[:ip_authentication] == true
947
+ end
948
+
949
+ #=====BUILDER METHODS=====
950
+
951
+ def build_new_auth_purchase_order(action, money, payment_source, options)
952
+ build_new_order_xml(action, money, payment_source, options) do |xml|
953
+ add_payment_source(xml, payment_source, options)
954
+ add_address(xml, payment_source, options)
955
+ if @options[:customer_profiles]
956
+ add_customer_data(xml, payment_source, options)
957
+ add_managed_billing(xml, options)
958
+ end
959
+ end
960
+ end
961
+
962
+ def build_new_order_xml(action, money, payment_source, parameters = {})
963
+ requires!(parameters, :order_id)
964
+ @use_secondary_url = parameters[:use_secondary_url] if parameters[:use_secondary_url]
965
+ xml = xml_envelope
966
+ xml.tag! :Request do
967
+ xml.tag! :NewOrder do
968
+ add_xml_credentials(xml)
969
+ xml.tag! :IndustryType, parameters[:industry_type] || ECOMMERCE_TRANSACTION
970
+ xml.tag! :MessageType, action
971
+ add_bin_merchant_and_terminal(xml, parameters)
972
+
973
+ yield xml if block_given?
974
+
975
+ three_d_secure = parameters[:three_d_secure]
976
+
977
+ add_eci(xml, payment_source, three_d_secure)
978
+ add_cavv(xml, payment_source, three_d_secure)
979
+ add_xid(xml, payment_source, three_d_secure)
980
+
981
+ xml.tag! :OrderID, format_order_id(parameters[:order_id])
982
+ xml.tag! :Amount, amount(money)
983
+ xml.tag! :Comments, parameters[:comments] if parameters[:comments]
984
+
985
+ add_level2_tax(xml, parameters)
986
+ add_level2_advice_addendum(xml, parameters)
987
+
988
+ add_aav(xml, payment_source, three_d_secure)
989
+ # CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
990
+
991
+ add_soft_descriptors(xml, parameters[:soft_descriptors])
992
+ add_payment_action_ind(xml, parameters[:payment_action_ind])
993
+ add_dpanind(xml, payment_source, parameters[:industry_type])
994
+ add_aevv(xml, payment_source, three_d_secure)
995
+ add_digital_token_cryptogram(xml, payment_source, three_d_secure)
996
+
997
+ xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && payment_source.is_a?(Check)
998
+
999
+ set_recurring_ind(xml, parameters)
1000
+
1001
+ # Append Transaction Reference Number at the end for Refund transactions
1002
+ add_tx_ref_num(xml, parameters[:authorization]) if action == REFUND && payment_source.nil?
1003
+
1004
+ add_level2_purchase(xml, parameters)
1005
+ add_level3_purchase(xml, parameters)
1006
+ add_level3_tax(xml, parameters)
1007
+ add_line_items(xml, parameters) if parameters[:line_items]
1008
+ add_ecp_details(xml, payment_source, parameters) if payment_source.is_a?(Check)
1009
+ add_card_indicators(xml, parameters)
1010
+ add_stored_credentials(xml, parameters)
1011
+ add_pymt_brand_program_code(xml, payment_source, three_d_secure)
1012
+ add_mastercard_fields(xml, payment_source, parameters, three_d_secure) if mastercard?(payment_source)
1013
+ end
1014
+ end
1015
+ xml.target!
1016
+ end
1017
+
1018
+ def build_mark_for_capture_xml(money, authorization, parameters = {})
1019
+ tx_ref_num, order_id = split_authorization(authorization)
1020
+ xml = xml_envelope
1021
+ xml.tag! :Request do
1022
+ xml.tag! :MarkForCapture do
1023
+ add_xml_credentials(xml)
1024
+ xml.tag! :OrderID, format_order_id(order_id)
1025
+ xml.tag! :Amount, amount(money)
1026
+ add_level2_tax(xml, parameters)
1027
+ add_bin_merchant_and_terminal(xml, parameters)
1028
+ xml.tag! :TxRefNum, tx_ref_num
1029
+ add_level2_purchase(xml, parameters)
1030
+ add_level2_advice_addendum(xml, parameters)
1031
+ add_level3_purchase(xml, parameters)
1032
+ add_level3_tax(xml, parameters)
1033
+ add_line_items(xml, parameters) if parameters[:line_items]
1034
+ end
1035
+ end
1036
+ xml.target!
1037
+ end
1038
+
1039
+ def build_void_request_xml(authorization, parameters = {})
1040
+ tx_ref_num, order_id = split_authorization(authorization)
1041
+ xml = xml_envelope
1042
+ xml.tag! :Request do
1043
+ xml.tag! :Reversal do
1044
+ add_xml_credentials(xml)
1045
+ xml.tag! :TxRefNum, tx_ref_num
1046
+ xml.tag! :TxRefIdx, parameters[:transaction_index]
1047
+ xml.tag! :AdjustedAmt, parameters[:amount] # setting adjusted amount to nil will void entire amount
1048
+ xml.tag! :OrderID, format_order_id(order_id || parameters[:order_id])
1049
+ add_bin_merchant_and_terminal(xml, parameters)
1050
+ xml.tag! :ReversalRetryNumber, parameters[:reversal_retry_number] if parameters[:reversal_retry_number]
1051
+ xml.tag! :OnlineReversalInd, parameters[:online_reversal_ind] if parameters[:online_reversal_ind]
1052
+ end
1053
+ end
1054
+ xml.target!
1055
+ end
1056
+
1057
+ def xml_envelope
1058
+ xml = Builder::XmlMarkup.new(indent: 2)
1059
+ xml.instruct!(:xml, version: '1.0', encoding: 'UTF-8')
1060
+ xml
1061
+ end
1062
+
1063
+ # Null characters are possible in some responses (namely, the respMsg field), causing XML parsing errors
1064
+ # Prevent by substituting these with a valid placeholder string
1065
+ def strip_invalid_xml_chars(xml)
1066
+ xml.gsub(/\u0000/, '[null]')
1067
+ end
1068
+
1069
+ # The valid characters include:
1070
+ #
1071
+ # 1. all letters and digits
1072
+ # 2. - , $ @ & and a space character, though the space character cannot be the leading character
1073
+ # 3. PINless Debit transactions can only use uppercase and lowercase alpha (A-Z, a-z) and numeric (0-9)
1074
+ def format_order_id(order_id)
1075
+ illegal_characters = /[^,$@&\- \w]/
1076
+ order_id = order_id.to_s.tr('.', '-')
1077
+ order_id.gsub!(illegal_characters, '')
1078
+ order_id.lstrip!
1079
+ order_id[0...22]
1080
+ end
1081
+
1082
+ # Address-related fields cannot contain % | ^ \ /
1083
+ # Returns the value with these characters removed, or nil
1084
+ def format_address_field(value)
1085
+ value.gsub(/[%\|\^\\\/]/, '') if value.respond_to?(:gsub)
1086
+ end
1087
+
1088
+ # Field lengths should be limited by byte count instead of character count
1089
+ # Returns the truncated value or nil
1090
+ def byte_limit(value, byte_length)
1091
+ limited_value = ''
1092
+
1093
+ value.to_s.each_char do |c|
1094
+ break if (limited_value.bytesize + c.bytesize) > byte_length
1095
+
1096
+ limited_value << c
1097
+ end
1098
+
1099
+ limited_value
1100
+ end
1101
+
1102
+ def build_customer_request_xml(credit_card, options = {})
1103
+ ActiveMerchant.deprecated 'Customer Profile support in Orbital is non-conformant to the ActiveMerchant API and will be removed in its current form in a future version. Please contact the ActiveMerchant maintainers if you have an interest in modifying it to conform to the store/unstore/update API.'
1104
+ xml = xml_envelope
1105
+ xml.tag! :Request do
1106
+ xml.tag! :Profile do
1107
+ xml.tag! :OrbitalConnectionUsername, @options[:login] unless ip_authentication?
1108
+ xml.tag! :OrbitalConnectionPassword, @options[:password] unless ip_authentication?
1109
+ xml.tag! :CustomerBin, bin
1110
+ xml.tag! :CustomerMerchantID, @options[:merchant_id]
1111
+ xml.tag! :CustomerName, credit_card.name if credit_card
1112
+ xml.tag! :CustomerRefNum, options[:customer_ref_num] if options[:customer_ref_num]
1113
+
1114
+ add_customer_address(xml, options)
1115
+
1116
+ xml.tag! :CustomerProfileAction, options[:customer_profile_action] # C, R, U, D
1117
+ # NO No mapping to order data
1118
+ # OI Use <CustomerRefNum> for <OrderID>
1119
+ # OD Use <CustomerReferNum> for <Comments>
1120
+ # OA Use <CustomerRefNum> for <OrderID> and <Comments>
1121
+ xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA
1122
+
1123
+ if options[:customer_profile_action] == CREATE
1124
+ # A Auto-Generate the CustomerRefNum
1125
+ # S Use CustomerRefNum field
1126
+ # O Use OrderID field
1127
+ # D Use Comments field
1128
+ xml.tag! :CustomerProfileFromOrderInd, (options[:customer_ref_num] ? USE_CUSTOMER_REF_NUM : AUTO_GENERATE)
1129
+ end
1130
+
1131
+ xml.tag! :OrderDefaultDescription, options[:order_default_description][0..63] if options[:order_default_description]
1132
+ xml.tag! :OrderDefaultAmount, options[:order_default_amount] if options[:order_default_amount]
1133
+
1134
+ if [CREATE, UPDATE].include? options[:customer_profile_action]
1135
+ xml.tag! :CustomerAccountType, 'CC' # Only credit card supported
1136
+ xml.tag! :Status, options[:status] || ACTIVE # Active
1137
+ end
1138
+
1139
+ xml.tag! :CCAccountNum, credit_card.number if credit_card
1140
+ xml.tag! :CCExpireDate, credit_card.expiry_date.expiration.strftime('%m%y') if credit_card
1141
+
1142
+ # This has to come after CCExpireDate.
1143
+ add_managed_billing(xml, options)
1144
+ end
1145
+ end
1146
+ xml.target!
1147
+ end
1148
+
1149
+ # Unfortunately, Orbital uses their own special codes for AVS responses
1150
+ # that are different than the standard codes defined in
1151
+ # <tt>ActiveMerchant::Billing::AVSResult</tt>.
1152
+ #
1153
+ # This class encapsulates the response codes shown on page 240 of their spec:
1154
+ # http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
1155
+ #
1156
+ class AVSResult < ActiveMerchant::Billing::AVSResult
1157
+ CODES = {
1158
+ '1' => 'No address supplied',
1159
+ '2' => 'Bill-to address did not pass Auth Host edit checks',
1160
+ '3' => 'AVS not performed',
1161
+ '4' => 'Issuer does not participate in AVS',
1162
+ '5' => 'Edit-error - AVS data is invalid',
1163
+ '6' => 'System unavailable or time-out',
1164
+ '7' => 'Address information unavailable',
1165
+ '8' => 'Transaction Ineligible for AVS',
1166
+ '9' => 'Zip Match/Zip 4 Match/Locale match',
1167
+ 'A' => 'Zip Match/Zip 4 Match/Locale no match',
1168
+ 'B' => 'Zip Match/Zip 4 no Match/Locale match',
1169
+ 'C' => 'Zip Match/Zip 4 no Match/Locale no match',
1170
+ 'D' => 'Zip No Match/Zip 4 Match/Locale match',
1171
+ 'E' => 'Zip No Match/Zip 4 Match/Locale no match',
1172
+ 'F' => 'Zip No Match/Zip 4 No Match/Locale match',
1173
+ 'G' => 'No match at all',
1174
+ 'H' => 'Zip Match/Locale match',
1175
+ 'J' => 'Issuer does not participate in Global AVS',
1176
+ 'JA' => 'International street address and postal match',
1177
+ 'JB' => 'International street address match. Postal code not verified',
1178
+ 'JC' => 'International street address and postal code not verified',
1179
+ 'JD' => 'International postal code match. Street address not verified',
1180
+ 'M1' => 'Cardholder name matches',
1181
+ 'M2' => 'Cardholder name, billing address, and postal code matches',
1182
+ 'M3' => 'Cardholder name and billing code matches',
1183
+ 'M4' => 'Cardholder name and billing address match',
1184
+ 'M5' => 'Cardholder name incorrect, billing address and postal code match',
1185
+ 'M6' => 'Cardholder name incorrect, billing postal code matches',
1186
+ 'M7' => 'Cardholder name incorrect, billing address matches',
1187
+ 'M8' => 'Cardholder name, billing address and postal code are all incorrect',
1188
+ 'N3' => 'Address matches, ZIP not verified',
1189
+ 'N4' => 'Address and ZIP code not verified due to incompatible formats',
1190
+ 'N5' => 'Address and ZIP code match (International only)',
1191
+ 'N6' => 'Address not verified (International only)',
1192
+ 'N7' => 'ZIP matches, address not verified',
1193
+ 'N8' => 'Address and ZIP code match (International only)',
1194
+ 'N9' => 'Address and ZIP code match (UK only)',
1195
+ 'R' => 'Issuer does not participate in AVS',
1196
+ 'UK' => 'Unknown',
1197
+ 'X' => 'Zip Match/Zip 4 Match/Address Match',
1198
+ 'Z' => 'Zip Match/Locale no match'
1199
+ }
1200
+
1201
+ # Map vendor's AVS result code to a postal match code
1202
+ ORBITAL_POSTAL_MATCH_CODE = {
1203
+ 'Y' => %w(9 A B C H JA JD M2 M3 M5 N5 N8 N9 X Z),
1204
+ 'N' => %w(D E F G M8),
1205
+ 'X' => %w(4 J R),
1206
+ nil => %w(1 2 3 5 6 7 8 JB JC M1 M4 M6 M7 N3 N4 N6 N7 UK)
1207
+ }.inject({}) do |map, (type, codes)|
1208
+ codes.each { |code| map[code] = type }
1209
+ map
1210
+ end
1211
+
1212
+ # Map vendor's AVS result code to a street match code
1213
+ ORBITAL_STREET_MATCH_CODE = {
1214
+ 'Y' => %w(9 B D F H JA JB M2 M4 M5 M6 M7 N3 N5 N7 N8 N9 X),
1215
+ 'N' => %w(A C E G M8 Z),
1216
+ 'X' => %w(4 J R),
1217
+ nil => %w(1 2 3 5 6 7 8 JC JD M1 M3 N4 N6 UK)
1218
+ }.inject({}) do |map, (type, codes)|
1219
+ codes.each { |code| map[code] = type }
1220
+ map
1221
+ end
1222
+
1223
+ def self.messages
1224
+ CODES
1225
+ end
1226
+
1227
+ def initialize(code)
1228
+ @code = (code.blank? ? nil : code.to_s.strip.upcase)
1229
+ if @code
1230
+ @message = CODES[@code]
1231
+ @postal_match = ORBITAL_POSTAL_MATCH_CODE[@code]
1232
+ @street_match = ORBITAL_STREET_MATCH_CODE[@code]
1233
+ end
1234
+ end
1235
+ end
1236
+
1237
+ # Unfortunately, Orbital uses their own special codes for CVV responses
1238
+ # that are different than the standard codes defined in
1239
+ # <tt>ActiveMerchant::Billing::CVVResult</tt>.
1240
+ #
1241
+ # This class encapsulates the response codes shown on page 255 of their spec:
1242
+ # http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
1243
+ #
1244
+ class CVVResult < ActiveMerchant::Billing::CVVResult
1245
+ MESSAGES = {
1246
+ 'M' => 'Match',
1247
+ 'N' => 'No match',
1248
+ 'P' => 'Not processed',
1249
+ 'S' => 'Should have been present',
1250
+ 'U' => 'Unsupported by issuer/Issuer unable to process request',
1251
+ 'I' => 'Invalid',
1252
+ 'Y' => 'Invalid',
1253
+ '' => 'Not applicable'
1254
+ }
1255
+
1256
+ def self.messages
1257
+ MESSAGES
1258
+ end
1259
+
1260
+ def initialize(code)
1261
+ @code = code.blank? ? '' : code.upcase
1262
+ @message = MESSAGES[@code]
1263
+ end
1264
+ end
1265
+ end
1266
+ end
1267
+ end