class ActiveMerchant::Billing::OrbitalGateway
For more information on Orbital, visit the integration center
Authentication Options¶ ↑
The Orbital Gateway
supports two methods of authenticating incoming requests: Source IP authentication and Connection
Username/Password authentication
In addition, these IP addresses/Connection Usernames must be affiliated with the Merchant IDs for which the client should be submitting transactions.
This does allow Third Party Hosting service organizations presenting on behalf of other merchants to submit transactions. However, each time a new customer is added, the merchant or Third-Party hosting organization needs to ensure that the new Merchant IDs or Chain IDs are affiliated with the hosting companies IPs or Connection
Usernames.
If the merchant expects to have more than one merchant account with the Orbital Gateway
, it should have its IP addresses/Connection Usernames affiliated at the Chain level hierarchy within the Orbital Gateway
. Each time a new merchant ID is added, as long as it is placed within the same Chain, it will simply work. Otherwise, the additional MIDs will need to be affiliated with the merchant IPs or Connection
Usernames respectively. For example, we generally affiliate all Salem accounts [BIN 000001] with their Company Number [formerly called MA #] number so all MIDs or Divisions under that Company will automatically be affiliated.
Constants
- ACCOUNT_TYPE
Bank account types to be used for check processing
- ACTIVE
Status Profile Status Flag This field is used to set the status of a Customer Profile.
- API_VERSION
- APPROVAL_SUCCESS
- APPROVED
- AUTH_AND_CAPTURE
AC - Auth and Capture = ‘AC’
- AUTH_ONLY
Auth Only No Capture
- AUTO_GENERATE
CustomerProfileFromOrderInd
Method to use to Generate the Customer Profile Number When Customer Profile Action Type = Create, defines what the Customer Profile Number will be:
- AVS_SUPPORTED_COUNTRIES
- CREATE
Customer Profile Actions
- CURRENCY_CODES
- CURRENCY_EXPONENTS
- DEFERRED
- DELETE
- ECOMMERCE_TRANSACTION
INDUSTRY TYPES
- FORCE_AUTH_AND_CAPTURE
FR - Force Auth No Capture and no online authorization = ‘FR’ FC - Force Auth and Capture no online authorization = ‘FC’
- FORCE_AUTH_ONLY
F - Force Auth No Capture and no online authorization = ‘F’
- GET_TOKEN
safetech token flags
- INACTIVE
- INTERACTIVE_VOICE_RESPONSE
- MAIL_ORDER_TELEPHONE_ORDER_TRANSACTION
- MANUAL_SUSPEND
- NON_TAXABLE_TRANSACTION
- NO_MAPPING_TO_ORDER_DATA
CustomerProfileOrderOverrideInd Defines if any Order Data can be pre-populated from the Customer Reference Number (CustomerRefNum)
- POST_HEADERS
- RECURRING
- RECURRING_PAYMENT_TRANSACTION
- REFUND
Refund and Capture no online authorization
- RETRIEVE
- SENSITIVE_FIELDS
- SUCCESS
- TAX_INCLUDED
- TAX_NOT_PROVIDED
Tax Inds
- UPDATE
- USE_COMMENTS
- USE_CRN_FOR_COMMENTS
- USE_CRN_FOR_ORDER_ID
- USE_CRN_FOR_ORDER_ID_AND_COMMENTS
- USE_CUSTOMER_REF_NUM
- USE_ORDER_ID
- USE_TOKEN
Public Class Methods
ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/orbital.rb, line 200 def initialize(options = {}) requires!(options, :merchant_id) requires!(options, :login, :password) unless options[:ip_authentication] super @options[:merchant_id] = @options[:merchant_id].to_s @use_secondary_url = false end
Public Instance Methods
Customer Profiles¶ ↑
:customer_ref_num should be set unless you’re happy with Orbital providing one
:customer_profile_order_override_ind can be set to map the CustomerRefNum to OrderID or Comments. Defaults to ‘NO’ - no mapping
'NO' - No mapping to order data 'OI' - Use <CustomerRefNum> for <OrderID> 'OD' - Use <CustomerRefNum> for <Comments> 'OA' - Use <CustomerRefNum> for <OrderID> and <Comments>
:order_default_description can be set optionally. 64 char max.
:order_default_amount can be set optionally. integer as cents.
:status defaults to Active
'A' - Active 'I' - Inactive 'MS' - Manual Suspend
# File lib/active_merchant/billing/gateways/orbital.rb, line 306 def add_customer_profile(credit_card, options = {}) options[:customer_profile_action] = CREATE order = build_customer_request_xml(credit_card, options) commit(order, :add_customer_profile) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 280 def allow_zero_auth?(credit_card) # Discover does not support a $0.00 authorization instead use $1.00 %w(visa master american_express diners_club jcb).include?(credit_card.brand) end
MFC - Mark For Capture
# File lib/active_merchant/billing/gateways/orbital.rb, line 237 def capture(money, authorization, options = {}) commit(build_mark_for_capture_xml(money, authorization, options), :capture, options[:retry_logic], options[:trace_number]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 252 def credit(money, payment_method, options = {}) order = build_new_order_xml(REFUND, money, payment_method, options) do |xml| add_payment_source(xml, payment_method, options) end commit(order, :refund, options[:retry_logic], options[:trace_number]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 276 def default_verify_amount(credit_card) allow_zero_auth?(credit_card) ? 0 : 100 end
# File lib/active_merchant/billing/gateways/orbital.rb, line 324 def delete_customer_profile(customer_ref_num) options = { customer_profile_action: DELETE, customer_ref_num: customer_ref_num } order = build_customer_request_xml(nil, options) commit(order, :delete_customer_profile) end
AC – Authorization and Capture
# File lib/active_merchant/billing/gateways/orbital.rb, line 229 def purchase(money, payment_source, options = {}) action = options[:force_capture] ? FORCE_AUTH_AND_CAPTURE : AUTH_AND_CAPTURE order = build_new_auth_purchase_order(action, money, payment_source, options) commit(order, :purchase, options[:retry_logic], options[:trace_number]) end
R – Refund request
# File lib/active_merchant/billing/gateways/orbital.rb, line 242 def refund(money, authorization, options = {}) payment_method = options[:payment_method] order = build_new_order_xml(REFUND, money, payment_method, options.merge(authorization: authorization)) do |xml| add_payment_source(xml, payment_method, options) xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn] end commit(order, :refund, options[:retry_logic], options[:trace_number]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 318 def retrieve_customer_profile(customer_ref_num) options = { customer_profile_action: RETRIEVE, customer_ref_num: customer_ref_num } order = build_customer_request_xml(nil, options) commit(order, :retrieve_customer_profile) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 338 def scrub(transcript) transcript. gsub(%r((<OrbitalConnectionUsername>).+(</OrbitalConnectionUsername>)), '\1[FILTERED]\2'). gsub(%r((<OrbitalConnectionPassword>).+(</OrbitalConnectionPassword>)), '\1[FILTERED]\2'). gsub(%r((<AccountNum>).+(</AccountNum>)), '\1[FILTERED]\2'). # the response sometimes contains a new line that cuts off the end of the closing tag gsub(%r((<CCAccountNum>).+(</CC)), '\1[FILTERED]\2'). gsub(%r((<CardSecVal>).+(</CardSecVal>)), '\1[FILTERED]\2'). gsub(%r((<MerchantID>).+(</MerchantID>)), '\1[FILTERED]\2'). gsub(%r((<CustomerMerchantID>).+(</CustomerMerchantID>)), '\1[FILTERED]\2'). gsub(%r((<CustomerProfileMessage>).+(</CustomerProfileMessage>)), '\1[FILTERED]\2'). gsub(%r((<CheckDDA>).+(</CheckDDA>)), '\1[FILTERED]\2'). gsub(%r((<BCRtNum>).+(</BCRtNum>)), '\1[FILTERED]\2'). gsub(%r((<DigitalTokenCryptogram>).+(</DigitalTokenCryptogram>)), '\1[FILTERED]\2') end
Orbital save a payment method if the TokenTxnType is ‘GT’, that’s why we use this as the default value for store
# File lib/active_merchant/billing/gateways/orbital.rb, line 261 def store(creditcard, options = {}) authorize(0, creditcard, options.merge({ token_txn_type: GET_TOKEN })) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 330 def supports_network_tokenization? true end
# File lib/active_merchant/billing/gateways/orbital.rb, line 334 def supports_scrubbing? true end
# File lib/active_merchant/billing/gateways/orbital.rb, line 312 def update_customer_profile(credit_card, options = {}) options[:customer_profile_action] = UPDATE order = build_customer_request_xml(credit_card, options) commit(order, :update_customer_profile) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 220 def verify(credit_card, options = {}) amount = options[:verify_amount] ? options[:verify_amount].to_i : default_verify_amount(credit_card) MultiResponse.run(:use_first_response) do |r| r.process { authorize(amount, credit_card, options) } r.process(:ignore_result) { void(r.authorization) } unless amount == 0 end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 265 def void(authorization, options = {}, deprecated = {}) if !options.kind_of?(Hash) ActiveMerchant.deprecated('Calling the void method with an amount parameter is deprecated and will be removed in a future version.') return void(options, deprecated.merge(amount: authorization)) end order = build_void_request_xml(authorization, options) commit(order, :void, options[:retry_logic], options[:trace_number]) end
Private Instance Methods
# File lib/active_merchant/billing/gateways/orbital.rb, line 694 def add_aav(xml, credit_card, three_d_secure) return unless three_d_secure && credit_card.brand == 'master' xml.tag!(:AAV, three_d_secure[:cavv]) end
ADDRESS FIELDS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 530 def add_address(xml, payment_source, options) return unless (address = get_address(options)) if avs_supported?(address[:country]) || empty?(address[:country]) xml.tag! :AVSzip, byte_limit(format_address_field(address[:zip]), 10) xml.tag! :AVSaddress1, byte_limit(format_address_field(address[:address1]), 30) xml.tag! :AVSaddress2, byte_limit(format_address_field(address[:address2]), 30) xml.tag! :AVScity, byte_limit(format_address_field(address[:city]), 20) xml.tag! :AVSstate, byte_limit(format_address_field(address[:state]), 2) xml.tag! :AVSphoneNum, (address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil) end xml.tag! :AVSname, billing_name(payment_source, options) xml.tag! :AVScountryCode, byte_limit(format_address_field(filter_unsupported_countries(address[:country])), 2) # Needs to come after AVScountryCode add_destination_address(xml, address) if avs_supported?(address[:country]) || empty?(address[:country]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 700 def add_aevv(xml, credit_card, three_d_secure) return unless three_d_secure && credit_card.brand == 'american_express' xml.tag!(:AEVV, three_d_secure[:cavv]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 651 def add_bank_account_type(xml, check) bank_account_type = if check.account_holder_type == 'business' 'X' else ACCOUNT_TYPE[check.account_type] end xml.tag! :BankAccountType, bank_account_type if bank_account_type end
# File lib/active_merchant/billing/gateways/orbital.rb, line 914 def add_bin_merchant_and_terminal(xml, parameters) xml.tag! :BIN, bin xml.tag! :MerchantID, @options[:merchant_id] xml.tag! :TerminalID, parameters[:terminal_id] || '001' end
# File lib/active_merchant/billing/gateways/orbital.rb, line 513 def add_card_commodity_code(xml, options = {}) if (level2 = options[:level_2_data]) && (level2[:commodity_code]) xml.tag! :PCardCommodityCode, byte_limit(level2[:commodity_code], 4) end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 662 def add_card_indicators(xml, options) xml.tag! :CardIndicators, options[:card_indicators] if options[:card_indicators] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 623 def add_credit_card(xml, credit_card, options) xml.tag! :AccountNum, credit_card.number if credit_card.is_a?(CreditCard) xml.tag! :Exp, expiry_date(credit_card) if credit_card.is_a?(CreditCard) add_currency_fields(xml, options[:currency]) add_verification_value(xml, credit_card) if credit_card.is_a?(CreditCard) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 646 def add_currency_fields(xml, currency) xml.tag! :CurrencyCode, currency_code(currency) xml.tag! :CurrencyExponent, currency_exponents(currency) end
For Profile requests
# File lib/active_merchant/billing/gateways/orbital.rb, line 563 def add_customer_address(xml, options) return unless (address = get_address(options)) xml.tag! :CustomerAddress1, byte_limit(format_address_field(address[:address1]), 30) xml.tag! :CustomerAddress2, byte_limit(format_address_field(address[:address2]), 30) xml.tag! :CustomerCity, byte_limit(format_address_field(address[:city]), 20) xml.tag! :CustomerState, byte_limit(format_address_field(address[:state]), 2) xml.tag! :CustomerZIP, byte_limit(format_address_field(address[:zip]), 10) xml.tag! :CustomerEmail, byte_limit(address[:email], 50) if address[:email] xml.tag! :CustomerPhone, (address[:phone] ? address[:phone].scan(/\d/).join.to_s : nil) xml.tag! :CustomerCountryCode, filter_unsupported_countries(address[:country]) end
REFERENCE FIELDS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 365 def add_customer_data(xml, credit_card, options) add_customer_ref_num(xml, options) return if options[:profile_txn] xml.tag! :CustomerProfileFromOrderInd, profile_number(options) if add_profile_number?(options, credit_card) xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA end
# File lib/active_merchant/billing/gateways/orbital.rb, line 382 def add_customer_ref_num(xml, options) xml.tag! :CustomerRefNum, options[:customer_ref_num] if options[:customer_ref_num] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 549 def add_destination_address(xml, address) return unless address[:dest_zip] xml.tag! :AVSDestzip, byte_limit(format_address_field(address[:dest_zip]), 10) xml.tag! :AVSDestaddress1, byte_limit(format_address_field(address[:dest_address1]), 30) xml.tag! :AVSDestaddress2, byte_limit(format_address_field(address[:dest_address2]), 30) xml.tag! :AVSDestcity, byte_limit(format_address_field(address[:dest_city]), 20) xml.tag! :AVSDeststate, byte_limit(format_address_field(address[:dest_state]), 2) xml.tag! :AVSDestphoneNum, (address[:dest_phone] ? address[:dest_phone].scan(/\d/).join.to_s[0..13] : nil) xml.tag! :AVSDestname, byte_limit(address[:dest_name], 30) xml.tag! :AVSDestcountryCode, filter_unsupported_countries(address[:dest_country]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 822 def add_digital_token_cryptogram(xml, credit_card, three_d_secure) return unless credit_card.is_a?(NetworkTokenizationCreditCard) || three_d_secure && credit_card.brand == 'discover' cryptogram = if three_d_secure && credit_card.brand == 'discover' three_d_secure[:cavv] else credit_card.payment_cryptogram end xml.tag!(:DigitalTokenCryptogram, cryptogram) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 816 def add_dpanind(xml, credit_card, industry_type = nil) return unless credit_card.is_a?(NetworkTokenizationCreditCard) xml.tag! :DPANInd, 'Y' unless industry_type == 'RC' end
# File lib/active_merchant/billing/gateways/orbital.rb, line 610 def add_echeck(xml, check, options = {}) return unless check xml.tag! :CardBrand, 'EC' add_currency_fields(xml, options[:currency]) xml.tag! :BCRtNum, check.routing_number xml.tag! :CheckDDA, check.account_number if check.account_number add_bank_account_type(xml, check) xml.tag! :ECPAuthMethod, options[:auth_method] if options[:auth_method] xml.tag! :BankPmtDelv, options[:payment_delivery] || 'B' xml.tag! :AVSname, (check&.name ? check.name[0..29] : nil) if get_address(options).blank? end
NETWORK TOKENIZATION FIELDS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 806 def add_eci(xml, credit_card, three_d_secure) eci = if three_d_secure three_d_secure[:eci] elsif credit_card.is_a?(NetworkTokenizationCreditCard) credit_card.eci end xml.tag!(:AuthenticationECIInd, eci) if eci end
Adds ECP conditional attributes depending on other attribute values
# File lib/active_merchant/billing/gateways/orbital.rb, line 892 def add_ecp_details(xml, payment_source, parameters = {}) requires!(payment_source.account_number) if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P') xml.tag! :ECPActionCode, parameters[:action_code] if parameters[:action_code] xml.tag! :ECPCheckSerialNumber, payment_source.account_number if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P') if parameters[:auth_method]&.eql?('P') xml.tag! :ECPTerminalCity, parameters[:terminal_city] if parameters[:terminal_city] xml.tag! :ECPTerminalState, parameters[:terminal_state] if parameters[:terminal_state] xml.tag! :ECPImageReferenceNumber, parameters[:image_reference_number] if parameters[:image_reference_number] end if parameters[:action_code]&.eql?('W3') || parameters[:action_code]&.eql?('W5') || parameters[:action_code]&.eql?('W7') || parameters[:action_code]&.eql?('W9') add_ews_details(xml, payment_source, parameters) end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 871 def add_ews_details(xml, payment_source, parameters = {}) split_name = payment_source.first_name.split if payment_source.first_name xml.tag! :EWSFirstName, split_name[0] xml.tag! :EWSMiddleName, split_name[1..-1].join(' ') xml.tag! :EWSLastName, payment_source.last_name xml.tag! :EWSBusinessName, parameters[:company] if payment_source.first_name.empty? && payment_source.last_name.empty? if (address = (parameters[:billing_address] || parameters[:address])) xml.tag! :EWSAddressLine1, byte_limit(format_address_field(address[:address1]), 30) xml.tag! :EWSAddressLine2, byte_limit(format_address_field(address[:address2]), 30) xml.tag! :EWSCity, byte_limit(format_address_field(address[:city]), 20) xml.tag! :EWSState, byte_limit(format_address_field(address[:state]), 2) xml.tag! :EWSZip, byte_limit(format_address_field(address[:zip]), 10) end xml.tag! :EWSPhoneType, parameters[:phone_type] xml.tag! :EWSPhoneNumber, parameters[:phone_number] xml.tag! :EWSCheckSerialNumber, payment_source.account_number unless parameters[:auth_method].eql?('I') end
# File lib/active_merchant/billing/gateways/orbital.rb, line 449 def add_level2_advice_addendum(xml, options = {}) if (level2 = options[:level_2_data]) xml.tag! :AMEXTranAdvAddn1, byte_limit(level2[:advice_addendum_1], 40) if level2[:advice_addendum_1] xml.tag! :AMEXTranAdvAddn2, byte_limit(level2[:advice_addendum_2], 40) if level2[:advice_addendum_2] xml.tag! :AMEXTranAdvAddn3, byte_limit(level2[:advice_addendum_3], 40) if level2[:advice_addendum_3] xml.tag! :AMEXTranAdvAddn4, byte_limit(level2[:advice_addendum_4], 40) if level2[:advice_addendum_4] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 499 def add_level2_card_and_more_tax(xml, options = {}) if (level2 = options[:level_2_data]) xml.tag! :PCardRequestorName, byte_limit(level2[:requestor_name], 38) if level2[:requestor_name] xml.tag! :PCardLocalTaxRate, byte_limit(level2[:local_tax_rate], 5) if level2[:local_tax_rate] # Canadian Merchants Only xml.tag! :PCardNationalTax, byte_limit(level2[:national_tax], 12) if level2[:national_tax] xml.tag! :PCardPstTaxRegNumber, byte_limit(level2[:pst_tax_reg_number], 15) if level2[:pst_tax_reg_number] xml.tag! :PCardCustomerVatRegNumber, byte_limit(level2[:customer_vat_reg_number], 13) if level2[:customer_vat_reg_number] # Canadian Merchants Only xml.tag! :PCardMerchantVatRegNumber, byte_limit(level2[:merchant_vat_reg_number], 20) if level2[:merchant_vat_reg_number] xml.tag! :PCardTotalTaxAmount, byte_limit(level2[:total_tax_amount], 12) if level2[:total_tax_amount] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 458 def add_level2_purchase(xml, options = {}) if (level2 = options[:level_2_data]) xml.tag! :PCOrderNum, byte_limit(level2[:purchase_order], 17) if level2[:purchase_order] xml.tag! :PCDestZip, byte_limit(format_address_field(level2[:zip]), 10) if level2[:zip] xml.tag! :PCDestName, byte_limit(format_address_field(level2[:name]), 30) if level2[:name] xml.tag! :PCDestAddress1, byte_limit(format_address_field(level2[:address1]), 30) if level2[:address1] xml.tag! :PCDestAddress2, byte_limit(format_address_field(level2[:address2]), 30) if level2[:address2] xml.tag! :PCDestCity, byte_limit(format_address_field(level2[:city]), 20) if level2[:city] xml.tag! :PCDestState, byte_limit(format_address_field(level2[:state]), 2) if level2[:state] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 433 def add_level2_tax(xml, options = {}) if (level2 = options[:level_2_data]) xml.tag! :TaxInd, level2[:tax_indicator] if [TAX_NOT_PROVIDED, TAX_INCLUDED, NON_TAXABLE_TRANSACTION].include?(level2[:tax_indicator].to_i) xml.tag! :Tax, level2[:tax].to_i if level2[:tax] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 470 def add_level3_purchase(xml, options = {}) if (level3 = options[:level_3_data]) xml.tag! :PC3FreightAmt, byte_limit(level3[:freight_amount], 12) if level3[:freight_amount] xml.tag! :PC3DutyAmt, byte_limit(level3[:duty_amount], 12) if level3[:duty_amount] xml.tag! :PC3DestCountryCd, byte_limit(level3[:dest_country], 3) if level3[:dest_country] xml.tag! :PC3ShipFromZip, byte_limit(level3[:ship_from_zip], 10) if level3[:ship_from_zip] xml.tag! :PC3DiscAmt, byte_limit(level3[:discount_amount], 12) if level3[:discount_amount] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 440 def add_level3_tax(xml, options = {}) if (level3 = options[:level_3_data]) xml.tag! :PC3VATtaxAmt, byte_limit(level3[:vat_tax], 12) if level3[:vat_tax] xml.tag! :PC3VATtaxRate, byte_limit(level3[:vat_rate], 4) if level3[:vat_rate] xml.tag! :PC3AltTaxInd, byte_limit(level3[:alt_ind], 15) if level3[:alt_ind] xml.tag! :PC3AltTaxAmt, byte_limit(level3[:alt_tax], 9) if level3[:alt_tax] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 519 def add_level3_vat_fields(xml, options = {}) if (level3 = options[:level_3_data]) xml.tag! :PC3InvoiceDiscTreatment, byte_limit(level3[:invoice_discount_treatment], 1) if level3[:invoice_discount_treatment] xml.tag! :PC3TaxTreatment, byte_limit(level3[:tax_treatment], 1) if level3[:tax_treatment] xml.tag! :PC3UniqueVATInvoiceRefNum, byte_limit(level3[:unique_vat_invoice_ref], 15) if level3[:unique_vat_invoice_ref] xml.tag! :PC3ShipVATRate, byte_limit(level3[:ship_vat_rate], 4) if level3[:ship_vat_rate] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 480 def add_line_items(xml, options = {}) xml.tag! :PC3LineItemCount, byte_limit(options[:line_items].count, 2) xml.tag! :PC3LineItemArray do options[:line_items].each_with_index do |line_item, index| xml.tag! :PC3LineItem do xml.tag! :PC3DtlIndex, byte_limit(index + 1, 2) line_item.each do |key, value| if [:line_tot, 'line_tot'].include? key formatted_key = :PC3Dtllinetot else formatted_key = "PC3Dtl#{key.to_s.camelize}".to_sym end xml.tag! formatted_key, value end end end end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 847 def add_managed_billing(xml, options) return unless mb = options[:managed_billing] ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE # default to recurring (R). Other option is deferred (D). xml.tag! :MBType, mb[:type] || RECURRING # default to Customer Reference Number xml.tag! :MBOrderIdGenerationMethod, mb[:order_id_generation_method] || 'IO' # By default use MBRecurringEndDate, set to N. # MMDDYYYY xml.tag! :MBRecurringStartDate, mb[:start_date].scan(/\d/).join.to_s if mb[:start_date] # MMDDYYYY xml.tag! :MBRecurringEndDate, mb[:end_date].scan(/\d/).join.to_s if mb[:end_date] # By default listen to any value set in MBRecurringEndDate. xml.tag! :MBRecurringNoEndDateFlag, mb[:no_end_date_flag] || 'N' # 'Y' || 'N' (Yes or No). xml.tag! :MBRecurringMaxBillings, mb[:max_billings] if mb[:max_billings] xml.tag! :MBRecurringFrequency, mb[:frequency] if mb[:frequency] xml.tag! :MBDeferredBillDate, mb[:deferred_bill_date] if mb[:deferred_bill_date] xml.tag! :MBMicroPaymentMaxDollarValue, mb[:max_dollar_value] if mb[:max_dollar_value] xml.tag! :MBMicroPaymentMaxBillingDays, mb[:max_billing_days] if mb[:max_billing_days] xml.tag! :MBMicroPaymentMaxTransactions, mb[:max_transactions] if mb[:max_transactions] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 722 def add_mastercard_fields(xml, credit_card, parameters, three_d_secure) add_mc_sca_merchant_initiated(xml, credit_card, parameters, three_d_secure) add_mc_sca_recurring(xml, credit_card, parameters, three_d_secure) add_mc_program_protocol(xml, credit_card, three_d_secure) add_mc_directory_trans_id(xml, credit_card, three_d_secure) add_mc_ucafind(xml, credit_card, three_d_secure, parameters) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 750 def add_mc_directory_trans_id(xml, credit_card, three_d_secure) return unless three_d_secure xml.tag!(:MCDirectoryTransID, three_d_secure[:ds_transaction_id]) if three_d_secure[:ds_transaction_id] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 744 def add_mc_program_protocol(xml, credit_card, three_d_secure) return unless version = three_d_secure.try(:[], :version) xml.tag!(:MCProgramProtocol, version.to_s[0]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 730 def add_mc_sca_merchant_initiated(xml, credit_card, parameters, three_d_secure) return unless parameters.try(:[], :sca_merchant_initiated) return unless three_d_secure.try(:[], :eci) == '7' xml.tag!(:SCAMerchantInitiatedTransaction, parameters[:sca_merchant_initiated]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 737 def add_mc_sca_recurring(xml, credit_card, parameters, three_d_secure) return unless parameters.try(:[], :sca_recurring) return unless three_d_secure.try(:[], :eci) == '7' xml.tag!(:SCARecurringPayment, parameters[:sca_recurring]) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 756 def add_mc_ucafind(xml, credit_card, three_d_secure, options) return unless three_d_secure if options[:alternate_ucaf_flow] return unless %w(4 6 7).include?(three_d_secure[:eci]) xml.tag! :UCAFInd, options[:ucaf_collection_indicator] if options[:ucaf_collection_indicator] else xml.tag! :UCAFInd, options[:ucaf_collection_indicator] || '4' end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 409 def add_payment_action_ind(xml, payment_action_ind) return unless payment_action_ind xml.tag! :PaymentActionInd, payment_action_ind end
Payment can be done through either Credit Card or Electronic Check
# File lib/active_merchant/billing/gateways/orbital.rb, line 605 def add_payment_source(xml, payment_source, options = {}) add_safetech_token_data(xml, payment_source, options) if payment_source.is_a?(String) payment_source.is_a?(Check) ? add_echeck(xml, payment_source, options) : add_credit_card(xml, payment_source, options) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 374 def add_profile_number?(options, credit_card) return true unless options[:customer_ref_num] && credit_card.nil? end
# File lib/active_merchant/billing/gateways/orbital.rb, line 712 def add_pymt_brand_program_code(xml, credit_card, three_d_secure) return unless three_d_secure && credit_card.brand == 'american_express' xml.tag!(:PymtBrandProgramCode, 'ASK') end
# File lib/active_merchant/billing/gateways/orbital.rb, line 596 def add_safetech_token_data(xml, payment_source, options) payment_source_token = split_authorization(payment_source).values_at(2).first xml.tag! :CardBrand, options[:card_brand] xml.tag! :AccountNum, payment_source_token end
DESCRIPTOR FIELDS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 402 def add_soft_descriptors(xml, descriptors) return unless descriptors add_soft_descriptors_from_specialized_class(xml, descriptors) if descriptors.is_a?(OrbitalSoftDescriptors) add_soft_descriptors_from_hash(xml, descriptors) if descriptors.is_a?(Hash) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 424 def add_soft_descriptors_from_hash(xml, soft_desc) xml.tag! :SDMerchantName, soft_desc[:merchant_name] || nil xml.tag! :SDProductDescription, soft_desc[:product_description] || nil xml.tag! :SDMerchantCity, soft_desc[:merchant_city] || nil xml.tag! :SDMerchantPhone, soft_desc[:merchant_phone] || nil xml.tag! :SDMerchantURL, soft_desc[:merchant_url] || nil xml.tag! :SDMerchantEmail, soft_desc[:merchant_email] || nil end
# File lib/active_merchant/billing/gateways/orbital.rb, line 415 def add_soft_descriptors_from_specialized_class(xml, soft_desc) xml.tag! :SDMerchantName, soft_desc.merchant_name if soft_desc.merchant_name xml.tag! :SDProductDescription, soft_desc.product_description if soft_desc.product_description xml.tag! :SDMerchantCity, soft_desc.merchant_city if soft_desc.merchant_city xml.tag! :SDMerchantPhone, soft_desc.merchant_phone if soft_desc.merchant_phone xml.tag! :SDMerchantURL, soft_desc.merchant_url if soft_desc.merchant_url xml.tag! :SDMerchantEmail, soft_desc.merchant_email if soft_desc.merchant_email end
SCA (STORED CREDENTIAL) FIELDS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 770 def add_stored_credentials(xml, parameters) return unless parameters[:mit_stored_credential_ind] == 'Y' || parameters[:stored_credential] && !parameters[:stored_credential].values.all?(&:nil?) if msg_type = get_msg_type(parameters) xml.tag! :MITMsgType, msg_type end xml.tag! :MITStoredCredentialInd, 'Y' if parameters[:mit_submitted_transaction_id] xml.tag! :MITSubmittedTransactionID, parameters[:mit_submitted_transaction_id] elsif parameters.dig(:stored_credential, :network_transaction_id) && parameters.dig(:stored_credential, :initiator) == 'merchant' xml.tag! :MITSubmittedTransactionID, parameters[:stored_credential][:network_transaction_id] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 386 def add_tx_ref_num(xml, authorization) return unless authorization xml.tag! :TxRefNum, split_authorization(authorization).first end
# File lib/active_merchant/billing/gateways/orbital.rb, line 630 def add_verification_value(xml, credit_card) return unless credit_card&.verification_value? # If you are trying to collect a Card Verification Number # (CardSecVal) for a Visa or Discover transaction, pass one of these values: # 1 Value is Present # 2 Value on card but illegible # 9 Cardholder states data not available # If the transaction is not a Visa or Discover transaction: # Null-fill this attribute OR # Do not submit the attribute at all. # - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf xml.tag! :CardSecValInd, '1' if %w(visa discover diners_club).include?(credit_card.brand) xml.tag! :CardSecVal, credit_card.verification_value end
# File lib/active_merchant/billing/gateways/orbital.rb, line 706 def add_xid(xml, credit_card, three_d_secure) return unless three_d_secure && credit_card.brand == 'visa' xml.tag!(:XID, three_d_secure[:xid]) if three_d_secure[:xid] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 907 def add_xml_credentials(xml) unless ip_authentication? xml.tag! :OrbitalConnectionUsername, @options[:login] xml.tag! :OrbitalConnectionPassword, @options[:password] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 584 def avs_supported?(address) AVS_SUPPORTED_COUNTRIES.include?(address.to_s) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 576 def billing_name(payment_source, options) if !payment_source.is_a?(String) && payment_source&.name.present? payment_source.name[0..29] elsif options[:billing_address] && options[:billing_address][:name].present? options[:billing_address][:name][0..29] end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 678 def bin @options[:bin] || (salem_mid? ? '000001' : '000002') end
# File lib/active_merchant/billing/gateways/orbital.rb, line 1161 def build_customer_request_xml(credit_card, options = {}) 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.' xml = xml_envelope xml.tag! :Request do xml.tag! :Profile do xml.tag! :OrbitalConnectionUsername, @options[:login] unless ip_authentication? xml.tag! :OrbitalConnectionPassword, @options[:password] unless ip_authentication? xml.tag! :CustomerBin, bin xml.tag! :CustomerMerchantID, @options[:merchant_id] xml.tag! :CustomerName, credit_card.name if credit_card xml.tag! :CustomerRefNum, options[:customer_ref_num] if options[:customer_ref_num] add_customer_address(xml, options) xml.tag! :CustomerProfileAction, options[:customer_profile_action] # C, R, U, D # NO No mapping to order data # OI Use <CustomerRefNum> for <OrderID> # OD Use <CustomerReferNum> for <Comments> # OA Use <CustomerRefNum> for <OrderID> and <Comments> xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA if options[:customer_profile_action] == CREATE # A Auto-Generate the CustomerRefNum # S Use CustomerRefNum field # O Use OrderID field # D Use Comments field xml.tag! :CustomerProfileFromOrderInd, (options[:customer_ref_num] ? USE_CUSTOMER_REF_NUM : AUTO_GENERATE) end xml.tag! :OrderDefaultDescription, options[:order_default_description][0..63] if options[:order_default_description] xml.tag! :OrderDefaultAmount, options[:order_default_amount] if options[:order_default_amount] if [CREATE, UPDATE].include? options[:customer_profile_action] xml.tag! :CustomerAccountType, 'CC' # Only credit card supported xml.tag! :Status, options[:status] || ACTIVE # Active end xml.tag! :CCAccountNum, credit_card.number if credit_card xml.tag! :CCExpireDate, credit_card.expiry_date.expiration.strftime('%m%y') if credit_card # This has to come after CCExpireDate. add_managed_billing(xml, options) end end xml.target! end
# File lib/active_merchant/billing/gateways/orbital.rb, line 1074 def build_mark_for_capture_xml(money, authorization, parameters = {}) tx_ref_num, order_id = split_authorization(authorization) xml = xml_envelope xml.tag! :Request do xml.tag! :MarkForCapture do add_xml_credentials(xml) xml.tag! :OrderID, format_order_id(order_id) xml.tag! :Amount, amount(money) add_level2_tax(xml, parameters) add_bin_merchant_and_terminal(xml, parameters) xml.tag! :TxRefNum, tx_ref_num add_level2_purchase(xml, parameters) add_level2_advice_addendum(xml, parameters) add_level3_purchase(xml, parameters) add_level3_tax(xml, parameters) add_line_items(xml, parameters) if parameters[:line_items] add_level2_card_and_more_tax(xml, parameters) add_card_commodity_code(xml, parameters) add_level3_vat_fields(xml, parameters) end end xml.target! end
BUILDER METHODS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 1008 def build_new_auth_purchase_order(action, money, payment_source, options) build_new_order_xml(action, money, payment_source, options) do |xml| add_payment_source(xml, payment_source, options) add_address(xml, payment_source, options) if @options[:customer_profiles] add_customer_data(xml, payment_source, options) add_managed_billing(xml, options) end end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 1019 def build_new_order_xml(action, money, payment_source, parameters = {}) requires!(parameters, :order_id) @use_secondary_url = parameters[:use_secondary_url] if parameters[:use_secondary_url] xml = xml_envelope xml.tag! :Request do xml.tag! :NewOrder do add_xml_credentials(xml) xml.tag! :IndustryType, parameters[:industry_type] || ECOMMERCE_TRANSACTION xml.tag! :MessageType, action add_bin_merchant_and_terminal(xml, parameters) yield xml if block_given? three_d_secure = parameters[:three_d_secure] add_eci(xml, payment_source, three_d_secure) add_cavv(xml, payment_source, three_d_secure) add_xid(xml, payment_source, three_d_secure) xml.tag! :OrderID, format_order_id(parameters[:order_id]) xml.tag! :Amount, amount(money) xml.tag! :Comments, parameters[:comments] if parameters[:comments] add_level2_tax(xml, parameters) add_level2_advice_addendum(xml, parameters) add_aav(xml, payment_source, three_d_secure) # CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here. add_soft_descriptors(xml, parameters[:soft_descriptors]) set_recurring_ind(xml, parameters) # Append Transaction Reference Number at the end for Refund transactions add_tx_ref_num(xml, parameters[:authorization]) if action == REFUND && payment_source.nil? add_level2_purchase(xml, parameters) add_level3_purchase(xml, parameters) add_level3_tax(xml, parameters) add_line_items(xml, parameters) if parameters[:line_items] add_card_indicators(xml, parameters) add_payment_action_ind(xml, parameters[:payment_action_ind]) add_dpanind(xml, payment_source, parameters[:industry_type]) add_aevv(xml, payment_source, three_d_secure) add_level2_card_and_more_tax(xml, parameters) add_digital_token_cryptogram(xml, payment_source, three_d_secure) xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && payment_source.is_a?(Check) add_ecp_details(xml, payment_source, parameters) if payment_source.is_a?(Check) add_stored_credentials(xml, parameters) add_pymt_brand_program_code(xml, payment_source, three_d_secure) xml.tag! :TokenTxnType, parameters[:token_txn_type] if parameters[:token_txn_type] add_mastercard_fields(xml, payment_source, parameters, three_d_secure) if mastercard?(payment_source) add_card_commodity_code(xml, parameters) add_level3_vat_fields(xml, parameters) end end xml.target! end
# File lib/active_merchant/billing/gateways/orbital.rb, line 1098 def build_void_request_xml(authorization, parameters = {}) tx_ref_num, order_id = split_authorization(authorization) xml = xml_envelope xml.tag! :Request do xml.tag! :Reversal do add_xml_credentials(xml) xml.tag! :TxRefNum, tx_ref_num xml.tag! :TxRefIdx, parameters[:transaction_index] xml.tag! :AdjustedAmt, parameters[:amount] # setting adjusted amount to nil will void entire amount xml.tag! :OrderID, format_order_id(order_id || parameters[:order_id]) add_bin_merchant_and_terminal(xml, parameters) xml.tag! :ReversalRetryNumber, parameters[:reversal_retry_number] if parameters[:reversal_retry_number] xml.tag! :OnlineReversalInd, parameters[:online_reversal_ind] if parameters[:online_reversal_ind] end end xml.target! end
Field lengths should be limited by byte count instead of character count Returns the truncated value or nil
# File lib/active_merchant/billing/gateways/orbital.rb, line 1149 def byte_limit(value, byte_length) limited_value = '' value.to_s.each_char do |c| break if (limited_value.bytesize + c.bytesize) > byte_length limited_value << c end limited_value end
REQUEST/RESPONSE METHODS=====¶ ↑
# File lib/active_merchant/billing/gateways/orbital.rb, line 922 def commit(order, message_type, retry_logic = nil, trace_number = nil) headers = POST_HEADERS.merge('Content-length' => order.size.to_s) if (@options[:retry_logic] || retry_logic) && trace_number headers['Trace-number'] = trace_number.to_s headers['Merchant-Id'] = @options[:merchant_id] end request = ->(url) { parse(ssl_post(url, order, headers)) } # Failover URL will be attempted in the event of a connection error response = begin raise ConnectionError.new 'Should use secondary url', 500 if @use_secondary_url request.call(remote_url) rescue ConnectionError request.call(remote_url(:secondary)) end authorization = authorization_string(response[:tx_ref_num], response[:order_id], response[:safetech_token], response[:card_brand]) Response.new( success?(response, message_type), message_from(response), response, { authorization: authorization, test: self.test?, avs_result: OrbitalGateway::AVSResult.new(response[:avs_resp_code]), cvv_result: OrbitalGateway::CVVResult.new(response[:cvv2_resp_code]) } ) end
# File lib/active_merchant/billing/gateways/orbital.rb, line 666 def currency_code(currency) CURRENCY_CODES[(currency || self.default_currency)].to_s end
# File lib/active_merchant/billing/gateways/orbital.rb, line 670 def currency_exponents(currency) CURRENCY_EXPONENTS[(currency || self.default_currency)].to_s end
# File lib/active_merchant/billing/gateways/orbital.rb, line 674 def expiry_date(credit_card) "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}" end
# File lib/active_merchant/billing/gateways/orbital.rb, line 588 def filter_unsupported_countries(address) avs_supported?(address) ? address.to_s : '' end
# File lib/active_merchant/billing/gateways/orbital.rb, line 356 def force_capture_with_echeck?(payment_source, options) return false unless options[:force_capture] return false unless payment_source.is_a?(Check) %w(W8 W9 ND).include?(options[:action_code]) end
Address-related fields cannot contain % | ^ \ / Returns the value with these characters removed, or nil
# File lib/active_merchant/billing/gateways/orbital.rb, line 1143 def format_address_field(value) value.gsub(/[%\|\^\\\/]/, '') if value.respond_to?(:gsub) end
The valid characters include:
-
all letters and digits
-
, $ @ & and a space character, though the space character cannot be the leading character
-
-
PINless Debit transactions can only use uppercase and lowercase alpha (A-Z, a-z) and numeric (0-9)
# File lib/active_merchant/billing/gateways/orbital.rb, line 1133 def format_order_id(order_id) illegal_characters = /[^,$@&\- \w]/ order_id = order_id.to_s.tr('.', '-') order_id.gsub!(illegal_characters, '') order_id.lstrip! order_id[0...22] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 592 def get_address(options) options[:billing_address] || options[:address] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 784 def get_msg_type(parameters) return parameters[:mit_msg_type] if parameters[:mit_msg_type] return 'CSTO' if parameters[:stored_credential][:initial_transaction] return unless parameters[:stored_credential][:initiator] && parameters[:stored_credential][:reason_type] initiator = case parameters[:stored_credential][:initiator] when 'cardholder', 'customer' then 'C' when 'merchant' then 'M' end reason = case parameters[:stored_credential][:reason_type] when 'recurring' then 'REC' when 'installment' then 'INS' when 'unscheduled' then 'USE' end "#{initiator}#{reason}" end
# File lib/active_merchant/billing/gateways/orbital.rb, line 1002 def ip_authentication? @options[:ip_authentication] == true end
# File lib/active_merchant/billing/gateways/orbital.rb, line 718 def mastercard?(payment_source) payment_source.is_a?(CreditCard) && payment_source.brand == 'master' end
# File lib/active_merchant/billing/gateways/orbital.rb, line 998 def message_from(response) response[:resp_msg] || response[:status_msg] || response[:customer_profile_message] end
# File lib/active_merchant/billing/gateways/orbital.rb, line 963 def parse(body) response = {} xml = REXML::Document.new(strip_invalid_xml_chars(body)) root = REXML::XPath.first(xml, '//Response') || REXML::XPath.first(xml, '//ErrorResponse') if root root.elements.to_a.each do |node| recurring_parse_element(response, node) end end response.delete_if { |k, _| SENSITIVE_FIELDS.include?(k) } end
# File lib/active_merchant/billing/gateways/orbital.rb, line 378 def profile_number(options) options[:customer_ref_num] ? USE_CUSTOMER_REF_NUM : AUTO_GENERATE end
# File lib/active_merchant/billing/gateways/orbital.rb, line 977 def recurring_parse_element(response, node) if node.has_elements? node.elements.each { |e| recurring_parse_element(response, e) } else response[node.name.underscore.to_sym] = node.text end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 955 def remote_url(url = :primary) if url == :primary (self.test? ? self.test_url : self.live_url) else (self.test? ? self.secondary_test_url : self.secondary_live_url) end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 682 def salem_mid? @options[:merchant_id].length == 6 end
For Canadian transactions on PNS Tampa on New Order RF - First Recurring Transaction RS - Subsequent Recurring Transactions
# File lib/active_merchant/billing/gateways/orbital.rb, line 840 def set_recurring_ind(xml, parameters) return unless parameters[:recurring_ind] raise 'RecurringInd must be set to either "RF" or "RS"' unless %w(RF RS).include?(parameters[:recurring_ind]) xml.tag! :RecurringInd, parameters[:recurring_ind] end
Null characters are possible in some responses (namely, the respMsg field), causing XML parsing errors Prevent by substituting these with a valid placeholder string
# File lib/active_merchant/billing/gateways/orbital.rb, line 1124 def strip_invalid_xml_chars(xml) xml.gsub(/\u0000/, '[null]') end
# File lib/active_merchant/billing/gateways/orbital.rb, line 985 def success?(response, message_type) if %i[void].include?(message_type) response[:proc_status] == SUCCESS elsif %i[refund].include?(message_type) response[:proc_status] == SUCCESS && response[:approval_status] == APPROVAL_SUCCESS elsif response[:customer_profile_action] response[:profile_proc_status] == SUCCESS else response[:proc_status] == SUCCESS && APPROVED.include?(response[:resp_code]) end end
# File lib/active_merchant/billing/gateways/orbital.rb, line 1116 def xml_envelope xml = Builder::XmlMarkup.new(indent: 2) xml.instruct!(:xml, version: '1.0', encoding: 'UTF-8') xml end