require 'nokogiri'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class CreditcallGateway < Gateway
self.test_url = 'https://test.cardeasexml.com/generic.cex'
self.live_url = 'https://live.cardeasexml.com/'
self.supported_countries = ['US']
self.default_currency = 'USD'
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
self.homepage_url = 'https://www.creditcall.com'
self.display_name = 'Creditcall'
def initialize(options={})
requires!(options, :terminal_id, :transaction_key)
super
end
def purchase(money, payment_method, options={})
multi_response = MultiResponse.run do |r|
r.process { authorize(money, payment_method, options) }
r.process { capture(money, r.authorization, options) }
end
Response.new(
multi_response.primary_response.success?,
multi_response.primary_response.message,
multi_response.primary_response.params,
authorization: multi_response.responses.first.authorization,
test: test?
)
end
def authorize(money, payment_method, options={})
request = build_xml_request do |xml|
add_transaction_details(xml, money, nil, "Auth", options)
add_terminal_details(xml, options)
add_card_details(xml, payment_method, options)
end
commit(request)
end
def capture(money, authorization, options={})
request = build_xml_request do |xml|
add_transaction_details(xml, money, authorization, "Conf", options)
add_terminal_details(xml, options)
end
commit(request)
end
def refund(money, authorization, options={})
request = build_xml_request do |xml|
add_transaction_details(xml, money, authorization, "Refund", options)
add_terminal_details(xml, options)
end
commit(request)
end
def void(authorization, options={})
request = build_xml_request do |xml|
add_transaction_details(xml, nil, authorization, "Void", options)
add_terminal_details(xml, options)
end
commit(request)
end
def verify(credit_card, options={})
MultiResponse.run(:use_first_response) do |r|
r.process { authorize(100, credit_card, options) }
r.process(:ignore_result) { void(r.authorization, options) }
end
end
def supports_scrubbing?
true
end
def scrub(transcript)
transcript.
gsub(%r(().+?())i, '\1[FILTERED]\2').
gsub(%r(().+?())i, '\1[FILTERED]\2').
gsub(%r(().+?())i, '\1[FILTERED]\2')
end
private
def build_xml_request
builder = Nokogiri::XML::Builder.new do |xml|
xml.Request(type: "CardEaseXML", version: "1.0.0") do
yield(xml)
end
end
builder.to_xml
end
def add_transaction_details(xml, amount, authorization, type, options={})
xml.TransactionDetails do
xml.MessageType type
xml.Amount(unit: "Minor"){ xml.text(amount) } if amount
xml.CardEaseReference authorization if authorization
xml.VoidReason "01" if type == "Void"
end
end
def add_terminal_details(xml, options={})
xml.TerminalDetails do
xml.TerminalID @options[:terminal_id]
xml.TransactionKey @options[:transaction_key]
xml.Software(version: "SoftwareVersion"){ xml.text("SoftwareName") }
end
end
def add_card_details(xml, payment_method, options={})
xml.CardDetails do
xml.Manual(type: "cnp") do
xml.PAN payment_method.number
xml.ExpiryDate exp_date(payment_method)
xml.CSC payment_method.verification_value
end
if address = options[:billing_address]
xml.AdditionalVerification do
xml.Address address[:address1]
xml.Zip address[:zip]
end
end
end
end
def exp_date(payment_method)
"#{format(payment_method.year, :two_digits)}#{format(payment_method.month, :two_digits)}"
end
def parse(body)
response = {}
xml = Nokogiri::XML(body)
node = xml.xpath("//Response/TransactionDetails")
node.children.each do |childnode|
response[childnode.name] = childnode.text
end
node = xml.xpath("//Response/Result")
node.children.each do |childnode|
if childnode.elements.empty?
response[childnode.name] = childnode.text
else
childnode_to_response(response, childnode)
end
end
response
end
def childnode_to_response(response, childnode)
childnode.elements.each do |element|
if element.name == "Error"
response["ErrorCode"] = element.attr("code")
response["ErrorMessage"] = element.text
else
response[element.name] = element.text
end
end
end
def commit(parameters)
response = parse(ssl_post(url, parameters))
Response.new(
success_from(response),
message_from(response),
response,
authorization: authorization_from(response),
avs_result: AVSResult.new(code: response["some_avs_response_key"]),
cvv_result: CVVResult.new(response["some_cvv_response_key"]),
test: test?
)
end
def url
test? ? test_url : live_url
end
def success_from(response)
response["LocalResult"] == "0" || response["LocalResult"] == "00"
end
def message_from(response)
if success_from(response)
"Succeeded"
else
response["ErrorMessage"]
end
end
def authorization_from(response)
response["CardEaseReference"]
end
end
end
end