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.
- checksums.yaml +7 -0
- data/CHANGELOG +4033 -0
- data/CONTRIBUTORS +568 -0
- data/MIT-LICENSE +20 -0
- data/README.md +252 -0
- data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
- data/lib/active_merchant/billing/avs_result.rb +95 -0
- data/lib/active_merchant/billing/base.rb +48 -0
- data/lib/active_merchant/billing/check.rb +112 -0
- data/lib/active_merchant/billing/compatibility.rb +118 -0
- data/lib/active_merchant/billing/credit_card.rb +451 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +512 -0
- data/lib/active_merchant/billing/cvv_result.rb +37 -0
- data/lib/active_merchant/billing/gateway.rb +332 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +774 -0
- data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
- data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
- data/lib/active_merchant/billing/gateways/allied_wallet.rb +205 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +1125 -0
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +424 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +977 -0
- data/lib/active_merchant/billing/gateways/axcessms.rb +242 -0
- data/lib/active_merchant/billing/gateways/balanced.rb +263 -0
- data/lib/active_merchant/billing/gateways/bambora_apac.rb +222 -0
- data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
- data/lib/active_merchant/billing/gateways/banwire.rb +116 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +397 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
- data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +474 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +238 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +57 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +549 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +644 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +190 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +272 -0
- data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +28 -0
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +952 -0
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +19 -0
- data/lib/active_merchant/billing/gateways/bridge_pay.rb +244 -0
- data/lib/active_merchant/billing/gateways/cams.rb +230 -0
- data/lib/active_merchant/billing/gateways/card_connect.rb +338 -0
- data/lib/active_merchant/billing/gateways/card_save.rb +21 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +394 -0
- data/lib/active_merchant/billing/gateways/cardknox.rb +327 -0
- data/lib/active_merchant/billing/gateways/cardprocess.rb +256 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +235 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +198 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +249 -0
- data/lib/active_merchant/billing/gateways/cenpos.rb +328 -0
- data/lib/active_merchant/billing/gateways/checkout.rb +212 -0
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +587 -0
- data/lib/active_merchant/billing/gateways/citrus_pay.rb +21 -0
- data/lib/active_merchant/billing/gateways/clearhaus.rb +219 -0
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +366 -0
- data/lib/active_merchant/billing/gateways/commercegate.rb +142 -0
- data/lib/active_merchant/billing/gateways/conekta.rb +230 -0
- data/lib/active_merchant/billing/gateways/creditcall.rb +272 -0
- data/lib/active_merchant/billing/gateways/credorax.rb +526 -0
- data/lib/active_merchant/billing/gateways/ct_payment.rb +269 -0
- data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
- data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +1148 -0
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +454 -0
- data/lib/active_merchant/billing/gateways/d_local.rb +343 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +302 -0
- data/lib/active_merchant/billing/gateways/decidir.rb +358 -0
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
- data/lib/active_merchant/billing/gateways/dibs.rb +199 -0
- data/lib/active_merchant/billing/gateways/digitzs.rb +295 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +346 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +215 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +475 -0
- data/lib/active_merchant/billing/gateways/element.rb +406 -0
- data/lib/active_merchant/billing/gateways/epay.rb +296 -0
- data/lib/active_merchant/billing/gateways/evo_ca.rb +307 -0
- data/lib/active_merchant/billing/gateways/eway.rb +226 -0
- data/lib/active_merchant/billing/gateways/eway_managed.rb +289 -0
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +578 -0
- data/lib/active_merchant/billing/gateways/exact.rb +219 -0
- data/lib/active_merchant/billing/gateways/ezic.rb +195 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +223 -0
- data/lib/active_merchant/billing/gateways/federated_canada.rb +158 -0
- data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
- data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +182 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +452 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +505 -0
- data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
- data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
- data/lib/active_merchant/billing/gateways/fluidpay.rb +275 -0
- data/lib/active_merchant/billing/gateways/forte.rb +286 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +256 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +580 -0
- data/lib/active_merchant/billing/gateways/global_transport.rb +193 -0
- data/lib/active_merchant/billing/gateways/hdfc.rb +205 -0
- data/lib/active_merchant/billing/gateways/hps.rb +472 -0
- data/lib/active_merchant/billing/gateways/iats_payments.rb +312 -0
- data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +159 -0
- data/lib/active_merchant/billing/gateways/ipg.rb +420 -0
- data/lib/active_merchant/billing/gateways/ipp.rb +176 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +467 -0
- data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
- data/lib/active_merchant/billing/gateways/iveri.rb +290 -0
- data/lib/active_merchant/billing/gateways/ixopay.rb +320 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +395 -0
- data/lib/active_merchant/billing/gateways/jetpay_v2.rb +432 -0
- data/lib/active_merchant/billing/gateways/klarna.rb +317 -0
- data/lib/active_merchant/billing/gateways/komoju.rb +115 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +297 -0
- data/lib/active_merchant/billing/gateways/latitude19.rb +412 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +448 -0
- data/lib/active_merchant/billing/gateways/litle.rb +643 -0
- data/lib/active_merchant/billing/gateways/mastercard.rb +286 -0
- data/lib/active_merchant/billing/gateways/maxipago.rb +220 -0
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +348 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +228 -0
- data/lib/active_merchant/billing/gateways/merchant_one.rb +110 -0
- data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +313 -0
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +284 -0
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +248 -0
- data/lib/active_merchant/billing/gateways/mercury.rb +352 -0
- data/lib/active_merchant/billing/gateways/metrics_global.rb +293 -0
- data/lib/active_merchant/billing/gateways/micropayment.rb +182 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/migs.rb +329 -0
- data/lib/active_merchant/billing/gateways/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +215 -0
- data/lib/active_merchant/billing/gateways/moka.rb +290 -0
- data/lib/active_merchant/billing/gateways/monei.rb +424 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +488 -0
- data/lib/active_merchant/billing/gateways/money_movers.rb +150 -0
- data/lib/active_merchant/billing/gateways/mundipagg.rb +366 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +299 -0
- data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +163 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
- data/lib/active_merchant/billing/gateways/netaxept.rb +180 -0
- data/lib/active_merchant/billing/gateways/netbanx.rb +376 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +229 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/network_merchants.rb +238 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +396 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +509 -0
- data/lib/active_merchant/billing/gateways/omise.rb +323 -0
- data/lib/active_merchant/billing/gateways/openpay.rb +246 -0
- data/lib/active_merchant/billing/gateways/opp.rb +394 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +331 -0
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +45 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +1267 -0
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +206 -0
- data/lib/active_merchant/billing/gateways/pagarme.rb +239 -0
- data/lib/active_merchant/billing/gateways/pago_facil.rb +120 -0
- data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_conex.rb +245 -0
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
- data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +206 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +110 -0
- data/lib/active_merchant/billing/gateways/pay_trace.rb +450 -0
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +224 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +513 -0
- data/lib/active_merchant/billing/gateways/payex.rb +409 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +235 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +42 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +473 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +220 -0
- data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +14 -0
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +20 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +373 -0
- data/lib/active_merchant/billing/gateways/paymentez.rb +365 -0
- data/lib/active_merchant/billing/gateways/paymill.rb +369 -0
- data/lib/active_merchant/billing/gateways/paynetworx.rb +228 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +718 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +69 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +136 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +272 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
- data/lib/active_merchant/billing/gateways/paypal_standard.rb +281 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +420 -0
- data/lib/active_merchant/billing/gateways/payscout.rb +159 -0
- data/lib/active_merchant/billing/gateways/paystation.rb +204 -0
- data/lib/active_merchant/billing/gateways/payu_in.rb +249 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +482 -0
- data/lib/active_merchant/billing/gateways/payway.rb +207 -0
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
- data/lib/active_merchant/billing/gateways/pin.rb +273 -0
- data/lib/active_merchant/billing/gateways/pixxels.rb +263 -0
- data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
- data/lib/active_merchant/billing/gateways/priority.rb +392 -0
- data/lib/active_merchant/billing/gateways/pro_pay.rb +325 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +227 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +295 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +302 -0
- data/lib/active_merchant/billing/gateways/quantum.rb +274 -0
- data/lib/active_merchant/billing/gateways/quickbooks.rb +377 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +184 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +297 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +226 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +24 -0
- data/lib/active_merchant/billing/gateways/qvalent.rb +305 -0
- data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
- data/lib/active_merchant/billing/gateways/reach.rb +277 -0
- data/lib/active_merchant/billing/gateways/realex.rb +400 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +723 -0
- data/lib/active_merchant/billing/gateways/s5.rb +247 -0
- data/lib/active_merchant/billing/gateways/safe_charge.rb +298 -0
- data/lib/active_merchant/billing/gateways/sage.rb +446 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +434 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +141 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +260 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +191 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +290 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +103 -0
- data/lib/active_merchant/billing/gateways/securion_pay.rb +305 -0
- data/lib/active_merchant/billing/gateways/shift4.rb +345 -0
- data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +450 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +274 -0
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +354 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +866 -0
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +602 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +151 -0
- data/lib/active_merchant/billing/gateways/telr.rb +273 -0
- data/lib/active_merchant/billing/gateways/tns.rb +23 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +240 -0
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +612 -0
- data/lib/active_merchant/billing/gateways/transact_pro.rb +222 -0
- data/lib/active_merchant/billing/gateways/transax.rb +21 -0
- data/lib/active_merchant/billing/gateways/transnational.rb +9 -0
- data/lib/active_merchant/billing/gateways/trexle.rb +221 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +500 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +24 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1612 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +367 -0
- data/lib/active_merchant/billing/gateways/vanco.rb +303 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +224 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +171 -0
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +250 -0
- data/lib/active_merchant/billing/gateways/vpos.rb +223 -0
- data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
- data/lib/active_merchant/billing/gateways/wepay.rb +235 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +430 -0
- data/lib/active_merchant/billing/gateways/wompi.rb +197 -0
- data/lib/active_merchant/billing/gateways/world_net.rb +345 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +1050 -0
- data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +208 -0
- data/lib/active_merchant/billing/gateways/worldpay_us.rb +221 -0
- data/lib/active_merchant/billing/gateways.rb +14 -0
- data/lib/active_merchant/billing/model.rb +30 -0
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +39 -0
- data/lib/active_merchant/billing/payment_token.rb +21 -0
- data/lib/active_merchant/billing/rails.rb +3 -0
- data/lib/active_merchant/billing/response.rb +121 -0
- data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +16 -0
- data/lib/active_merchant/connection.rb +194 -0
- data/lib/active_merchant/country.rb +338 -0
- data/lib/active_merchant/empty.rb +20 -0
- data/lib/active_merchant/errors.rb +38 -0
- data/lib/active_merchant/net_http_ssl_connection.rb +11 -0
- data/lib/active_merchant/network_connection_retries.rb +78 -0
- data/lib/active_merchant/post_data.rb +26 -0
- data/lib/active_merchant/posts_data.rb +92 -0
- data/lib/active_merchant/version.rb +3 -0
- data/lib/active_merchant.rb +63 -0
- data/lib/activemerchant.rb +1 -0
- data/lib/certs/cacert.pem +3214 -0
- data/lib/support/gateway_support.rb +69 -0
- data/lib/support/outbound_hosts.rb +28 -0
- data/lib/support/ssl_verify.rb +88 -0
- data/lib/support/ssl_version.rb +86 -0
- 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
|