require 'ews/transaction/validator'
module EWS # :nodoc:
module Transaction # :nodoc:
# The Request class allows you to build transaction requests for
# submission to the E-xact Web Service.
#
# All requests will result in a financial transaction occurring, with the exception
# of the :transaction_details request, which looks up the details of a pre-existing
# transaction.
#
# The following fields are *mandatory* on all requests:
# :gateway_id the gateway to which this request should be sent
# :password your password for that gateway
# :transaction_type the type of transaction you want to perform
#
# Different transaction types will have their own additional requirements when it comes to
# mandatory and optional fields, and it is recommended that the E-xact Web Service Programming
# Reference Guide, v8.5 be consulted. This document is contained in the Webservice Plugin ZIP file:
# http://www.e-xact.com/wp-content/uploads/2007/06/E-xact_Payment_Webservice_Plug-In.zip
#
# Please note that, if your chosen transaction requires it, credit card expiry dates *must* be entered in MMYY format.
#
# =Allowable transaction types
# :purchase
# :pre_auth
# :pre_auth_completion
# :forced_post
# :refund
# :pre_auth_only
# :purchase_correction
# :refund_correction
# :void
# :tagged_purchase
# :tagged_pre_auth
# :tagged_pre_auth_completion
# :tagged_void
# :tagged_refund
# :tagged_online_debit_refund
# :tagged_update
# :referenced_void
# :recurring_seed_pre_auth
# :recurring_seed_purchase
# :idebit_purchase
# :idebit_refund
# :secure_storage
# :secure_storage_eft
# :batch_query
# :batch_close
# :transaction_details
class Request
include Validator
# yeah, it's ugly, but otherwise RDoc won't pick them up
attr_accessor :errors
attr_accessor :gateway_id, :password, :transaction_type, :amount, :surcharge_amount, :cc_number, :transaction_tag, :track1, :track2, :pan, :authorization_num, :cc_expiry, :cardholder_name
attr_accessor :cc_verification_str2, :cvd_presence_ind, :tax1_amount, :tax1_number, :tax2_amount, :tax2_number, :secure_auth_required, :secure_auth_result, :user_name
# AVS - Address Verification,
attr_accessor :cc_verification_str1
[:avs_test_flag, :avs_street_address, :avs_unit_no, :avs_po_box, :avs_postal_code].each { |m|
class_eval <<-METHOD_EOS
def #{m.to_s}
@#{m.to_s}
end
def #{m.to_s}=(v)
@#{m.to_s} = v
calculate_verification_str1
end
METHOD_EOS
}
attr_accessor :ecommerce_flag, :xid, :cavv, :cavv_algorithm, :reference_no, :customer_ref, :reference_3, :language, :client_ip, :client_email, :zip_code
# Initialize a Request with a hash of values
def initialize(hash = {})
hash.each {|k,v| self.send "#{k.to_s}=", v}
@errors = {}
end
# Set the transasction_type using either a symbol or the relevant code, e.g: for a purchase
# you can use either :purchase or '00'
def transaction_type=(type_sym)
# assume we're given a symbol, so look up the code
value = @@transaction_codes[type_sym]
# if nothing found, then maybe we were given an actual code?
if(value.nil?)
raise ArgumentError, "invalid transaction_type supplied #{type_sym}" unless @@transaction_codes.values.include?(type_sym)
value = type_sym
end
@transaction_type = value
end
# Indicates whether or not this transaction is a :transaction_details transaction
def is_find_transaction?
self.transaction_type == "CR"
end
private
@@transaction_codes = {
:purchase => '00',
:pre_auth => '01',
:pre_auth_completion => '02',
:forced_post => '03',
:refund => '04',
:pre_auth_only => '05',
:purchase_correction => '11',
:refund_correction => '12',
:void => '13',
:tagged_purchase => '30',
:tagged_pre_auth => '31',
:tagged_pre_auth_completion => '32',
:tagged_void => '33',
:tagged_refund => '34',
:tagged_online_debit_refund => '35',
:referenced_void => '36',
:tagged_update => '37',
:recurring_seed_pre_auth => '40',
:recurring_seed_purchase => '41',
:idebit_purchase => '50',
:idebit_refund => '54',
:secure_storage => '60',
:secure_storage_eft => '61',
:batch_query => '80',
:batch_close => '81',
:transaction_details => 'CR'
}.freeze unless defined?(@@transaction_codes)
# Calculate verification str1, callback method invoked after the avs_*= methods
def calculate_verification_str1
self.cc_verification_str1 = ''
self.cc_verification_str1 << (self.avs_test_flag || '')
unless self.avs_street_address.nil?
self.cc_verification_str1 << (self.avs_street_address || '')
self.cc_verification_str1 << (self.avs_unit_no || '')
else
self.cc_verification_str1 << (self.avs_po_box || '')
end
unless self.avs_postal_code.nil?
self.cc_verification_str1 << '|' << self.avs_postal_code
end
end
end
end
end