require 'rexml/document'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
# Public: For more information on the Eway Gateway please visit their
# {Developers Area}[http://www.eway.com.au/developers/api/direct-payments]
class EwayGateway < Gateway
self.live_url = 'https://www.eway.com.au'
self.money_format = :cents
self.supported_countries = ['AU']
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
self.homepage_url = 'http://www.eway.com.au/'
self.display_name = 'eWAY'
# Public: Create a new Eway Gateway.
# options - A hash of options:
# :login - Your Customer ID.
# :password - Your XML Refund Password that you
# specified on the Eway site. (optional)
def initialize(options = {})
requires!(options, :login)
super
end
def purchase(money, creditcard, options = {})
requires_address!(options)
post = {}
add_creditcard(post, creditcard)
add_address(post, options)
add_customer_id(post)
add_invoice_data(post, options)
add_non_optional_data(post)
add_amount(post, money)
post[:CustomerEmail] = options[:email]
commit(purchase_url(post[:CVN]), money, post)
end
def refund(money, authorization, options={})
post = {}
add_customer_id(post)
add_amount(post, money)
add_non_optional_data(post)
post[:OriginalTrxnNumber] = authorization
post[:RefundPassword] = @options[:password]
post[:CardExpiryMonth] = nil
post[:CardExpiryYear] = nil
commit(refund_url, money, post)
end
def supports_scrubbing
true
end
def scrub(transcript)
transcript.
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
gsub(%r(()\d+())i, '\1[FILTERED]\2').
gsub(%r(()\d+())i, '\1[FILTERED]\2')
end
private
def requires_address!(options)
raise ArgumentError.new('Missing eWay required parameters: address or billing_address') unless options.has_key?(:address) or options.has_key?(:billing_address)
end
def add_creditcard(post, creditcard)
post[:CardNumber] = creditcard.number
post[:CardExpiryMonth] = sprintf('%.2i', creditcard.month)
post[:CardExpiryYear] = sprintf('%.4i', creditcard.year)[-2..-1]
post[:CustomerFirstName] = creditcard.first_name
post[:CustomerLastName] = creditcard.last_name
post[:CardHoldersName] = creditcard.name
post[:CVN] = creditcard.verification_value if creditcard.verification_value?
end
def add_address(post, options)
if address = options[:billing_address] || options[:address]
post[:CustomerAddress] = [address[:address1], address[:address2], address[:city], address[:state], address[:country]].compact.join(', ')
post[:CustomerPostcode] = address[:zip]
end
end
def add_customer_id(post)
post[:CustomerID] = @options[:login]
end
def add_invoice_data(post, options)
post[:CustomerInvoiceRef] = options[:order_id]
post[:CustomerInvoiceDescription] = options[:description]
end
def add_amount(post, money)
post[:TotalAmount] = amount(money)
end
def add_non_optional_data(post)
post[:Option1] = nil
post[:Option2] = nil
post[:Option3] = nil
post[:TrxnNumber] = nil
end
def commit(url, money, parameters)
raw_response = ssl_post(url, post_data(parameters))
response = parse(raw_response)
Response.new(success?(response),
message_from(response[:ewaytrxnerror]),
response,
authorization: response[:ewaytrxnnumber],
test: test?
)
end
def success?(response)
response[:ewaytrxnstatus] == 'True'
end
def parse(xml)
response = {}
xml = REXML::Document.new(xml)
xml.elements.each('//ewayResponse/*') do |node|
response[node.name.downcase.to_sym] = normalize(node.text)
end unless xml.root.nil?
response
end
def post_data(parameters = {})
xml = REXML::Document.new
root = xml.add_element('ewaygateway')
parameters.each do |key, value|
root.add_element("eway#{key}").text = value
end
xml.to_s
end
def message_from(message)
return '' if message.blank?
MESSAGES[message[0, 2]] || message
end
def purchase_url(cvn)
suffix = test? ? 'xmltest/testpage.asp' : 'xmlpayment.asp'
gateway_part = cvn ? 'gateway_cvn' : 'gateway'
"#{live_url}/#{gateway_part}/#{suffix}"
end
def refund_url
suffix = test? ? 'xmltest/refund_test.asp' : 'xmlpaymentrefund.asp'
"#{live_url}/gateway/#{suffix}"
end
MESSAGES = {
'00' => 'Transaction Approved',
'01' => 'Refer to Issuer',
'02' => 'Refer to Issuer, special',
'03' => 'No Merchant',
'04' => 'Pick Up Card',
'05' => 'Do Not Honour',
'06' => 'Error',
'07' => 'Pick Up Card, Special',
'08' => 'Honour With Identification',
'09' => 'Request In Progress',
'10' => 'Approved For Partial Amount',
'11' => 'Approved, VIP',
'12' => 'Invalid Transaction',
'13' => 'Invalid Amount',
'14' => 'Invalid Card Number',
'15' => 'No Issuer',
'16' => 'Approved, Update Track 3',
'19' => 'Re-enter Last Transaction',
'21' => 'No Action Taken',
'22' => 'Suspected Malfunction',
'23' => 'Unacceptable Transaction Fee',
'25' => 'Unable to Locate Record On File',
'30' => 'Format Error',
'31' => 'Bank Not Supported By Switch',
'33' => 'Expired Card, Capture',
'34' => 'Suspected Fraud, Retain Card',
'35' => 'Card Acceptor, Contact Acquirer, Retain Card',
'36' => 'Restricted Card, Retain Card',
'37' => 'Contact Acquirer Security Department, Retain Card',
'38' => 'PIN Tries Exceeded, Capture',
'39' => 'No Credit Account',
'40' => 'Function Not Supported',
'41' => 'Lost Card',
'42' => 'No Universal Account',
'43' => 'Stolen Card',
'44' => 'No Investment Account',
'51' => 'Insufficient Funds',
'52' => 'No Cheque Account',
'53' => 'No Savings Account',
'54' => 'Expired Card',
'55' => 'Incorrect PIN',
'56' => 'No Card Record',
'57' => 'Function Not Permitted to Cardholder',
'58' => 'Function Not Permitted to Terminal',
'59' => 'Suspected Fraud',
'60' => 'Acceptor Contact Acquirer',
'61' => 'Exceeds Withdrawal Limit',
'62' => 'Restricted Card',
'63' => 'Security Violation',
'64' => 'Original Amount Incorrect',
'66' => 'Acceptor Contact Acquirer, Security',
'67' => 'Capture Card',
'75' => 'PIN Tries Exceeded',
'82' => 'CVV Validation Error',
'90' => 'Cutoff In Progress',
'91' => 'Card Issuer Unavailable',
'92' => 'Unable To Route Transaction',
'93' => 'Cannot Complete, Violation Of The Law',
'94' => 'Duplicate Transaction',
'96' => 'System Error'
}
end
end
end