archetype2142_activemerchant 1.124.0

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