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
-
For checks you can purchase and store.
-
AVS and CVV only work against the production server. You will always get back X for AVS and no response for CVV against the test server.
-
Nexus is the list of states or provinces where you have a physical presence. Nexus is used to calculate tax. Leave blank to tax everyone.
-
If you want to calculate VAT for overseas customers you must supply a registration number in the options hash as vat_reg_number.
-
productCode is a value in the line_items hash that is used to tell CyberSource what kind of item you are selling. It is used when calculating tax/VAT.
-
All transactions use dollar values.
-
The order of the XML elements does matter, make sure to follow the order in the documentation exactly.
Constants
- DEFAULT_COLLECTION_INDICATOR
- ECI_BRAND_MAPPING
- NT_PAYMENT_SOLUTION
- PRODUCTION_XSD_VERSION
- TEST_XSD_VERSION
Schema files can be found here: ics2ws.ic3.com/commerce/1.x/transactionProcessor/
- THREEDS_EXEMPTIONS
Public Class Methods
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
ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 174 def initialize(options = {}) requires!(options, :login, :password) super end
Public Instance Methods
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 214 def adjust(money, authorization, options = {}) commit(build_adjust_request(money, authorization, options), :adjust, money, options) end
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 291 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 190 def capture(money, authorization, options = {}) setup_address_hash(options) commit(build_capture_request(money, authorization, options), :capture, money, options) end
Adds credit to a card or subscription (stand alone credit).
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 227 def credit(money, creditcard_or_reference, options = {}) setup_address_hash(options) commit(build_credit_request(money, creditcard_or_reference, options), :credit, money, options) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 195 def purchase(money, payment_method, options = {}) if valid_payment_method?(payment_method) setup_address_hash(options) commit(build_purchase_request(money, payment_method, options), :purchase, money, options) else # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '') Response.new(false, "#{card_brand(payment_method).capitalize} is not supported by #{payment_type} at CyberSource, check https://developer.cybersource.com/docs/cybs/en-us/payments/developer/all/rest/payments/CreatingOnlineAuth/CreatingAuthReqPNT.html") end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 210 def refund(money, identification, options = {}) commit(build_refund_request(money, identification, options), :refund, money, options) end
Retrieves a customer subscription/profile
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 260 def retrieve(reference, options = {}) requires!(options, :order_id) commit(build_retrieve_subscription_request(reference, options), :retrieve, nil, options) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 301 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((<networkTokenCryptogram>)[^<]*(</networkTokenCryptogram>))i, '\1[FILTERED]\2'). gsub(%r((<requestorID>)[^<]*(</requestorID>))i, '\1[FILTERED]\2'). gsub(%r((<authenticationData>)[^<]*(</authenticationData>))i, '\1[FILTERED]\2') end
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 235 def store(payment_method, options = {}) if valid_payment_method?(payment_method) setup_address_hash(options) commit(build_create_subscription_request(payment_method, options), :store, nil, options) else # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '') Response.new(false, "#{card_brand(payment_method).capitalize} is not supported by #{payment_type} at CyberSource, check https://developer.cybersource.com/docs/cybs/en-us/payments/developer/all/rest/payments/CreatingOnlineAuth/CreatingAuthReqPNT.html") end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 313 def supports_network_tokenization? true end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 297 def supports_scrubbing? true end
Removes a customer subscription/profile
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 254 def unstore(reference, options = {}) requires!(options, :order_id) commit(build_delete_subscription_request(reference, options), :unstore, nil, options) end
Updates a customer subscription/profile
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 247 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 218 def verify(payment, options = {}) amount = eligible_for_zero_auth?(payment, options) ? 0 : 100 MultiResponse.run(:use_first_response) do |r| r.process { authorize(amount, payment, options) } r.process(:ignore_result) { void(r.authorization, options) } unless amount == 0 end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 317 def verify_credentials response = void('0') response.params['reasonCode'] == '102' end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 206 def void(identification, options = {}) commit(build_void_request(identification, options), :void, nil, options) end
Private Instance Methods
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 683 def add_address(xml, payment_method, address, options, shipTo = false) first_name, last_name = address_names(address[:name], payment_method) bill_to_merchant_tax_id = options[:merchant_tax_id] unless shipTo xml.tag! shipTo ? 'shipTo' : 'billTo' do xml.tag! 'firstName', first_name if first_name xml.tag! 'lastName', last_name if last_name 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].presence || '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? xml.tag! 'merchantTaxID', bill_to_merchant_tax_id unless bill_to_merchant_tax_id.blank? end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 658 def add_airline_data(xml, options) return unless options[:airline_agent_code] xml.tag! 'airlineData' do xml.tag! 'agentCode', options[:airline_agent_code] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 899 def add_auth_network_tokenization(xml, payment_method, options) commerce_indicator = stored_credential_commerce_indicator(options) || 'internet' xml.tag! 'ccAuthService', { 'run' => 'true' } do xml.tag!('networkTokenCryptogram', payment_method.payment_cryptogram) xml.tag!('commerceIndicator', commerce_indicator) xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 991 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 794 def add_auth_service(xml, payment_method, options) if network_tokenization?(payment_method) if payment_method.source == :network_token add_auth_network_tokenization(xml, payment_method, options) else add_auth_wallet(xml, payment_method, options) end else xml.tag! 'ccAuthService', { 'run' => 'true' } do if options[:three_d_secure] add_normalized_threeds_2_data(xml, payment_method, options) add_threeds_exemption_data(xml, options) if options[:three_ds_exemption_type] else indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options) xml.tag!('commerceIndicator', indicator) if indicator end xml.tag!('aggregatorID', options[:aggregator_id]) if options[:aggregator_id] xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id] xml.tag!('firstRecurringPayment', options[:first_recurring_payment]) if options[:first_recurring_payment] xml.tag!('mobileRemotePaymentType', options[:mobile_remote_payment_type]) if options[:mobile_remote_payment_type] end end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 908 def add_auth_wallet(xml, payment_method, options) commerce_indicator = 'internet' if subsequent_nt_apple_pay_auth(payment_method.source, options) brand = card_brand(payment_method).to_sym case brand when :visa xml.tag! 'ccAuthService', { 'run' => 'true' } do xml.tag!('cavv', payment_method.payment_cryptogram) unless commerce_indicator xml.commerceIndicator commerce_indicator.nil? ? ECI_BRAND_MAPPING[brand] : commerce_indicator xml.tag!('xid', payment_method.payment_cryptogram) unless commerce_indicator xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id] end when :master xml.tag! 'ccAuthService', { 'run' => 'true' } do xml.commerceIndicator commerce_indicator.nil? ? ECI_BRAND_MAPPING[brand] : commerce_indicator xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id] 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', ECI_BRAND_MAPPING[brand]) xml.tag!('xid', Base64.encode64(cryptogram[20...40])) if cryptogram.bytes.count > 20 xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id] end end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 570 def add_business_rules_data(xml, payment_method, options) prioritized_options = [options, @options] xml.tag! 'businessRules' do xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true' xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true' end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 959 def add_capture_service(xml, request_id, request_token, options) xml.tag! 'ccCaptureService', { 'run' => 'true' } do xml.tag! 'authRequestID', request_id xml.tag! 'authRequestToken', request_token xml.tag! 'gratuityAmount', options[:gratuity_amount] if options[:gratuity_amount] xml.tag! 'reconciliationID', options[:reconciliation_id] if options[:reconciliation_id] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 968 def add_capture_service_fields_with_run_false(xml, options) return unless options[:gratuity_amount] xml.tag! 'ccCaptureService', { 'run' => 'false' } do xml.tag! 'gratuityAmount', options[:gratuity_amount] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 778 def add_check(xml, check, options) xml.tag! 'check' do xml.tag! 'accountNumber', check.account_number xml.tag! 'accountType', check.account_type == 'checking' ? 'C' : 'S' xml.tag! 'bankTransitNumber', format_routing_number(check.routing_number, options) xml.tag! 'secCode', options[:sec_code] if options[:sec_code] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1057 def add_check_payment_method(xml) xml.tag! 'subscription' do xml.tag! 'paymentMethod', 'check' end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1009 def add_check_service(xml) xml.tag! 'ecDebitService', { 'run' => 'true' } end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 998 def add_credit_service(xml, options = {}) service = options[:use_check_service] ? 'ecCreditService' : 'ccCreditService' request_tag = options[:use_check_service] ? 'debitRequestID' : 'captureRequestID' options.delete :request_token if options[:use_check_service] xml.tag! service, { 'run' => 'true' } do xml.tag! request_tag, options[:request_id] if options[:request_id] xml.tag! 'captureRequestToken', options[:request_token] if options[:request_token] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 717 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].to_s == 'true' || creditcard.verification_value.blank? xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1051 def add_creditcard_payment_method(xml) xml.tag! 'subscription' do xml.tag! 'paymentMethod', 'credit card' end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 636 def add_customer_id(xml, options) return unless options[:customer_id] xml.tag! 'customerID', options[:customer_id] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 727 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 829 def add_incremental_auth_service(xml, authorization, options) xml.tag! 'ccIncrementalAuthService', { 'run' => 'true' } do xml.tag! 'authRequestID', authorization end xml.tag! 'subsequentAuthReason', options[:auth_reason] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1083 def add_installments(xml, options) return unless %i[installment_total_count installment_total_amount installment_plan_type first_installment_date installment_annual_interest_rate installment_grace_period_duration].any? { |gsf| options.include?(gsf) } xml.tag! 'installment' do xml.tag!('totalCount', options[:installment_total_count]) if options[:installment_total_count] xml.tag!('totalAmount', options[:installment_total_amount]) if options[:installment_total_amount] xml.tag!('planType', options[:installment_plan_type]) if options[:installment_plan_type] xml.tag!('firstInstallmentDate', options[:first_installment_date]) if options[:first_installment_date] xml.tag!('annualInterestRate', options[:installment_annual_interest_rate]) if options[:installment_annual_interest_rate] xml.tag!('gracePeriodDuration', options[:installment_grace_period_duration]) if options[:installment_grace_period_duration] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 748 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 586 def add_line_item_data(xml, options) return unless options[:line_items] 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] xml.tag! 'taxAmount', value[:tax_amount] if value[:tax_amount] xml.tag! 'nationalTax', value[:national_tax] if value[:national_tax] end end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 937 def add_mastercard_network_tokenization_ucaf_data(xml, payment_method, options) return unless network_tokenization?(payment_method) && card_brand(payment_method).to_sym == :master return if payment_method.source == :network_token commerce_indicator = 'internet' if subsequent_nt_apple_pay_auth(payment_method.source, options) xml.tag! 'ucaf' do xml.tag!('authenticationData', payment_method.payment_cryptogram) unless commerce_indicator xml.tag!('collectionIndicator', DEFAULT_COLLECTION_INDICATOR) end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 767 def add_mdd_fields(xml, options) return unless options.keys.any? { |key| key.to_s.start_with?('mdd_field') && options[key] } xml.tag! 'merchantDefinedData' do (1..100).each do |each| key = "mdd_field_#{each}".to_sym xml.tag!('mddField', options[key], 'id' => each) if options[key] end end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 602 def add_merchant_data(xml, options) xml.tag! 'merchantID', options[:merchant_id] || @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 add_merchant_descriptor(xml, options) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 642 def add_merchant_description(xml, options) return unless options[:merchant_descriptor_name] || options[:merchant_descriptor_address1] || options[:merchant_descriptor_locality] xml.tag! 'merchantInformation' do xml.tag! 'merchantDescriptor' do xml.tag! 'name', options[:merchant_descriptor_name] if options[:merchant_descriptor_name] xml.tag! 'address1', options[:merchant_descriptor_address1] if options[:merchant_descriptor_address1] xml.tag! 'locality', options[:merchant_descriptor_locality] if options[:merchant_descriptor_locality] end end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 612 def add_merchant_descriptor(xml, options) return unless options[:merchant_descriptor] || options[:user_po] || options[:taxable] || options[:reference_data_code] || options[:invoice_number] || options[:merchant_descriptor_city] || options[:submerchant_id] || options[:merchant_descriptor_state] || options[:merchant_descriptor_country] xml.tag! 'invoiceHeader' do xml.tag! 'merchantDescriptor', options[:merchant_descriptor] if options[:merchant_descriptor] xml.tag! 'merchantDescriptorCity', options[:merchant_descriptor_city] if options[:merchant_descriptor_city] xml.tag! 'merchantDescriptorState', options[:merchant_descriptor_state] if options[:merchant_descriptor_state] xml.tag! 'merchantDescriptorCountry', options[:merchant_descriptor_country] if options[:merchant_descriptor_country] xml.tag! 'userPO', options[:user_po] if options[:user_po] xml.tag! 'taxable', options[:taxable] if options[:taxable] xml.tag! 'submerchantID', options[:submerchant_id] if options[:submerchant_id] xml.tag! 'referenceDataCode', options[:reference_data_code] if options[:reference_data_code] xml.tag! 'invoiceNumber', options[:invoice_number] if options[:invoice_number] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 836 def add_normalized_threeds_2_data(xml, payment_method, options) threeds_2_options = options[:three_d_secure] cc_brand = card_brand(payment_method).to_sym return if threeds_2_options[:cavv].blank? && infer_commerce_indicator?(options, cc_brand) xid = threeds_2_options[:xid] xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && cc_brand != :master xml.tag!('cavvAlgorithm', threeds_2_options[:cavv_algorithm]) if threeds_2_options[:cavv_algorithm] xml.tag!('paSpecificationVersion', threeds_2_options[:version]) if threeds_2_options[:version] xml.tag!('directoryServerTransactionID', threeds_2_options[:ds_transaction_id]) if threeds_2_options[:ds_transaction_id] xml.tag!('commerceIndicator', options[:commerce_indicator] || ECI_BRAND_MAPPING[cc_brand]) xml.tag!('eciRaw', threeds_2_options[:eci]) if threeds_2_options[:eci] if xid.present? xml.tag!('xid', xid) elsif threeds_2_options[:version]&.start_with?('2') && cc_brand != :master cavv = threeds_2_options[:cavv] xml.tag!('xid', cavv) if cavv.present? end xml.tag!('veresEnrolled', threeds_2_options[:enrolled]) if threeds_2_options[:enrolled] xml.tag!('paresStatus', threeds_2_options[:authentication_response_status]) if threeds_2_options[:authentication_response_status] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 756 def add_other_tax(xml, options) return unless %i[vat_tax_rate local_tax_amount national_tax_amount national_tax_indicator].any? { |gsf| options.include?(gsf) } xml.tag! 'otherTax' do xml.tag! 'vatTaxRate', options[:vat_tax_rate] if options[:vat_tax_rate] xml.tag! 'localTaxAmount', options[:local_tax_amount] if options[:local_tax_amount] xml.tag! 'nationalTaxAmount', options[:national_tax_amount] if options[:national_tax_amount] xml.tag! 'nationalTaxIndicator', options[:national_tax_indicator] if options[:national_tax_indicator] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1152 def add_partner_solution_id(xml) return unless application_id xml.tag!('partnerSolutionID', application_id) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1063 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_installments(xml, 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_installments(xml, options) add_check(xml, payment_method_or_reference, options) 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_line_item_data(xml, options) add_purchase_data(xml, money, true, options) add_installments(xml, options) add_creditcard(xml, payment_method_or_reference) end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 949 def add_payment_network_token(xml, payment_method, options) return unless network_tokenization?(payment_method) transaction_type = payment_method.source == :network_token ? '3' : '1' xml.tag! 'paymentNetworkToken' do xml.tag!('requestorID', options[:trid]) if transaction_type == '3' && options[:trid] xml.tag!('transactionType', transaction_type) end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 736 def add_payment_solution(xml, payment_method) return unless network_tokenization?(payment_method) case payment_method.source when :network_token payment_solution = NT_PAYMENT_SOLUTION[payment_method.brand] xml.tag! 'paymentSolution', payment_solution if payment_solution when :apple_pay, :google_pay xml.tag! 'paymentSolution', @@wallet_payment_solution[payment_method.source] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 672 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!('discountManagementIndicator', options[:discount_management_indicator]) if options[:discount_management_indicator] xml.tag!('taxAmount', options[:purchase_tax_amount]) if options[:purchase_tax_amount] xml.tag!('grandTotalAmount', localized_amount(money.to_i, options[:currency] || default_currency)) if include_grand_total xml.tag!('originalAmount', options[:original_amount]) if options[:original_amount] xml.tag!('invoiceAmount', options[:invoice_amount]) if options[:invoice_amount] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 976 def add_purchase_service(xml, payment_method, options) add_auth_service(xml, payment_method, options) xml.tag! 'ccCaptureService', { 'run' => 'true' } do xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id] xml.tag!('gratuityAmount', options[:gratuity_amount]) if options[:gratuity_amount] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 654 def add_sales_slip_number(xml, options) xml.tag! 'salesSlipNumber', options[:sales_slip_number] if options[:sales_slip_number] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1120 def add_stored_credential_options(xml, options = {}) return unless options[:stored_credential] || options[:stored_credential_overrides] stored_credential_subsequent_auth_first = 'true' if cardholder_or_initiated_transaction?(options) stored_credential_transaction_id = options.dig(:stored_credential, :network_transaction_id) if options.dig(:stored_credential, :initiator) == 'merchant' stored_credential_subsequent_auth_stored_cred = 'true' if subsequent_cardholder_initiated_transaction?(options) || unscheduled_merchant_initiated_transaction?(options) || threeds_stored_credential_exemption?(options) override_subsequent_auth_first = options.dig(:stored_credential_overrides, :subsequent_auth_first) override_subsequent_auth_transaction_id = options.dig(:stored_credential_overrides, :subsequent_auth_transaction_id) override_subsequent_auth_stored_cred = options.dig(:stored_credential_overrides, :subsequent_auth_stored_credential) xml.subsequentAuthFirst override_subsequent_auth_first.nil? ? stored_credential_subsequent_auth_first : override_subsequent_auth_first xml.subsequentAuthTransactionID override_subsequent_auth_transaction_id.nil? ? stored_credential_transaction_id : override_subsequent_auth_transaction_id xml.subsequentAuthStoredCredential override_subsequent_auth_stored_cred.nil? ? stored_credential_subsequent_auth_stored_cred : override_subsequent_auth_stored_cred end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1110 def add_stored_credential_subsequent_auth(xml, options = {}) return unless options[:stored_credential] || options[:stored_credential_overrides] stored_credential_subsequent_auth = 'true' if options.dig(:stored_credential, :initiator) == 'merchant' override_subsequent_auth = options.dig(:stored_credential_overrides, :subsequent_auth) xml.subsequentAuth override_subsequent_auth.nil? ? stored_credential_subsequent_auth : override_subsequent_auth end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1029 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1013 def add_subscription_create_service(xml, options) xml.tag! 'paySubscriptionCreateService', { 'run' => 'true' } end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1021 def add_subscription_delete_service(xml, options) xml.tag! 'paySubscriptionDeleteService', { 'run' => 'true' } end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1025 def add_subscription_retrieve_service(xml, options) xml.tag! 'paySubscriptionRetrieveService', { 'run' => 'true' } end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1017 def add_subscription_update_service(xml, options) xml.tag! 'paySubscriptionUpdateService', { 'run' => 'true' } end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 666 def add_tax_management_indicator(xml, options) return unless options[:tax_management_indicator] xml.tag! 'taxManagementIndicator', options[:tax_management_indicator] if options[:tax_management_indicator] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 787 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 866 def add_threeds_2_ucaf_data(xml, payment_method, options) return unless options[:three_d_secure] && card_brand(payment_method).to_sym == :master xml.tag! 'ucaf' do xml.tag!('authenticationData', options[:three_d_secure][:cavv]) xml.tag!('collectionIndicator', options[:collection_indicator] || DEFAULT_COLLECTION_INDICATOR) end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 818 def add_threeds_exemption_data(xml, options) return unless options[:three_ds_exemption_type] exemption = options[:three_ds_exemption_type].to_sym case exemption when :authentication_outage, :corporate_card, :delegated_authentication, :low_risk, :low_value, :trusted_merchant xml.tag!(THREEDS_EXEMPTIONS[exemption], '1') end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1096 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 984 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 707 def address_names(address_name, payment_method) names = split_names(address_name) return names if names.any?(&:present?) [ payment_method&.first_name, payment_method&.last_name ] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1216 def auto_void?(authorization, response, message, options = {}) return message unless response[:reasonCode] == '230' && options[:auto_void_230] response = void(authorization, options) response&.success? ? message += ' - transaction has been auto-voided.' : message += ' - transaction could not be auto-voided.' message end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 383 def build_adjust_request(money, authorization, options) _, request_id = authorization.split(';') xml = Builder::XmlMarkup.new indent: 2 add_purchase_data(xml, money, true, options) add_incremental_auth_service(xml, request_id, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 357 def build_auth_request(money, creditcard_or_reference, options) xml = Builder::XmlMarkup.new indent: 2 add_customer_id(xml, options) add_payment_method_or_subscription(xml, money, creditcard_or_reference, options) add_threeds_2_ucaf_data(xml, creditcard_or_reference, options) add_mastercard_network_tokenization_ucaf_data(xml, creditcard_or_reference, options) add_decision_manager_fields(xml, options) add_other_tax(xml, options) add_mdd_fields(xml, options) add_auth_service(xml, creditcard_or_reference, options) add_capture_service_fields_with_run_false(xml, options) add_threeds_services(xml, options) add_business_rules_data(xml, creditcard_or_reference, options) add_airline_data(xml, options) add_sales_slip_number(xml, options) add_payment_network_token(xml, creditcard_or_reference, options) add_payment_solution(xml, creditcard_or_reference) add_tax_management_indicator(xml, options) add_stored_credential_subsequent_auth(xml, options) add_issuer_additional_data(xml, options) add_partner_solution_id(xml) add_stored_credential_options(xml, options) add_merchant_description(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 404 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_other_tax(xml, options) add_mdd_fields(xml, options) add_capture_service(xml, request_id, request_token, options) add_business_rules_data(xml, authorization, options) add_tax_management_indicator(xml, options) add_issuer_additional_data(xml, options) add_merchant_description(xml, options) add_partner_solution_id(xml) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 510 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, options) add_check_payment_method(xml) options[:payment_method] = :check else add_creditcard(xml, payment_method) add_creditcard_payment_method(xml) options[:payment_method] = :credit_card 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, payment_method, options) end end add_subscription_create_service(xml, options) add_business_rules_data(xml, payment_method, options) add_tax_management_indicator(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 498 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_mdd_fields(xml, options) add_credit_service(xml, use_check_service: creditcard_or_reference.is_a?(Check)) add_issuer_additional_data(xml, options) add_merchant_description(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 556 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 422 def build_purchase_request(money, payment_method_or_reference, options) xml = Builder::XmlMarkup.new indent: 2 add_customer_id(xml, options) add_payment_method_or_subscription(xml, money, payment_method_or_reference, options) add_threeds_2_ucaf_data(xml, payment_method_or_reference, options) add_mastercard_network_tokenization_ucaf_data(xml, payment_method_or_reference, options) add_decision_manager_fields(xml, options) add_other_tax(xml, options) add_mdd_fields(xml, options) if (!payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check') || reference_is_a_check?(payment_method_or_reference) add_check_service(xml) add_airline_data(xml, options) add_sales_slip_number(xml, options) add_tax_management_indicator(xml, options) add_issuer_additional_data(xml, options) add_partner_solution_id(xml) options[:payment_method] = :check else add_purchase_service(xml, payment_method_or_reference, options) add_threeds_services(xml, options) add_business_rules_data(xml, payment_method_or_reference, options) add_airline_data(xml, options) add_sales_slip_number(xml, options) add_payment_network_token(xml, payment_method_or_reference, options) add_payment_solution(xml, payment_method_or_reference) add_tax_management_indicator(xml, options) add_stored_credential_subsequent_auth(xml, options) add_issuer_additional_data(xml, options) add_partner_solution_id(xml) add_stored_credential_options(xml, options) options[:payment_method] = :credit_card end add_merchant_description(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 484 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_id, request_token: request_token, use_check_service: reference_is_a_check?(identification)) add_partner_solution_id(xml) xml.target! end
Where we actually build the full SOAP request using builder
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1159 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 563 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 392 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) add_tax_management_indicator(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 543 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) add_tax_management_indicator(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 464 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 case action when 'capture', 'purchase' add_mdd_fields(xml, options) add_void_service(xml, request_id, request_token) else add_purchase_data(xml, money, true, options.merge(currency: currency || default_currency)) add_mdd_fields(xml, options) add_auth_reversal_service(xml, request_id, request_token) end add_issuer_additional_data(xml, options) add_partner_solution_id(xml) xml.target! end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1136 def cardholder_or_initiated_transaction?(options) options.dig(:stored_credential, :initiator) == 'cardholder' || options.dig(:stored_credential, :initial_transaction) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 347 def check_billing_field_value(default, submitted) if submitted.nil? nil elsif submitted.blank? default else submitted end end
Contact CyberSource, make the SOAP request, and parse the reply into a Response
object
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1185 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 = success?(response) message = message_from(response) authorization = success || in_fraud_review?(response) ? authorization_from(response, action, amount, options) : nil message = auto_void?(authorization_from(response, action, amount, options), response, message, options) Response.new( success, message, response, test: test?, authorization: authorization, fraud_review: in_fraud_review?(response), avs_result: { code: response[:avsCode] }, cvv_result: response[:cvCode] ) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1290 def eligible_for_zero_auth?(payment_method, options = {}) payment_method.is_a?(CreditCard) && options[:zero_amount_auth] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 579 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1294 def format_routing_number(routing_number, options) options[:currency] == 'CAD' && routing_number.length > 8 ? routing_number[-8..-1] : routing_number end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1272 def in_fraud_review?(response) response[:decision] == @@decision_codes[:review] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 862 def infer_commerce_indicator?(options, cc_brand) options[:commerce_indicator].blank? && ECI_BRAND_MAPPING[cc_brand].present? end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1105 def lookup_country_code(country_field) country_code = Country.find(country_field) rescue nil country_code&.code(:alpha2) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1280 def message_from(response) if response[:reasonCode] == '101' && response[:missingField] "#{response[:message]}: #{response[:missingField]}" elsif response[:reasonCode] == '102' && response[:invalidField] "#{response[:message]}: #{response[:invalidField]}" else response[:message] end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 888 def network_tokenization?(payment_method) payment_method.is_a?(NetworkTokenizationCreditCard) end
Parse the SOAP response Technique inspired by the Paypal Gateway
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1226 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
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1246 def parse_element(reply, node) if node.has_elements? node.elements.each { |e| parse_element(reply, e) } else if /item/.match?(node.parent.name) parent = node.parent.name parent += '_' + node.parent.attributes['id'] if node.parent.attributes['id'] parent += '_' end reply[:reconciliationID2] = node.text if node.name == 'reconciliationID' && reply[:reconciliationID] reply["#{parent}#{node.name}".to_sym] ||= node.text end return reply end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1261 def reason_message(reason_code) return if reason_code.blank? @@response_codes[:"r#{reason_code}"] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 460 def reference_is_a_check?(payment_method_or_reference) payment_method_or_reference.is_a?(String) && payment_method_or_reference.split(';')[7] == 'check' end
Create all required address hash key value pairs If a value of nil is received, that value will be passed on to the gateway and will not be replaced with a default value Billing
address fields received without an override value or with an empty string value will be replaced with the default_address values
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 333 def setup_address_hash(options) default_address = { address1: 'Unspecified', city: 'Unspecified', state: 'NC', zip: '00000', country: 'US' } submitted_address = options[:billing_address] || options[:address] || default_address options[:billing_address] = default_address.merge(submitted_address.symbolize_keys) { |_k, default, submitted| check_billing_field_value(default, submitted) } options[:shipping_address] = options[:shipping_address] || {} end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 875 def stored_credential_commerce_indicator(options) return unless (reason_type = options.dig(:stored_credential, :reason_type)) case reason_type when 'installment' 'install' when 'recurring' 'recurring' else 'internet' end end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1140 def subsequent_cardholder_initiated_transaction?(options) options.dig(:stored_credential, :initiator) == 'cardholder' && !options.dig(:stored_credential, :initial_transaction) end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 892 def subsequent_nt_apple_pay_auth(source, options) return unless options[:stored_credential] || options[:stored_credential_overrides] return unless @@wallet_payment_solution[source] options.dig(:stored_credential_overrides, :subsequent_auth) || options.dig(:stored_credential, :initiator) == 'merchant' end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1276 def success?(response) response[:decision] == @@decision_codes[:accept] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1148 def threeds_stored_credential_exemption?(options) options[:three_ds_exemption_type] == THREEDS_EXEMPTIONS[:stored_credential] end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 1144 def unscheduled_merchant_initiated_transaction?(options) options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled' end
# File lib/active_merchant/billing/gateways/cyber_source.rb, line 324 def valid_payment_method?(payment_method) return true unless payment_method.is_a?(NetworkTokenizationCreditCard) %w(visa master american_express).include?(card_brand(payment_method)) end