Payment Gateway testing using webmock

Testing the payment gateway involves lots of scenarios like what should happen if exception is raised while doing payment. To test this scenario we have to call payment gateway API and take response. But herein lies a problem. The test code you have written may work sometime and won’t work another time. The reason behind this failure is, whenever  you call payment gateway in quick succession, then gateway gives error. So, we can’t test payment scenarios by calling actual gateway API. How can we then test gateway integration? The answer is  stubbing the gateway requests using webmock.

Testing recurring payment with authorize.net

  1. For configure ‘webmock’ for test environment and do bundle install.
  2. Executes your controller specs. Anyway, specs will fail as we disable all real HTTP requests.
  3. Download the recurring payment response from authorize.net using curl like below:
curl -H 'Content-Type:text/xml' <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ARBCreateSubscriptionRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">\n  <merchantAuthentication>\n    <name>2ErYn5tb5X</name>\n    <transactionKey>75mhe6B5TLNwA47b</transactionKey>\n  </merchantAuthentication>\n  <subscription>\n    <paymentSchedule>\n      <interval>\n        <length>1</length>\n        <unit>months</unit>\n      </interval>\n      <startDate>2011-09-14</startDate>\n      <totalOccurrences>1</totalOccurrences>\n    </paymentSchedule>\n    <amount>10.00</amount>\n    <payment>\n      <creditCard>\n        <cardNumber>370000000000002</cardNumber>\n        <expirationDate>2011-21</expirationDate>\n      </creditCard>\n    </payment>\n    <billTo>\n      <firstName>Test</firstName>\n      <lastName>Account</lastName>\n      <company></company>\n      <address></address>\n      <city></city>\n      <state></state>\n      <zip></zip>\n      <country></country>\n    </billTo>\n  </subscription>\n</ARBCreateSubscriptionRequest>\n" https://apitest.authorize.net/xml/v1/request.api > success_response

This sends an XMLHttpPost request to https://apitest.authorize.net/xml/v1/request.api and copies the response to success_reponse file.

We now have response in  hand. Place this repsonse in spec/support/authotize.net directory. Now, we need to configure the response such a way that whenever we send recurring payment request it should return our downloaded response.

Create a file called payment.rb in spec/support directory.

    #spec/support/payment.rb
    require 'webmock/rspec'

    RSpec.configure do |config|
     VALID_CARD  = 370000000000002
     FIRST_NAME   = "test"
     LAST_NAME    = "account"
     EXPIRY_YEAR  = (Time.now.year + 10).to_s
     EXPIRY_MONTH = (Time.now.month + 1).to_s
     CVV = "123"

     config.fixture_path = "#{::Rails.root}/spec/fixtures"
     # configure test response for purchase and recurring payment
     authorize_net = config.fixture_path + '/webmock/authorize.net/'
     payment_responses = []
     Dir["#{authorize_net}/**/*"].each do |path|
       payment_responses << path
     end
     payment_gateway = "https://apitest.authorize.net/xml/v1/request.api"
     success_params = []

     # configure recurring payment request parameters with different values
     10.times do |i|
       amount = 5 * i

       # Stubbing request parameters with different values
       success_params << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ARBCreateSubscriptionRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">\n  <merchantAuthentication>\n    <name>2ErYn5tb5X</name>\n    <transactionKey>75mhe6B5TLNwA47b</transactionKey>\    n  </merchantAuthentication>\n  <subscription>\n    <paymentSchedule>\n      <interval>\n        <length>1</length>\n        <unit>months</unit>\n      </interval>\n      <startDate>#{(Date.today + 1.month).to_s(:db)}</startDate>\n      <totalOccurrences>1</to    talOccurrences>\n    </paymentSchedule>\n    <amount>#{amount}.00</amount>\n    <payment>\n      <creditCard>\n        <cardNumber>#{VALID_CARD}</cardNumber>\n        <expirationDate>#{EXPIRY_YEAR}-#{EXPIRY_MONTH}</expirationDate>\n      </creditCard>\n    </payment>\n    <billTo>\n      <firstName>#{FIRST_NAME}</firstName>\n      <lastName>#{LAST_NAME}</lastName>\n      <company></company>\n      <address></address>\n      <city></city>\n      <state></state>\n      <zip></zip>\n      <country></country>\n    </billTo>\n  </subscription>\n</ARBCreateSubscriptionRequest>\n"

       config.around(:each) do |example|
         success_params.each { |parameter| WebMock::API.stub_request(:post, payment_gateway).
                with(:body => parameter,
                     :headers => {'Accept'=>'*/*', 'Content-Type'=>'text/xml'}).
                to_return(:status => 200,
                          :body => File.new(payment_responses[0]), :headers => {})}
       end
     end
    end

    WebMock.disable_net_connect!(:allow_localhost => true)
    example.call
    WebMock.allow_net_connect!

I think you understand how to stub recurring payment requests. Now we will see another example.

Purchase using authorize.net

As usual download purchase response from authorize.net like below:

   curl -H "Content-Type:application/x-www-form-urlencoded" -d login=2ErYn5tb5X -d key=75mhe6B5TLNwA47b -d key=x_type=AUTH_CAPTURE -d x_encap_char=%24 -d x_first_name=test -d x_invoice_num= -d x_last_name=account -d x_tran_key=75mhe6B5TLNwA47b -d x_card_num=370000000000002 -d x_version=3.1 -d x_relay_response=FALSE -d x_exp_date=1021 -d x_login=2ErYn5tb5X -d x_delim_data=TRUE -d x_description= -d x_card_code=123 -d x_amount=30.00 -d x_test_request=FALSE -d x_delim_char=%2C https://test.authorize.net/gateway/transact.dll > purchase
 

It will send as HTTP Post request to https://test.authorize.net/gateway/transact.dll and copy the response into purchase file. Place this file in spec/fixtures/authorize.net directory.

Now stub the purchase request:

   #spec/support/payment.rb
   stub_request(:post, "https://test.authorize.net/gateway/transact.dll")
        with(:body => /^[A-Za-z&_0-9#%.=]*$/,
             :headers => {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded'}).
        to_return(:status => 200, :body => File.new(payment_responses[1]), :headers => {})

Note: We can’t stub request with different parameters as it is a HTTP Post request. So match request parameters against regular expression.

Hope this helps! Please let me know if you see any complex payment scenarios. I will give a shot!.

Advertisements

About Siva Gollapalli

Being a programmer is a huge possibility to learn
This entry was posted in Ruby on Rails, Tutorials and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s