lib/active_merchant/billing/gateways/merchant_ware.rb in jelaniharris-activemerchant-1.24.1 vs lib/active_merchant/billing/gateways/merchant_ware.rb in jelaniharris-activemerchant-1.29.1
- old
+ new
@@ -1,105 +1,104 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class MerchantWareGateway < Gateway
- URL = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx'
-
+ self.live_url = self.test_url = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx'
+
self.supported_countries = ['US']
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
self.homepage_url = 'http://merchantwarehouse.com/merchantware'
self.display_name = 'MerchantWARE'
-
+
ENV_NAMESPACES = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
"xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/"
}
TX_NAMESPACE = "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail"
-
+
ACTIONS = {
:purchase => "IssueKeyedSale",
:authorize => "IssueKeyedPreAuth",
:capture => "IssuePostAuth",
:void => "IssueVoid",
:credit => "IssueKeyedRefund",
:reference_credit => "IssueRefundByReference"
}
-
+
# Creates a new MerchantWareGateway
- #
+ #
# The gateway requires that a valid login, password, and name be passed
# in the +options+ hash.
- #
+ #
# ==== Options
#
# * <tt>:login</tt> - The MerchantWARE SiteID.
# * <tt>:password</tt> - The MerchantWARE Key.
# * <tt>:name</tt> - The MerchantWARE Name.
def initialize(options = {})
requires!(options, :login, :password, :name)
- @options = options
super
end
# Authorize a credit card for a given amount.
- #
+ #
# ==== Parameters
# * <tt>money</tt> - The amount to be authorized as an Integer value in cents.
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
# * <tt>options</tt>
# * <tt>:order_id</tt> - A unique reference for this order (required).
- # * <tt>:billing_address</tt> - The billing address for the cardholder.
+ # * <tt>:billing_address</tt> - The billing address for the cardholder.
def authorize(money, credit_card, options = {})
request = build_purchase_request(:authorize, money, credit_card, options)
commit(:authorize, request)
end
-
+
# Authorize and immediately capture funds from a credit card.
- #
+ #
# ==== Parameters
# * <tt>money</tt> - The amount to be authorized as anInteger value in cents.
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
# * <tt>options</tt>
# * <tt>:order_id</tt> - A unique reference for this order (required).
# * <tt>:billing_address</tt> - The billing address for the cardholder.
def purchase(money, credit_card, options = {})
request = build_purchase_request(:purchase, money, credit_card, options)
commit(:purchase, request)
- end
+ end
# Capture authorized funds from a credit card.
- #
+ #
# ==== Parameters
# * <tt>money</tt> - The amount to be captured as anInteger value in cents.
# * <tt>authorization</tt> - The authorization string returned from the initial authorization.
def capture(money, authorization, options = {})
request = build_capture_request(:capture, money, authorization, options)
commit(:capture, request)
end
# Void a transaction.
- #
+ #
# ==== Parameters
# * <tt>authorization</tt> - The authorization string returned from the initial authorization or purchase.
def void(authorization, options = {})
reference, options[:order_id] = split_reference(authorization)
-
+
request = soap_request(:void) do |xml|
add_reference(xml, reference)
end
commit(:void, request)
end
-
+
# Refund an amount back a cardholder
- #
+ #
# ==== Parameters
#
# * <tt>money</tt> - The amount to be refunded as an Integer value in cents.
# * <tt>identification</tt> - The credit card you want to refund or the authorization for the existing transaction you are refunding.
# * <tt>options</tt>
# * <tt>:order_id</tt> - A unique reference for this order (required when performing a non-referenced credit)
def credit(money, identification, options = {})
- if identification.is_a?(String)
+ if identification.is_a?(String)
deprecated CREDIT_DEPRECATION_MESSAGE
refund(money, identification, options)
else
perform_credit(money, identification, options)
end
@@ -107,13 +106,13 @@
def refund(money, reference, options = {})
perform_reference_credit(money, reference, options)
end
-
+
private
-
+
def soap_request(action)
xml = Builder::XmlMarkup.new :indent => 2
xml.instruct!
xml.tag! "env:Envelope", ENV_NAMESPACES do
xml.tag! "env:Body" do
@@ -123,162 +122,162 @@
end
end
end
xml.target!
end
-
+
def build_purchase_request(action, money, credit_card, options)
requires!(options, :order_id)
-
+
request = soap_request(action) do |xml|
add_invoice(xml, options)
add_amount(xml, money)
add_credit_card(xml, credit_card)
add_address(xml, options)
end
end
-
+
def build_capture_request(action, money, identification, options)
reference, options[:order_id] = split_reference(identification)
-
+
request = soap_request(action) do |xml|
add_reference(xml, reference)
add_invoice(xml, options)
add_amount(xml, money)
end
end
-
+
def perform_reference_credit(money, identification, options)
reference, options[:order_id] = split_reference(identification)
request = soap_request(:reference_credit) do |xml|
add_reference(xml, reference)
add_invoice(xml, options)
add_amount(xml, money, "strOverrideAmount")
end
-
+
commit(:reference_credit, request)
end
-
+
def perform_credit(money, credit_card, options)
requires!(options, :order_id)
-
+
request = soap_request(:credit) do |xml|
add_invoice(xml, options)
add_amount(xml, money)
add_credit_card(xml, credit_card)
end
-
+
commit(:credit, request)
end
def add_credentials(xml)
xml.tag! "strSiteId", @options[:login]
xml.tag! "strKey", @options[:password]
xml.tag! "strName", @options[:name]
end
-
+
def expdate(credit_card)
year = sprintf("%.4i", credit_card.year)
month = sprintf("%.2i", credit_card.month)
"#{month}#{year[-2..-1]}"
end
-
+
def add_invoice(xml, options)
xml.tag! "strOrderNumber", options[:order_id].to_s.gsub(/[^\w]/, '').slice(0, 25)
end
-
+
def add_amount(xml, money, tag = "strAmount")
xml.tag! tag, amount(money)
end
def add_reference(xml, reference)
xml.tag! "strReferenceCode", reference
end
-
+
def add_address(xml, options)
if address = options[:billing_address] || options[:address]
xml.tag! "strAVSStreetAddress", address[:address1]
xml.tag! "strAVSZipCode", address[:zip]
end
end
-
+
def add_credit_card(xml, credit_card)
xml.tag! "strPAN", credit_card.number
xml.tag! "strExpDate", expdate(credit_card)
xml.tag! "strCardHolder", credit_card.name
xml.tag! "strCVCode", credit_card.verification_value if credit_card.verification_value?
end
-
+
def split_reference(reference)
reference.to_s.split(";")
end
-
+
def parse(action, data)
response = {}
xml = REXML::Document.new(data)
-
+
root = REXML::XPath.first(xml, "//#{ACTIONS[action]}Response/#{ACTIONS[action]}Result")
root.elements.each do |element|
response[element.name] = element.text
end
-
+
status, code, message = response["ApprovalStatus"].split(";")
response[:status] = status
-
- if response[:success] = status == "APPROVED"
+
+ if response[:success] = status == "APPROVED"
response[:message] = status
else
response[:message] = message
response[:failure_code] = code
end
- response
+ response
end
-
+
def parse_error(http_response)
response = {}
response[:http_code] = http_response.code
response[:http_message] = http_response.message
response[:success] = false
document = REXML::Document.new(http_response.body)
node = REXML::XPath.first(document, "//soap:Fault")
-
+
node.elements.each do |element|
response[element.name] = element.text
end
-
+
response[:message] = response["faultstring"].to_s.gsub("\n", " ")
response
rescue REXML::ParseException => e
response[:http_body] = http_response.body
response[:message] = "Failed to parse the failed response"
response
end
-
+
def commit(action, request)
begin
- data = ssl_post(URL, request,
+ data = ssl_post(self.live_url, request,
"Content-Type" => 'text/xml; charset=utf-8',
"SOAPAction" => "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail/#{ACTIONS[action]}"
)
response = parse(action, data)
rescue ActiveMerchant::ResponseError => e
response = parse_error(e.response)
end
-
- Response.new(response[:success], response[:message], response,
- :test => test?,
+
+ Response.new(response[:success], response[:message], response,
+ :test => test?,
:authorization => authorization_from(response),
:avs_result => { :code => response["AVSResponse"] },
:cvv_result => response["CVResponse"]
)
end
-
+
def authorization_from(response)
if response[:success]
[ response["ReferenceID"], response["OrderNumber"] ].join(";")
end
end