Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add Gateway for Moneris US #313

Merged
merged 1 commit into from

2 participants

@eddanger

No description provided.

@ntalbott
Owner

Is Moneris US a completely different gateway than the other Moneris gateway we already support?

@eddanger

Yes, it is a completely different gateway.

@ntalbott
Owner

I'm getting errors when running the unit tests:

  1) Error:
test_capture_is_valid_xml(MonerisUsTest):
NoMethodError: undefined method `each' for nil:NilClass
    /Users/ntalbott/git/active_merchant/lib/active_merchant/billing/gateways/moneris_us.rb:172:in `post_data'
    ./test/unit/gateways/moneris_us_test.rb:94:in `send'
    ./test/unit/gateways/moneris_us_test.rb:94:in `test_capture_is_valid_xml'
    /Users/ntalbott/.rbenv/versions/1.8.7-p352/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `__send__'
    /Users/ntalbott/.rbenv/versions/1.8.7-p352/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `run'

  2) Error:
test_purchase_is_valid_xml(MonerisUsTest):
NoMethodError: undefined method `each' for nil:NilClass
    /Users/ntalbott/git/active_merchant/lib/active_merchant/billing/gateways/moneris_us.rb:172:in `post_data'
    ./test/unit/gateways/moneris_us_test.rb:79:in `send'
    ./test/unit/gateways/moneris_us_test.rb:79:in `test_purchase_is_valid_xml'
    /Users/ntalbott/.rbenv/versions/1.8.7-p352/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `__send__'
    /Users/ntalbott/.rbenv/versions/1.8.7-p352/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `run'

I'm also getting a failure when running remote tests:

  1) Failure:
test_successful_authorization_and_void(MonerisUsRemoteTest)
    [test/remote/gateways/remote_moneris_us_test.rb:50:in `test_successful_authorization_and_void'
     /Users/ntalbott/.rbenv/versions/1.8.7-p352/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `__send__'
     /Users/ntalbott/.rbenv/versions/1.8.7-p352/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `run']:
Response failed: #<ActiveMerchant::Billing::Response:0x10a6f5440 @authorization=nil, @success=nil, @cvv_result={"code"=>nil, "message"=>nil}, @params={"trans_id"=>nil, "ticket"=>nil, "card_type"=>nil, "response_code"=>nil, "timed_out"=>nil, "iso"=>nil, "trans_time"=>nil, "receipt_id"=>nil, "trans_date"=>nil, "complete"=>false, "trans_amount"=>nil, "trans_type"=>nil, "auth_code"=>nil, "reference_num"=>nil, "bank_totals"=>nil, "message"=>"Invalid follow_up_amount number"}, @fraud_review=nil, @message="Invalid follow_up_amount number", @avs_result={"code"=>nil, "postal_match"=>nil, "street_match"=>nil, "message"=>nil}, @test=true>.
<nil> is not true.

The code looks solid, so if you can get me fixes for the tests, I'll be happy to merge. Thanks!

@eddanger

Hi @ntalbott I've fixed up the Unit and Remote tests.

I also fixed a failing test for the Moneris Canada gateway. Recent changes to Moneris no longer allow a void on a preauthorization. You must capture a $0.00 on the auth to in effect void it.

The Moneris Canada remote test fix is also in this pull request if that is okay.

@ntalbott
Owner

Actually would be best to split the void change into another PR; I think we'll actually want to abstract away the zero-dollar capture behind the void method.

@eddanger

One issue is the void method behaves differently depending on whether the original transaction was an auth or purchase/capture. And we only know the authorization of the transaction, not the type. One solution may be to create a void_authorization method that does the capture of $0.00.

Also, is it possible to remove/change a commit from a pull request?

@eddanger

Another possibility is to remove that test altogether since only captures and purchases can be voided.

@ntalbott
Owner

The PR is based on the branch, so if you force push a different set of commits into the branch, the PR will update.

If the type of the transaction matters, maybe we should add additional info to the authorization string to indicate that?

@eddanger

Done, void the authorization commit removed. I'll make a new pull request for these changes.

@ntalbott
Owner

Still getting a remote failure:

  1) Failure:
test_successful_authorization_and_void(MonerisUsRemoteTest)
    [test/remote/gateways/remote_moneris_us_test.rb:50:in `test_successful_authorization_and_void'
     /Users/ntalbott/.rbenv/versions/1.8.7-p358/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `__send__'
     /Users/ntalbott/.rbenv/versions/1.8.7-p358/lib/ruby/gems/1.8/gems/mocha-0.9.12/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:22:in `run']:
Response failed: #<ActiveMerchant::Billing::Response:0x106929210 @fraud_review=nil, @avs_result={"street_match"=>nil, "message"=>nil, "postal_match"=>nil, "code"=>nil}, @test=true, @message="Invalid follow_up_amount number", @authorization=nil, @success=nil, @cvv_result={"message"=>nil, "code"=>nil}, @params={"message"=>"Invalid follow_up_amount number", "bank_totals"=>nil, "receipt_id"=>nil, "trans_type"=>nil, "trans_date"=>nil, "reference_num"=>nil, "trans_amount"=>nil, "response_code"=>nil, "timed_out"=>nil, "iso"=>nil, "auth_code"=>nil, "complete"=>false, "ticket"=>nil, "trans_time"=>nil, "card_type"=>nil, "trans_id"=>nil}>.
<nil> is not true.
@eddanger

Fix added back in (curses that force push!)

@ntalbott
Owner

Working beautifully, just one last request: can you squash this all into a single commit? I'll merge ASAP once I have that. Thanks!

@eddanger eddanger Add Gateway for Moneris US
Fix unit tests for Moneris US XML

Moneris US cannot void a preauthorization
Bring this in line with the way Moneris Canada does things.
2faffc1
@eddanger

Hi, @ntalbott squashed them into a single commit! Interesting. I have never done something like that before, and was just wondering what the benefit is?

@ntalbott
Owner

With a large open source project with a lot of contributors, it's really handy to keep the history as clean as possible. Makes it much easier to see at a glance what's gone on and who has done what.

@ntalbott ntalbott merged commit a63697a into activemerchant:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 23, 2012
  1. @eddanger

    Add Gateway for Moneris US

    eddanger authored
    Fix unit tests for Moneris US XML
    
    Moneris US cannot void a preauthorization
    Bring this in line with the way Moneris Canada does things.
This page is out of date. Refresh to see the latest.
View
1  README.md
@@ -111,6 +111,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [MerchantWare](http://merchantwarehouse.com/merchantware) - US
* [Modern Payments](http://www.modpay.com) - US
* [Moneris](http://www.moneris.com/) - CA
+* [Moneris US](http://www.monerisusa.com/) - US
* [NABTransact](http://www.nab.com.au/nabtransact/) - AU
* [Netaxept](http://www.betalingsterminal.no/Netthandel-forside) - NO, DK, SE, FI
* [NetRegistry](http://www.netregistry.com.au) - AU
View
211 lib/active_merchant/billing/gateways/moneris_us.rb
@@ -0,0 +1,211 @@
+require 'rexml/document'
+
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+
+ # To learn more about the Moneris (US) gateway, please contact
+ # ussales@moneris.com for a copy of their integration guide. For
+ # information on remote testing, please see "Test Environment Penny Value
+ # Response Table", and "Test Environment eFraud (AVS and CVD) Penny
+ # Response Values", available at Moneris' {eSelect Plus Documentation
+ # Centre}[https://www3.moneris.com/connect/en/documents/index.html].
+ class MonerisUsGateway < Gateway
+ TEST_URL = 'https://esplusqa.moneris.com/gateway_us/servlet/MpgRequest'
+ LIVE_URL = 'https://esplus.moneris.com/gateway_us/servlet/MpgRequest'
+
+ self.supported_countries = ['US']
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover]
+ self.homepage_url = 'http://www.monerisusa.com/'
+ self.display_name = 'Moneris (US)'
+
+ # login is your Store ID
+ # password is your API Token
+ def initialize(options = {})
+ requires!(options, :login, :password)
+ @options = { :crypt_type => 7 }.update(options)
+ super
+ end
+
+ # Referred to as "PreAuth" in the Moneris integration guide, this action
+ # verifies and locks funds on a customer's card, which then must be
+ # captured at a later date.
+ #
+ # Pass in +order_id+ and optionally a +customer+ parameter.
+ def authorize(money, creditcard, options = {})
+ debit_commit 'us_preauth', money, creditcard, options
+ end
+
+ # This action verifies funding on a customer's card, and readies them for
+ # deposit in a merchant's account.
+ #
+ # Pass in <tt>order_id</tt> and optionally a <tt>customer</tt> parameter
+ def purchase(money, creditcard, options = {})
+ debit_commit 'us_purchase', money, creditcard, options
+ end
+
+ # This method retrieves locked funds from a customer's account (from a
+ # PreAuth) and prepares them for deposit in a merchant's account.
+ #
+ # Note: Moneris requires both the order_id and the transaction number of
+ # the original authorization. To maintain the same interface as the other
+ # gateways the two numbers are concatenated together with a ; separator as
+ # the authorization number returned by authorization
+ def capture(money, authorization, options = {})
+ commit 'us_completion', crediting_params(authorization, :comp_amount => amount(money))
+ end
+
+ # Voiding requires the original transaction ID and order ID of some open
+ # transaction. Closed transactions must be refunded. Note that the only
+ # methods which may be voided are +capture+ and +purchase+.
+ #
+ # Concatenate your transaction number and order_id by using a semicolon
+ # (';'). This is to keep the Moneris interface consistent with other
+ # gateways. (See +capture+ for details.)
+ def void(authorization, options = {})
+ commit 'us_purchasecorrection', crediting_params(authorization)
+ end
+
+ # Performs a refund. This method requires that the original transaction
+ # number and order number be included. Concatenate your transaction
+ # number and order_id by using a semicolon (';'). This is to keep the
+ # Moneris interface consistent with other gateways. (See +capture+ for
+ # details.)
+ def credit(money, authorization, options = {})
+ deprecated CREDIT_DEPRECATION_MESSAGE
+ refund(money, authorization, options)
+ end
+
+ def refund(money, authorization, options = {})
+ commit 'us_refund', crediting_params(authorization, :amount => amount(money))
+ end
+
+ def test?
+ @options[:test] || super
+ end
+ private # :nodoc: all
+
+ def expdate(creditcard)
+ sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
+ end
+
+ def debit_commit(commit_type, money, creditcard, options)
+ requires!(options, :order_id)
+ commit(commit_type, debit_params(money, creditcard, options))
+ end
+
+ # Common params used amongst the +purchase+ and +authorization+ methods
+ def debit_params(money, creditcard, options = {})
+ {
+ :order_id => options[:order_id],
+ :cust_id => options[:customer],
+ :amount => amount(money),
+ :pan => creditcard.number,
+ :expdate => expdate(creditcard),
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
+ }
+ end
+
+ # Common params used amongst the +credit+, +void+ and +capture+ methods
+ def crediting_params(authorization, options = {})
+ {
+ :txn_number => split_authorization(authorization).first,
+ :order_id => split_authorization(authorization).last,
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
+ }.merge(options)
+ end
+
+ # Splits an +authorization+ param and retrives the order id and
+ # transaction number in that order.
+ def split_authorization(authorization)
+ if authorization.nil? || authorization.empty? || authorization !~ /;/
+ raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
+ else
+ authorization.split(';')
+ end
+ end
+
+ def commit(action, parameters = {})
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters)))
+
+ Response.new(successful?(response), message_from(response[:message]), response,
+ :test => test?,
+ :authorization => authorization_from(response)
+ )
+ end
+
+ # Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
+ def authorization_from(response = {})
+ if response[:trans_id] && response[:receipt_id]
+ "#{response[:trans_id]};#{response[:receipt_id]}"
+ end
+ end
+
+ # Tests for a successful response from Moneris' servers
+ def successful?(response)
+ response[:response_code] &&
+ response[:complete] &&
+ (0..49).include?(response[:response_code].to_i)
+ end
+
+ def parse(xml)
+ response = { :message => "Global Error Receipt", :complete => false }
+ hashify_xml!(xml, response)
+ response
+ end
+
+ def hashify_xml!(xml, response)
+ xml = REXML::Document.new(xml)
+ return if xml.root.nil?
+ xml.elements.each('//receipt/*') do |node|
+ response[node.name.underscore.to_sym] = normalize(node.text)
+ end
+ end
+
+ def post_data(action, parameters = {})
+ xml = REXML::Document.new
+ root = xml.add_element("request")
+ root.add_element("store_id").text = options[:login]
+ root.add_element("api_token").text = options[:password]
+ transaction = root.add_element(action)
+
+ # Must add the elements in the correct order
+ actions[action].each do |key|
+ transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
+ end
+
+ xml.to_s
+ end
+
+ def message_from(message)
+ return 'Unspecified error' if message.blank?
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
+ end
+
+ # Make a Ruby type out of the response string
+ def normalize(field)
+ case field
+ when "true" then true
+ when "false" then false
+ when '', "null" then nil
+ else field
+ end
+ end
+
+ def actions
+ {
+ "us_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
+ "us_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
+ "us_refund" => [:order_id, :amount, :txn_number, :crypt_type],
+ "us_ind_refund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
+ "us_completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
+ "us_purchasecorrection" => [:order_id, :txn_number, :crypt_type],
+ "us_cavv_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
+ "us_cavv_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
+ "us_batchcloseall" => [],
+ "us_opentotals" => [:ecr_number],
+ "us_batchclose" => [:ecr_number]
+ }
+ end
+ end
+ end
+end
View
4 test/fixtures.yml
@@ -168,6 +168,10 @@ moneris:
login: store1
password: yesguy
+moneris_us:
+ login: monusqa002
+ password: qatoken
+
#Working credentials, no need to replace
nab_transact:
login: ABC0001
View
84 test/remote/gateways/remote_moneris_us_test.rb
@@ -0,0 +1,84 @@
+require 'test_helper'
+
+class MonerisUsRemoteTest < Test::Unit::TestCase
+ def setup
+ Base.mode = :test
+
+ @gateway = MonerisUsGateway.new(fixtures(:moneris_us))
+ @amount = 100
+ @credit_card = credit_card('4242424242424242')
+ @options = {
+ :order_id => generate_unique_id,
+ :billing_address => address,
+ :description => 'Store Purchase'
+ }
+ end
+
+ def test_successful_purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal 'Approved', response.message
+ assert_false response.authorization.blank?
+ end
+
+ def test_successful_authorization
+ response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert_false response.authorization.blank?
+ end
+
+ def test_failed_authorization
+ response = @gateway.authorize(105, @credit_card, @options)
+ assert_failure response
+ end
+
+ def test_successful_authorization_and_capture
+ response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert response.authorization
+
+ response = @gateway.capture(@amount, response.authorization)
+ assert_success response
+ end
+
+ def test_successful_authorization_and_void
+ response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert response.authorization
+
+ # Moneris cannot void a preauthorization
+ # You must capture the auth transaction with an amount of $0.00
+ void = @gateway.capture(0, response.authorization)
+ assert_success void
+ end
+
+ def test_successful_purchase_and_void
+ purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success purchase
+
+ void = @gateway.void(purchase.authorization)
+ assert_success void
+ end
+
+ def test_failed_purchase_and_void
+ purchase = @gateway.purchase(101, @credit_card, @options)
+ assert_failure purchase
+
+ void = @gateway.void(purchase.authorization)
+ assert_failure void
+ end
+
+ def test_successful_purchase_and_credit
+ purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success purchase
+
+ credit = @gateway.credit(@amount, purchase.authorization)
+ assert_success credit
+ end
+
+ def test_failed_purchase_from_error
+ assert response = @gateway.purchase(150, @credit_card, @options)
+ assert_failure response
+ assert_equal 'Declined', response.message
+ end
+end
View
3  test/unit/base_test.rb
@@ -11,7 +11,8 @@ def teardown
def test_should_return_a_new_gateway_specified_by_symbol_name
assert_equal BogusGateway, Base.gateway(:bogus)
- assert_equal MonerisGateway, Base.gateway(:moneris)
+ assert_equal MonerisGateway, Base.gateway(:moneris)
+ assert_equal MonerisUsGateway, Base.gateway(:moneris_us)
assert_equal AuthorizeNetGateway, Base.gateway(:authorize_net)
assert_equal UsaEpayGateway, Base.gateway(:usa_epay)
assert_equal LinkpointGateway, Base.gateway(:linkpoint)
View
172 test/unit/gateways/moneris_us_test.rb
@@ -0,0 +1,172 @@
+require 'test_helper'
+
+class MonerisUsTest < Test::Unit::TestCase
+ def setup
+ Base.mode = :test
+
+ @gateway = MonerisUsGateway.new(
+ :login => 'monusqa002',
+ :password => 'qatoken'
+ )
+
+ @amount = 100
+ @credit_card = credit_card('4242424242424242')
+ @options = { :order_id => '1', :billing_address => address }
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+
+ assert response = @gateway.authorize(100, @credit_card, @options)
+ assert_success response
+ assert_equal '58-0_3;1026.1', response.authorization
+ end
+
+ def test_failed_purchase
+ @gateway.expects(:ssl_post).returns(failed_purchase_response)
+
+ assert response = @gateway.authorize(100, @credit_card, @options)
+ assert_failure response
+ end
+
+ def test_deprecated_credit
+ @gateway.expects(:ssl_post).with(anything, regexp_matches(/txn_number>123<\//), anything).returns("")
+ @gateway.expects(:parse).returns({})
+ assert_deprecation_warning(Gateway::CREDIT_DEPRECATION_MESSAGE, @gateway) do
+ @gateway.credit(@amount, "123;456", @options)
+ end
+ end
+
+ def test_refund
+ @gateway.expects(:ssl_post).with(anything, regexp_matches(/txn_number>123<\//), anything).returns("")
+ @gateway.expects(:parse).returns({})
+ @gateway.refund(@amount, "123;456", @options)
+ end
+
+ def test_amount_style
+ assert_equal '10.34', @gateway.send(:amount, 1034)
+
+ assert_raise(ArgumentError) do
+ @gateway.send(:amount, '10.34')
+ end
+ end
+
+ def test_purchase_is_valid_xml
+
+ params = {
+ :order_id => "order1",
+ :amount => "1.01",
+ :pan => "4242424242424242",
+ :expdate => "0303",
+ :crypt_type => 7,
+ }
+
+ assert data = @gateway.send(:post_data, 'us_preauth', params)
+ assert REXML::Document.new(data)
+ assert_equal xml_capture_fixture.size, data.size
+ end
+
+ def test_purchase_is_valid_xml
+
+ params = {
+ :order_id => "order1",
+ :amount => "1.01",
+ :pan => "4242424242424242",
+ :expdate => "0303",
+ :crypt_type => 7,
+ }
+
+ assert data = @gateway.send(:post_data, 'us_purchase', params)
+ assert REXML::Document.new(data)
+ assert_equal xml_purchase_fixture.size, data.size
+ end
+
+ def test_capture_is_valid_xml
+
+ params = {
+ :order_id => "order1",
+ :amount => "1.01",
+ :pan => "4242424242424242",
+ :expdate => "0303",
+ :crypt_type => 7,
+ }
+
+ assert data = @gateway.send(:post_data, 'us_preauth', params)
+ assert REXML::Document.new(data)
+ assert_equal xml_capture_fixture.size, data.size
+ end
+
+ def test_supported_countries
+ assert_equal ['US'], MonerisUsGateway.supported_countries
+ end
+
+ def test_supported_card_types
+ assert_equal [:visa, :master, :american_express, :diners_club, :discover], MonerisUsGateway.supported_cardtypes
+ end
+
+ def test_should_raise_error_if_transaction_param_empty_on_credit_request
+ [nil, '', '1234'].each do |invalid_transaction_param|
+ assert_raise(ArgumentError) { @gateway.void(invalid_transaction_param) }
+ end
+ end
+
+ private
+ def successful_purchase_response
+ <<-RESPONSE
+<?xml version="1.0"?>
+<response>
+ <receipt>
+ <ReceiptId>1026.1</ReceiptId>
+ <ReferenceNum>661221050010170010</ReferenceNum>
+ <ResponseCode>027</ResponseCode>
+ <ISO>01</ISO>
+ <AuthCode>013511</AuthCode>
+ <TransTime>18:41:13</TransTime>
+ <TransDate>2008-01-05</TransDate>
+ <TransType>00</TransType>
+ <Complete>true</Complete>
+ <Message>APPROVED * =</Message>
+ <TransAmount>1.00</TransAmount>
+ <CardType>V</CardType>
+ <TransID>58-0_3</TransID>
+ <TimedOut>false</TimedOut>
+ </receipt>
+</response>
+
+ RESPONSE
+ end
+
+ def failed_purchase_response
+ <<-RESPONSE
+<?xml version="1.0"?>
+<response>
+ <receipt>
+ <ReceiptId>1026.1</ReceiptId>
+ <ReferenceNum>661221050010170010</ReferenceNum>
+ <ResponseCode>481</ResponseCode>
+ <ISO>01</ISO>
+ <AuthCode>013511</AuthCode>
+ <TransTime>18:41:13</TransTime>
+ <TransDate>2008-01-05</TransDate>
+ <TransType>00</TransType>
+ <Complete>true</Complete>
+ <Message>DECLINED * =</Message>
+ <TransAmount>1.00</TransAmount>
+ <CardType>V</CardType>
+ <TransID>97-2-0</TransID>
+ <TimedOut>false</TimedOut>
+ </receipt>
+</response>
+
+ RESPONSE
+ end
+
+ def xml_purchase_fixture
+ '<request><store_id>monusqa002</store_id><api_token>qatoken</api_token><us_purchase><amount>1.01</amount><pan>4242424242424242</pan><expdate>0303</expdate><crypt_type>7</crypt_type><order_id>order1</order_id></us_purchase></request>'
+ end
+
+ def xml_capture_fixture
+ '<request><store_id>monusqa002</store_id><api_token>qatoken</api_token><us_preauth><amount>1.01</amount><pan>4242424242424242</pan><expdate>0303</expdate><crypt_type>7</crypt_type><order_id>order1</order_id></us_preauth></request>'
+ end
+
+end
Something went wrong with that request. Please try again.