class ActiveMerchant::Billing::CyberSourceGateway

Initial setup instructions can be found in apps.cybersource.com/library/documentation/dev_guides/SOAP_Toolkits/SOAP_toolkits.pdf

Important Notes

Constants

PRODUCTION_XSD_VERSION
TEST_XSD_VERSION

Schema files can be found here: ics2ws.ic3.com/commerce/1.x/transactionProcessor/

Public Class Methods

new(options = {}) click to toggle source

These are the options that can be used when creating a new CyberSource Gateway object.

:login => your username

:password => the transaction key you generated in the Business Center

:test => true sets the gateway to test mode

:vat_reg_number => your VAT registration number

:nexus => “WI CA QC” sets the states/provinces where you have a physical

presence for tax purposes

:ignore_avs => true don't want to use AVS so continue processing even

if AVS would have failed

:ignore_cvv => true don't want to use CVV so continue processing even

if CVV would have failed
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 112
def initialize(options = {})
  requires!(options, :login, :password)
  super
end

Public Instance Methods

authorize(money, creditcard_or_reference, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 117
def authorize(money, creditcard_or_reference, options = {})
  setup_address_hash(options)
  commit(build_auth_request(money, creditcard_or_reference, options), :authorize, money, options)
end
calculate_tax(creditcard, options) click to toggle source

CyberSource requires that you provide line item information for tax calculations. If you do not have prices for each item or want to simplify the situation then pass in one fake line item that costs the subtotal of the order

The line_item hash goes in the options hash and should look like

:line_items => [
  {
    :declared_value => '1',
    :quantity => '2',
    :code => 'default',
    :description => 'Giant Walrus',
    :sku => 'WA323232323232323'
  },
  {
    :declared_value => '6',
    :quantity => '1',
    :code => 'default',
    :description => 'Marble Snowcone',
    :sku => 'FAKE1232132113123'
  }
]

This functionality is only supported by this particular gateway may be changed at any time

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 207
def calculate_tax(creditcard, options)
  requires!(options,  :line_items)
  setup_address_hash(options)
  commit(build_tax_calculation_request(creditcard, options), :calculate_tax, nil, options)
end
capture(money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 122
def capture(money, authorization, options = {})
  setup_address_hash(options)
  commit(build_capture_request(money, authorization, options), :capture, money, options)
end
credit(money, creditcard_or_reference, options = {}) click to toggle source

Adds credit to a card or subscription (stand alone credit).

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 149
def credit(money, creditcard_or_reference, options = {})
  setup_address_hash(options)
  commit(build_credit_request(money, creditcard_or_reference, options), :credit, money, options)
end
purchase(money, payment_method_or_reference, options = {}) click to toggle source

options => true # attempts to process as pinless debit card

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 128
def purchase(money, payment_method_or_reference, options = {})
  setup_address_hash(options)
  commit(build_purchase_request(money, payment_method_or_reference, options), :purchase, money, options)
end
refund(money, identification, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 137
def refund(money, identification, options = {})
  commit(build_refund_request(money, identification, options), :refund, money, options)
end
retrieve(reference, options = {}) click to toggle source

Retrieves a customer subscription/profile

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 176
def retrieve(reference, options = {})
  requires!(options, :order_id)
  commit(build_retrieve_subscription_request(reference, options), :retrieve, nil, options)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 223
def scrub(transcript)
  transcript.
    gsub(%r((<wsse:Password [^>]*>)[^<]*(</wsse:Password>))i, '\1[FILTERED]\2').
    gsub(%r((<accountNumber>)[^<]*(</accountNumber>))i, '\1[FILTERED]\2').
    gsub(%r((<cvNumber>)[^<]*(</cvNumber>))i, '\1[FILTERED]\2').
    gsub(%r((<cavv>)[^<]*(</cavv>))i, '\1[FILTERED]\2').
    gsub(%r((<xid>)[^<]*(</xid>))i, '\1[FILTERED]\2').
    gsub(%r((<authenticationData>)[^<]*(</authenticationData>))i, '\1[FILTERED]\2')
end
store(payment_method, options = {}) click to toggle source

Stores a customer subscription/profile with type “on-demand”. To charge the card while creating a profile, pass options => money

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 157
def store(payment_method, options = {})
  setup_address_hash(options)
  commit(build_create_subscription_request(payment_method, options), :store, nil, options)
end
supports_network_tokenization?() click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 233
def supports_network_tokenization?
  true
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 219
def supports_scrubbing?
  true
end
unstore(reference, options = {}) click to toggle source

Removes a customer subscription/profile

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 170
def unstore(reference, options = {})
  requires!(options, :order_id)
  commit(build_delete_subscription_request(reference, options), :unstore, nil, options)
end
update(reference, creditcard, options = {}) click to toggle source

Updates a customer subscription/profile

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 163
def update(reference, creditcard, options = {})
  requires!(options, :order_id)
  setup_address_hash(options)
  commit(build_update_subscription_request(reference, creditcard, options), :update, nil, options)
end
validate_pinless_debit_card(creditcard, options = {}) click to toggle source

Determines if a card can be used for Pinless Debit Card transactions

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 214
def validate_pinless_debit_card(creditcard, options = {})
  requires!(options, :order_id)
  commit(build_validate_pinless_debit_request(creditcard, options), :validate_pinless_debit_card, nil, options)
end
verify(payment, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 141
def verify(payment, options = {})
  MultiResponse.run(:use_first_response) do |r|
    r.process { authorize(100, payment, options) }
    r.process(:ignore_result) { void(r.authorization, options) }
  end
end
verify_credentials() click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 237
def verify_credentials
  response = void('0')
  response.params['reasonCode'] == '102'
end
void(identification, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 133
def void(identification, options = {})
  commit(build_void_request(identification, options), :void, nil, options)
end

Private Instance Methods

add_address(xml, payment_method, address, options, shipTo = false) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 455
def add_address(xml, payment_method, address, options, shipTo = false)
  xml.tag! shipTo ? 'shipTo' : 'billTo' do
    xml.tag! 'firstName',             payment_method.first_name             if payment_method
    xml.tag! 'lastName',              payment_method.last_name              if payment_method
    xml.tag! 'street1',               address[:address1]
    xml.tag! 'street2',               address[:address2]                unless address[:address2].blank?
    xml.tag! 'city',                  address[:city]
    xml.tag! 'state',                 address[:state]
    xml.tag! 'postalCode',            address[:zip]
    xml.tag! 'country',               lookup_country_code(address[:country]) unless address[:country].blank?
    xml.tag! 'company',               address[:company]                 unless address[:company].blank?
    xml.tag! 'companyTaxID',          address[:companyTaxID]            unless address[:company_tax_id].blank?
    xml.tag! 'phoneNumber',           address[:phone]                   unless address[:phone].blank?
    xml.tag! 'email',                 options[:email] || 'null@cybersource.com'
    xml.tag! 'ipAddress',             options[:ip]                      unless options[:ip].blank? || shipTo
    xml.tag! 'driversLicenseNumber',  options[:drivers_license_number]  unless options[:drivers_license_number].blank?
    xml.tag! 'driversLicenseState',   options[:drivers_license_state]   unless options[:drivers_license_state].blank?
  end
end
add_auth_network_tokenization(xml, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 557
def add_auth_network_tokenization(xml, payment_method, options)
  return unless network_tokenization?(payment_method)

  case card_brand(payment_method).to_sym
  when :visa
    xml.tag! 'ccAuthService', {'run' => 'true'} do
      xml.tag!('cavv', payment_method.payment_cryptogram)
      xml.tag!('commerceIndicator', 'vbv')
      xml.tag!('xid', payment_method.payment_cryptogram)
    end
  when :master
    xml.tag! 'ucaf' do
      xml.tag!('authenticationData', payment_method.payment_cryptogram)
      xml.tag!('collectionIndicator', '2')
    end
    xml.tag! 'ccAuthService', {'run' => 'true'} do
      xml.tag!('commerceIndicator', 'spa')
    end
  when :american_express
    cryptogram = Base64.decode64(payment_method.payment_cryptogram)
    xml.tag! 'ccAuthService', {'run' => 'true'} do
      xml.tag!('cavv', Base64.encode64(cryptogram[0...20]))
      xml.tag!('commerceIndicator', 'aesk')
      xml.tag!('xid', Base64.encode64(cryptogram[20...40]))
    end
  end
end
add_auth_reversal_service(xml, request_id, request_token) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 614
def add_auth_reversal_service(xml, request_id, request_token)
  xml.tag! 'ccAuthReversalService', {'run' => 'true'} do
    xml.tag! 'authRequestID', request_id
    xml.tag! 'authRequestToken', request_token
  end
end
add_auth_service(xml, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 528
def add_auth_service(xml, payment_method, options)
  if network_tokenization?(payment_method)
    add_auth_network_tokenization(xml, payment_method, options)
  else
    xml.tag! 'ccAuthService', {'run' => 'true'} do
      check_for_stored_cred_commerce_indicator(xml, options)
    end
  end
end
add_business_rules_data(xml, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 410
def add_business_rules_data(xml, payment_method, options)
  prioritized_options = [options, @options]

  unless network_tokenization?(payment_method)
    xml.tag! 'businessRules' do
      xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs)
      xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv)
    end
  end
end
add_capture_service(xml, request_id, request_token) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 591
def add_capture_service(xml, request_id, request_token)
  xml.tag! 'ccCaptureService', {'run' => 'true'} do
    xml.tag! 'authRequestID', request_id
    xml.tag! 'authRequestToken', request_token
  end
end
add_check(xml, check) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 513
def add_check(xml, check)
  xml.tag! 'check' do
    xml.tag! 'accountNumber', check.account_number
    xml.tag! 'accountType', check.account_type[0]
    xml.tag! 'bankTransitNumber', check.routing_number
  end
end
add_check_payment_method(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 676
def add_check_payment_method(xml)
  xml.tag! 'subscription' do
    xml.tag! 'paymentMethod', 'check'
  end
end
add_check_service(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 628
def add_check_service(xml)
  xml.tag! 'ecDebitService', {'run' => 'true'}
end
add_credit_service(xml, request_id = nil, request_token = nil) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 621
def add_credit_service(xml, request_id = nil, request_token = nil)
  xml.tag! 'ccCreditService', {'run' => 'true'} do
    xml.tag! 'captureRequestID', request_id if request_id
    xml.tag! 'captureRequestToken', request_token if request_token
  end
end
add_creditcard(xml, creditcard) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 475
def add_creditcard(xml, creditcard)
  xml.tag! 'card' do
    xml.tag! 'accountNumber', creditcard.number
    xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
    xml.tag! 'expirationYear', format(creditcard.year, :four_digits)
    xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv] || creditcard.verification_value.blank?
    xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym]
  end
end
add_creditcard_payment_method(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 670
def add_creditcard_payment_method(xml)
  xml.tag! 'subscription' do
    xml.tag! 'paymentMethod', 'credit card'
  end
end
add_decision_manager_fields(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 485
def add_decision_manager_fields(xml, options)
  return unless options[:decision_manager_enabled]

  xml.tag! 'decisionManager' do
    xml.tag! 'enabled', options[:decision_manager_enabled] if options[:decision_manager_enabled]
    xml.tag! 'profile', options[:decision_manager_profile] if options[:decision_manager_profile]
  end
end
add_issuer_additional_data(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 494
def add_issuer_additional_data(xml, options)
  return unless options[:issuer_additional_data]

  xml.tag! 'issuer' do
    xml.tag! 'additionalData', options[:issuer_additional_data]
  end
end
add_line_item_data(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 428
def add_line_item_data(xml, options)
  options[:line_items].each_with_index do |value, index|
    xml.tag! 'item', {'id' => index} do
      xml.tag! 'unitPrice', localized_amount(value[:declared_value].to_i, options[:currency] || default_currency)
      xml.tag! 'quantity', value[:quantity]
      xml.tag! 'productCode', value[:code] || 'shipping_only'
      xml.tag! 'productName', value[:description]
      xml.tag! 'productSKU', value[:sku]
    end
  end
end
add_mdd_fields(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 502
def add_mdd_fields(xml, options)
  return unless options.keys.any? { |key| key.to_s.start_with?('mdd_field') }

  xml.tag! 'merchantDefinedData' do
    (1..100).each do |each|
      key = "mdd_field_#{each}".to_sym
      xml.tag!("field#{each}", options[key]) if options[key]
    end
  end
end
add_merchant_data(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 440
def add_merchant_data(xml, options)
  xml.tag! 'merchantID', @options[:login]
  xml.tag! 'merchantReferenceCode', options[:order_id] || generate_unique_id
  xml.tag! 'clientLibrary', 'Ruby Active Merchant'
  xml.tag! 'clientLibraryVersion',  VERSION
  xml.tag! 'clientEnvironment', RUBY_PLATFORM
end
add_payment_method_or_subscription(xml, money, payment_method_or_reference, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 682
def add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
  if payment_method_or_reference.is_a?(String)
    add_purchase_data(xml, money, true, options)
    add_subscription(xml, options, payment_method_or_reference)
  elsif card_brand(payment_method_or_reference) == 'check'
    add_address(xml, payment_method_or_reference, options[:billing_address], options)
    add_purchase_data(xml, money, true, options)
    add_check(xml, payment_method_or_reference)
  else
    add_address(xml, payment_method_or_reference, options[:billing_address], options)
    add_address(xml, payment_method_or_reference, options[:shipping_address], options, true)
    add_purchase_data(xml, money, true, options)
    add_creditcard(xml, payment_method_or_reference)
  end
end
add_payment_network_token(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 585
def add_payment_network_token(xml)
  xml.tag! 'paymentNetworkToken' do
    xml.tag!('transactionType', '1')
  end
end
add_purchase_data(xml, money = 0, include_grand_total = false, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 448
def add_purchase_data(xml, money = 0, include_grand_total = false, options={})
  xml.tag! 'purchaseTotals' do
    xml.tag! 'currency', options[:currency] || currency(money)
    xml.tag!('grandTotalAmount', localized_amount(money.to_i, options[:currency] || default_currency))  if include_grand_total
  end
end
add_purchase_service(xml, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 598
def add_purchase_service(xml, payment_method, options)
  if options[:pinless_debit_card]
    xml.tag! 'pinlessDebitService', {'run' => 'true'}
  else
    add_auth_service(xml, payment_method, options)
    xml.tag! 'ccCaptureService', {'run' => 'true'}
  end
end
add_stored_credential_options(xml, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 716
def add_stored_credential_options(xml, options={})
  return unless options[:stored_credential]
  if options[:stored_credential][:initial_transaction]
    xml.tag! 'subsequentAuthFirst', 'true'
  elsif options[:stored_credential][:reason_type] == 'unscheduled'
    xml.tag! 'subsequentAuth', 'true'
    xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
  else
    xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
  end
end
add_subscription(xml, options, reference = nil) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 648
def add_subscription(xml, options, reference = nil)
  options[:subscription] ||= {}

  xml.tag! 'recurringSubscriptionInfo' do
    if reference
      subscription_id = reference.split(';')[6]
      xml.tag! 'subscriptionID',  subscription_id
    end

    xml.tag! 'status',            options[:subscription][:status]                         if options[:subscription][:status]
    xml.tag! 'amount',            localized_amount(options[:subscription][:amount].to_i, options[:currency] || default_currency) if options[:subscription][:amount]
    xml.tag! 'numberOfPayments',  options[:subscription][:occurrences]                    if options[:subscription][:occurrences]
    xml.tag! 'automaticRenew',    options[:subscription][:automatic_renew]                if options[:subscription][:automatic_renew]
    xml.tag! 'frequency',         options[:subscription][:frequency]                      if options[:subscription][:frequency]
    xml.tag! 'startDate',         options[:subscription][:start_date].strftime('%Y%m%d')  if options[:subscription][:start_date]
    xml.tag! 'endDate',           options[:subscription][:end_date].strftime('%Y%m%d')    if options[:subscription][:end_date]
    xml.tag! 'approvalRequired',  options[:subscription][:approval_required] || false
    xml.tag! 'event',             options[:subscription][:event]                          if options[:subscription][:event]
    xml.tag! 'billPayment',       options[:subscription][:bill_payment]                   if options[:subscription][:bill_payment]
  end
end
add_subscription_create_service(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 632
def add_subscription_create_service(xml, options)
  xml.tag! 'paySubscriptionCreateService', {'run' => 'true'}
end
add_subscription_delete_service(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 640
def add_subscription_delete_service(xml, options)
  xml.tag! 'paySubscriptionDeleteService', {'run' => 'true'}
end
add_subscription_retrieve_service(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 644
def add_subscription_retrieve_service(xml, options)
  xml.tag! 'paySubscriptionRetrieveService', {'run' => 'true'}
end
add_subscription_update_service(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 636
def add_subscription_update_service(xml, options)
  xml.tag! 'paySubscriptionUpdateService', {'run' => 'true'}
end
add_tax_service(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 521
def add_tax_service(xml)
  xml.tag! 'taxService', {'run' => 'true'} do
    xml.tag!('nexus', @options[:nexus]) unless @options[:nexus].blank?
    xml.tag!('sellerRegistration', @options[:vat_reg_number]) unless @options[:vat_reg_number].blank?
  end
end
add_threeds_services(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 702
def add_threeds_services(xml, options)
  xml.tag! 'payerAuthEnrollService', {'run' => 'true'} if options[:payer_auth_enroll_service]
  if options[:payer_auth_validate_service]
    xml.tag! 'payerAuthValidateService', {'run' => 'true'} do
      xml.tag! 'signedPARes', options[:pares]
    end
  end
end
add_validate_pinless_debit_service(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 698
def add_validate_pinless_debit_service(xml)
  xml.tag! 'pinlessDebitValidateService', {'run' => 'true'}
end
add_void_service(xml, request_id, request_token) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 607
def add_void_service(xml, request_id, request_token)
  xml.tag! 'voidService', {'run' => 'true'} do
    xml.tag! 'voidRequestID', request_id
    xml.tag! 'voidRequestToken', request_token
  end
end
authorization_from(response, action, amount, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 822
def authorization_from(response, action, amount, options)
  [options[:order_id], response[:requestID], response[:requestToken], action, amount,
   options[:currency], response[:subscriptionID]].join(';')
end
build_auth_request(money, creditcard_or_reference, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 258
def build_auth_request(money, creditcard_or_reference, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
  add_decision_manager_fields(xml, options)
  add_mdd_fields(xml, options)
  add_auth_service(xml, creditcard_or_reference, options)
  add_threeds_services(xml, options)
  add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
  add_business_rules_data(xml, creditcard_or_reference, options)
  add_stored_credential_options(xml, options)
  add_issuer_additional_data(xml, options)

  xml.target!
end
build_capture_request(money, authorization, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 284
def build_capture_request(money, authorization, options)
  order_id, request_id, request_token = authorization.split(';')
  options[:order_id] = order_id

  xml = Builder::XmlMarkup.new :indent => 2
  add_purchase_data(xml, money, true, options)
  add_capture_service(xml, request_id, request_token)
  add_business_rules_data(xml, authorization, options)
  xml.target!
end
build_create_subscription_request(payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 347
def build_create_subscription_request(payment_method, options)
  default_subscription_params = {:frequency => 'on-demand', :amount => 0, :automatic_renew => false}
  options[:subscription] = default_subscription_params.update(
    options[:subscription] || {}
  )

  xml = Builder::XmlMarkup.new :indent => 2
  add_address(xml, payment_method, options[:billing_address], options)
  add_purchase_data(xml, options[:setup_fee] || 0, true, options)
  if card_brand(payment_method) == 'check'
    add_check(xml, payment_method)
    add_check_payment_method(xml)
  else
    add_creditcard(xml, payment_method)
    add_creditcard_payment_method(xml)
  end
  add_subscription(xml, options)
  if options[:setup_fee]
    if card_brand(payment_method) == 'check'
      add_check_service(xml)
    else
      add_purchase_service(xml, payment_method, options)
      add_payment_network_token(xml) if network_tokenization?(payment_method)
    end
  end
  add_subscription_create_service(xml, options)
  add_business_rules_data(xml, payment_method, options)
  xml.target!
end
build_credit_request(money, creditcard_or_reference, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 338
def build_credit_request(money, creditcard_or_reference, options)
  xml = Builder::XmlMarkup.new :indent => 2

  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
  add_credit_service(xml)

  xml.target!
end
build_delete_subscription_request(reference, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 389
def build_delete_subscription_request(reference, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_subscription(xml, options, reference)
  add_subscription_delete_service(xml, options)
  xml.target!
end
build_purchase_request(money, payment_method_or_reference, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 295
def build_purchase_request(money, payment_method_or_reference, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
  add_decision_manager_fields(xml, options)
  add_mdd_fields(xml, options)
  if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
    add_check_service(xml)
  else
    add_purchase_service(xml, payment_method_or_reference, options)
    add_threeds_services(xml, options)
    add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
    add_business_rules_data(xml, payment_method_or_reference, options) unless options[:pinless_debit_card]
  end
  add_issuer_additional_data(xml, options)

  xml.target!
end
build_refund_request(money, identification, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 327
def build_refund_request(money, identification, options)
  order_id, request_id, request_token = identification.split(';')
  options[:order_id] = order_id

  xml = Builder::XmlMarkup.new :indent => 2
  add_purchase_data(xml, money, true, options)
  add_credit_service(xml, request_id, request_token)

  xml.target!
end
build_request(body, options) click to toggle source

Where we actually build the full SOAP request using builder

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 729
def build_request(body, options)
  xsd_version = test? ? TEST_XSD_VERSION : PRODUCTION_XSD_VERSION

  xml = Builder::XmlMarkup.new :indent => 2
  xml.instruct!
  xml.tag! 's:Envelope', {'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/'} do
    xml.tag! 's:Header' do
      xml.tag! 'wsse:Security', {'s:mustUnderstand' => '1', 'xmlns:wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'} do
        xml.tag! 'wsse:UsernameToken' do
          xml.tag! 'wsse:Username', @options[:login]
          xml.tag! 'wsse:Password', @options[:password], 'Type' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'
        end
      end
    end
    xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
      xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}"} do
        add_merchant_data(xml, options)
        xml << body
      end
    end
  end
  xml.target!
end
build_retrieve_subscription_request(reference, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 396
def build_retrieve_subscription_request(reference, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_subscription(xml, options, reference)
  add_subscription_retrieve_service(xml, options)
  xml.target!
end
build_tax_calculation_request(creditcard, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 273
def build_tax_calculation_request(creditcard, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_address(xml, creditcard, options[:billing_address], options, false)
  add_address(xml, creditcard, options[:shipping_address], options, true)
  add_line_item_data(xml, options)
  add_purchase_data(xml, 0, false, options)
  add_tax_service(xml)
  add_business_rules_data(xml, creditcard, options)
  xml.target!
end
build_update_subscription_request(reference, creditcard, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 377
def build_update_subscription_request(reference, creditcard, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_address(xml, creditcard, options[:billing_address], options) unless options[:billing_address].blank?
  add_purchase_data(xml, options[:setup_fee], true, options) unless options[:setup_fee].blank?
  add_creditcard(xml, creditcard)    if creditcard
  add_creditcard_payment_method(xml) if creditcard
  add_subscription(xml, options, reference)
  add_subscription_update_service(xml, options)
  add_business_rules_data(xml, creditcard, options)
  xml.target!
end
build_validate_pinless_debit_request(creditcard, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 403
def build_validate_pinless_debit_request(creditcard, options)
  xml = Builder::XmlMarkup.new :indent => 2
  add_creditcard(xml, creditcard)
  add_validate_pinless_debit_service(xml)
  xml.target!
end
build_void_request(identification, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 313
def build_void_request(identification, options)
  order_id, request_id, request_token, action, money, currency  = identification.split(';')
  options[:order_id] = order_id

  xml = Builder::XmlMarkup.new :indent => 2
  if action == 'capture'
    add_void_service(xml, request_id, request_token)
  else
    add_purchase_data(xml, money, true, options.merge(:currency => currency || default_currency))
    add_auth_reversal_service(xml, request_id, request_token)
  end
  xml.target!
end
check_for_stored_cred_commerce_indicator(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 538
def check_for_stored_cred_commerce_indicator(xml, options)
  return unless options[:stored_credential]
  if commerce_indicator(options)
    xml.tag!('commerceIndicator', commerce_indicator(options))
  end
end
commerce_indicator(options) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 545
def commerce_indicator(options)
  return if options[:stored_credential][:initial_transaction]
  case options[:stored_credential][:reason_type]
  when 'installment' then 'install'
  when 'recurring' then 'recurring'
  end
end
commit(request, action, amount, options) click to toggle source

Contact CyberSource, make the SOAP request, and parse the reply into a Response object

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 755
def commit(request, action, amount, options)
  begin
    raw_response = ssl_post(test? ? self.test_url : self.live_url, build_request(request, options))
  rescue ResponseError => e
    raw_response = e.response.body
  end

  begin
    response = parse(raw_response)
  rescue REXML::ParseException => e
    response = { message: e.to_s }
  end

  success = response[:decision] == 'ACCEPT'
  message = response[:message]

  authorization = success ? authorization_from(response, action, amount, options) : nil

  Response.new(success, message, response,
    :test => test?,
    :authorization => authorization,
    :avs_result => { :code => response[:avsCode] },
    :cvv_result => response[:cvCode]
  )
end
extract_option(prioritized_options, option_name) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 421
def extract_option(prioritized_options, option_name)
  options_matching_key = prioritized_options.detect do |options|
    options.has_key? option_name
  end
  options_matching_key[option_name] if options_matching_key
end
lookup_country_code(country_field) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 711
def lookup_country_code(country_field)
  country_code = Country.find(country_field) rescue nil
  country_code&.code(:alpha2)
end
network_tokenization?(payment_method) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 553
def network_tokenization?(payment_method)
  payment_method.is_a?(NetworkTokenizationCreditCard)
end
parse(xml) click to toggle source

Parse the SOAP response Technique inspired by the Paypal Gateway

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 783
def parse(xml)
  reply = {}
  xml = REXML::Document.new(xml)
  if root = REXML::XPath.first(xml, '//c:replyMessage')
    root.elements.to_a.each do |node|
      case node.expanded_name
      when 'c:reasonCode'
        reply[:reasonCode] = node.text
        reply[:message] = reason_message(node.text)
      else
        parse_element(reply, node)
      end
    end
  elsif root = REXML::XPath.first(xml, '//soap:Fault')
    parse_element(reply, root)
    reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}"
  end
  return reply
end
parse_element(reply, node) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 803
def parse_element(reply, node)
  if node.has_elements?
    node.elements.each { |e| parse_element(reply, e) }
  else
    if node.parent.name =~ /item/
      parent = node.parent.name
      parent += '_' + node.parent.attributes['id'] if node.parent.attributes['id']
      parent += '_'
    end
    reply["#{parent}#{node.name}".to_sym] ||= node.text
  end
  return reply
end
reason_message(reason_code) click to toggle source
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 817
def reason_message(reason_code)
  return if reason_code.blank?
  @@response_codes[:"r#{reason_code}"]
end
setup_address_hash(options) click to toggle source

Create all address hash key value pairs so that we still function if we were only provided with one or two of them or even none

# File lib/active_merchant/billing/gateways/cyber_source.rb, line 246
def setup_address_hash(options)
  default_address = {
    :address1 => 'Unspecified',
    :city => 'Unspecified',
    :state => 'NC',
    :zip => '00000',
    :country => 'US'
  }
  options[:billing_address] = options[:billing_address] || options[:address] || default_address
  options[:shipping_address] = options[:shipping_address] || {}
end