class ActiveMerchant::Billing::FirstdataE4Gateway
Constants
- BRANDS
- DEFAULT_ECI
- E4_BRANDS
- POST_HEADERS
- SENSITIVE_FIELDS
- STANDARD_ERROR_CODE_MAPPING
- SUCCESS
- TRANSACTIONS
Public Class Methods
Create a new FirstdataE4Gateway
The gateway requires that a valid login and password be passed in the options
hash.
Options¶ ↑
-
:login
– The EXACT ID. Also known as theGateway
ID.(Found in your administration terminal settings)
-
:password
– The terminal password (not your account password)
ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 76 def initialize(options = {}) requires!(options, :login, :password) @options = options super end
Public Instance Methods
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 91 def capture(money, authorization, options = {}) commit(:capture, build_capture_or_credit_request(money, authorization, options)) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 87 def purchase(money, credit_card_or_store_authorization, options = {}) commit(:sale, build_sale_or_authorization_request(money, credit_card_or_store_authorization, options)) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 99 def refund(money, authorization, options = {}) commit(:credit, build_capture_or_credit_request(money, authorization, options)) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 143 def scrub(transcript) transcript. gsub(%r((<Card_Number>).+(</Card_Number>)), '\1[FILTERED]\2'). gsub(%r((<VerificationStr2>).+(</VerificationStr2>)), '\1[FILTERED]\2'). gsub(%r((<Password>).+(</Password>))i, '\1[FILTERED]\2'). gsub(%r((<CAVV>).+(</CAVV>)), '\1[FILTERED]\2'). gsub(%r((Card Number : ).*\d)i, '\1[FILTERED]') end
Tokenize a credit card with TransArmor
The TransArmor token and other card data necessary for subsequent transactions is stored in the response's authorization
attribute. The authorization string may be passed to authorize
and purchase
instead of a ActiveMerchant::Billing::CreditCard
instance.
TransArmor support must be explicitly activated on your gateway account by FirstData. If your authorization string is empty, contact FirstData support for account setup assistance.
Example¶ ↑
# Generate token result = gateway.store(credit_card) if result.success? my_record.update_attributes(:authorization => result.authorization) end # Use token result = gateway.purchase(1000, my_record.authorization)
firstdata.zendesk.com/entries/21303361-transarmor-tokenization
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 130 def store(credit_card, options = {}) commit(:store, build_store_request(credit_card, options), credit_card) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 152 def supports_network_tokenization? true end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 139 def supports_scrubbing? true end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 103 def verify(credit_card, options = {}) commit(:verify, build_sale_or_authorization_request(0, credit_card, options)) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 134 def verify_credentials response = void('0') response.message != 'Unauthorized Request. Bad or missing credentials.' end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 95 def void(authorization, options = {}) commit(:void, build_capture_or_credit_request(money_from_authorization(authorization), authorization, options)) end
Private Instance Methods
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 319 def add_address(xml, options) if address = (options[:billing_address] || options[:address]) xml.tag! 'ZipCode', address[:zip] end end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 226 def add_amount(xml, money, options) currency_code = options[:currency] || default_currency xml.tag! 'DollarAmount', localized_amount(money, currency_code) xml.tag! 'Currency', currency_code end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 292 def add_card_authentication_data(xml, options) xml.tag! 'CAVV', options[:cavv] xml.tag! 'XID', options[:xid] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 210 def add_credentials(xml) xml.tag! 'ExactID', @options[:login] xml.tag! 'Password', @options[:password] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 232 def add_credit_card(xml, credit_card, options) if credit_card.respond_to?(:track_data) && credit_card.track_data.present? xml.tag! 'Track1', credit_card.track_data xml.tag! 'Ecommerce_Flag', 'R' else xml.tag! 'Card_Number', credit_card.number xml.tag! 'Expiry_Date', expdate(credit_card) xml.tag! 'CardHoldersName', credit_card.name xml.tag! 'CardType', card_type(credit_card.brand) add_credit_card_eci(xml, credit_card, options) add_credit_card_verification_strings(xml, credit_card, options) end end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 247 def add_credit_card_eci(xml, credit_card, options) eci = if credit_card.is_a?(NetworkTokenizationCreditCard) && credit_card.source == :apple_pay && card_brand(credit_card) == 'discover' # Discover requires any Apple Pay transaction, regardless of in-app # or web, and regardless of the ECI contained in the PKPaymentToken, # to have an ECI value explicitly of 04. '04' else (credit_card.respond_to?(:eci) ? credit_card.eci : nil) || options[:eci] || DEFAULT_ECI end xml.tag! 'Ecommerce_Flag', eci.to_s =~ /^[0-9]+$/ ? eci.to_s.rjust(2, '0') : eci end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 297 def add_credit_card_token(xml, store_authorization, options) params = store_authorization.split(';') credit_card = CreditCard.new( :brand => params[1], :first_name => params[2], :last_name => params[3], :month => params[4], :year => params[5]) xml.tag! 'TransarmorToken', params[0] xml.tag! 'Expiry_Date', expdate(credit_card) xml.tag! 'CardHoldersName', credit_card.name xml.tag! 'CardType', card_type(credit_card.brand) add_card_authentication_data(xml, options) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 260 def add_credit_card_verification_strings(xml, credit_card, options) address = options[:billing_address] || options[:address] if address address_values = [] [:address1, :zip, :city, :state, :country].each { |part| address_values << address[part].to_s } xml.tag! 'VerificationStr1', address_values.join('|') end if credit_card.is_a?(NetworkTokenizationCreditCard) add_network_tokenization_credit_card(xml, credit_card) else if credit_card.verification_value? xml.tag! 'CVD_Presence_Ind', '1' xml.tag! 'VerificationStr2', credit_card.verification_value end add_card_authentication_data(xml, options) end end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 313 def add_customer_data(xml, options) xml.tag! 'Customer_Ref', options[:customer] if options[:customer] xml.tag! 'Client_IP', options[:ip] if options[:ip] xml.tag! 'Client_Email', options[:email] if options[:email] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 219 def add_identification(xml, identification) authorization_num, transaction_tag, _ = identification.split(';') xml.tag! 'Authorization_Num', authorization_num xml.tag! 'Transaction_Tag', transaction_tag end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 325 def add_invoice(xml, options) xml.tag! 'Reference_No', options[:order_id] xml.tag! 'Reference_3', options[:description] if options[:description] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 335 def add_level_3(xml, options) xml.tag!('Level3') { |x| x << options[:level_3] } if options[:level_3] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 280 def add_network_tokenization_credit_card(xml, credit_card) case card_brand(credit_card).to_sym when :american_express cryptogram = Base64.decode64(credit_card.payment_cryptogram) xml.tag!('XID', Base64.encode64(cryptogram[20...40])) xml.tag!('CAVV', Base64.encode64(cryptogram[0...20])) else xml.tag!('XID', credit_card.transaction_id) if credit_card.transaction_id xml.tag!('CAVV', credit_card.payment_cryptogram) end end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 330 def add_tax_fields(xml, options) xml.tag! 'Tax1Amount', options[:tax1_amount] if options[:tax1_amount] xml.tag! 'Tax1Number', options[:tax1_number] if options[:tax1_number] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 215 def add_transaction_type(xml, action) xml.tag! 'Transaction_Type', TRANSACTIONS[action] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 190 def build_capture_or_credit_request(money, identification, options) xml = Builder::XmlMarkup.new add_identification(xml, identification) add_amount(xml, money, options) add_customer_data(xml, options) add_card_authentication_data(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 158 def build_request(action, body) xml = Builder::XmlMarkup.new xml.instruct! xml.tag! 'Transaction', xmlns: 'http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/encodedTypes' do add_credentials(xml) add_transaction_type(xml, action) xml << body end xml.target! end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 201 def build_store_request(credit_card, options) xml = Builder::XmlMarkup.new add_credit_card(xml, credit_card, options) add_customer_data(xml, options) xml.target! end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 343 def card_type(credit_card_brand) E4_BRANDS[credit_card_brand.to_sym] if credit_card_brand end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 347 def commit(action, request, credit_card = nil) url = (test? ? self.test_url : self.live_url) begin response = parse(ssl_post(url, build_request(action, request), POST_HEADERS)) rescue ResponseError => e response = parse_error(e.response) end Response.new(successful?(response), message_from(response), response, :test => test?, :authorization => successful?(response) ? response_authorization(action, response, credit_card) : '', :avs_result => {:code => response[:avs]}, :cvv_result => response[:cvv2], :error_code => standard_error_code(response) ) end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 339 def expdate(credit_card) "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}" end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 408 def message_from(response) if(response[:faultcode] && response[:faultstring]) response[:faultstring] elsif(response[:error_number] && response[:error_number] != '0') response[:error_description] else result = (response[:exact_message] || '') result << " - #{response[:bank_message]}" if response[:bank_message].present? result end end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 433 def parse(xml) response = {} xml = REXML::Document.new(xml) if root = REXML::XPath.first(xml, '//TransactionResult') parse_elements(response, root) end response.delete_if { |k, v| SENSITIVE_FIELDS.include?(k) } end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 444 def parse_elements(response, root) root.elements.to_a.each do |node| response[node.name.gsub(/EXact/, 'Exact').underscore.to_sym] = (node.text || '').strip end end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 420 def parse_error(error) { :transaction_approved => 'false', :error_number => error.code, :error_description => error.body, :ecommerce_error_code => error.body.gsub(/[^\d]/, '') } end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 429 def standard_error_code(response) STANDARD_ERROR_CODE_MAPPING[response[:bank_resp_code] || response[:ecommerce_error_code]] end
# File lib/active_merchant/billing/gateways/firstdata_e4.rb, line 364 def successful?(response) response[:transaction_approved] == SUCCESS end