ASP 101 - Active Server Pages 101 - Web06
The Place ASP Developers Go!



Windows Technology Windows Technology
15 Seconds
4GuysFromRolla.com
ASP 101
ASP Wire
VB Forums
VB Wire
WinDrivers.com
internet.commerce internet.commerce
Partners & Affiliates
ASP 101 is an
internet.com site
ASP 101 is an internet.com site
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

ASP 101 News Flash ASP 101 News Flash



 Top ASP 101 Stories Top ASP 101 Stories
What is ASP?
VBScript Classes: Part 1 of N
Migrating to ASP.NET

QUICK TIP:
Single Quotes Work Fine With ADO
Show All Tips >>
ASP 101 RSS Feed ASP 101 Updates


Using ASP and XMLHTTP to Talk to Authorize.Net

Dan Hounshell

Introduction

Recently I found myself putting together an Authorize.Net implementation for a client. For those who do not know, Authorize.Net is a payment processing gateway similar to Verisign's Payflow Pro or the almost completely departed CyberCash's CashRegister. Authorize.Net offers several different products and services ranging from a complete virtual terminal to payment forms. Unlike several other gateways, the developer has the option of how to implement Authorize.Net's services. You can simply send the user to a form on Authorize.Net's site (what they call WebLink), you can post your form to a page at Authorize.Net's site that will grab a thank you page that you specify from your site and display to your users (what they call Relay Response), or you can use 3rd party software to post to their server and get the return values and then do what you need to in your script (what they call Direct Response).

Slow Out of the Gate

I have implemented CyberCash and Verisign's products several times before, but I had never done a project with Authorize.Net. Several months ago in preparation for the payment portion of the project I am working on, I went to their site and found that similar to other payment gateways they had a component, AuthNetSSLConnect, that you could download and install, which could be used for passing your data to their site and getting the return values. Unfortunately, when I returned last week to gather all the details, I realized that they no longer support the product and refer you to 3rd party solutions instead. After searching the Internet for several hours and some of my favorite component sites, I realized that if I wanted to use someone's "3rd party solution" I was either going to have to tell my client that I needed them to dish out some more money (which I'd already done several times recently and was leery about doing again) or I could shell out the dough myself (which was definitely not going to happen).

I went ahead and installed the version of AuthNetSSLConnect that I had downloaded previously hoping that it would still work. After checking out the documentation that came with it and comparing it to the newest Developer's Guide from the site, it looked like I was in luck. Alas, it was not meant to be and I got "memory out of range" errors when I ran it. I was ready to give up and try something else.

Looks Promising? No it doesn't.

I thought I might try using the Relay Response that Authorize.Net offered and found that if you pass all the required parameters - credit card number, expiration date, amount, etc. - the user would not even be shown any forms from Authorize.Net's site, but instead sent directly to the thank you page after they processed the payment information. Worked well as far as I was concerned. I did have a problem with it, though. Instead of redirecting them to your payment page they instead grab your page and display it from their site. Yes, any code in the page is executed (like storing the information into a database), but what you are left with is the user's browser open with a page served from the Authorize.Net site. I'm a smart guy and I probably could have figured out a way to make it work, like by using JavaScript to redirect after a few seconds or placing a link back to the client's site, but at the time I didn't want to be encumbered with the mess. Plus with the applications that I am doing I wanted a simple page that I could use as an include file that I could drop into any form handler page where I needed it and it would work seamlessly into the process.

A Fresh Start

I was back to figuring out a way to post to their site from within my asp page and getting the return values all in the same script. I knew that I could find a simple component out there to do it or I would just write one of my own. All of a sudden it hit me - I remembered seeing some code for utilizing PayPal's direct response where the author was used Microsoft's XMLHTTP to pass data to Paypal and get the return values.

I knew that Authorize.Net wasn't supporting XML yet, but I figured I would take a look at it anyway, maybe I would learn a thing or two or I could make it fit. After playing around or awhile I tested to see if Authorize.Net would take the values in the query string rather than in the content as a "POST" and it would. I was halfway there. An hour and a couple of cups of coffee later and I found that I could pass the required values in the query string, send an empty string with the Send method (normally used for sending XML), and when setting the proper parameters Authorize.net would send back the response which I could assign to a variable with the XMLHTTP's responseText value. After some simple string manipulation and error checking I was in business.

Following are code samples similar to what I did. The form page is based on the sample scripts I initially downloaded with the AuthNetSSLConnect file.

FORM PAGE
<HTML>
<BODY>
<FORM METHOD=post ACTION="orderScript.asp">
Description: <INPUT name=x_Description value="Qty 24 - Yellow Note Pads"><br>
Amount: <INPUT name=x_Amount value="4.95"><br>
Credit Card Number: <INPUT name=x_Card_Num value="4111111111111111"><br>
Expiration Date: <INPUT name=x_Exp_Date value="102003"><br>
First Name: <INPUT name=x_First_Name value="Fred"><br>
Last Name: <INPUT name=x_Last_Name value="Consumer"><br>
Address: <INPUT name=x_Address value="1500 N. Scenic Dr."><br>
City: <INPUT name=x_City value="Hollywood"><br>
State: <INPUT name=x_State value="CA"><br>
Zip Code: <INPUT name=x_ZIP value="90201"><br>
Phone: <INPUT name=x_Phone value="800-555-1212"><br>
Fax: <INPUT name=x_Fax value="800-555-1213"><br>
Email: <INPUT name=x_Email value="fred@testmail.com"><br>
<INPUT type=submit value=Submit name=submit>
</FORM>
</BODY>
</HTML>

Handler Page
<HTML>
<BODY>
<%
'First enter our loginID
PostData = "x_Login=testdrive"        'test account for Authorize.Net
PostData = PostData & "&x_Version=3.0"
PostData = PostData & "&x_Test_Request=TRUE"   'since we are testing
PostData = PostData & "&x_ADC_Delim_Data=TRUE" 'we want comma delimited
PostData = PostData & "&x_ADC_URL=FALSE"       'do not want to redirect
'Now add the form fields
PostData = PostData & "&x_Card_Num=" & Request.Form("x_Card_Num") & ""
PostData = PostData & "&x_Exp_Date=" & Request.Form("x_Exp_Date") & ""
PostData = PostData & "&x_Description=" & Request.Form("x_Description") & ""
PostData = PostData & "&x_Amount=" & Request.Form("x_Amount") & ""
PostData = PostData & "&x_First_Name=" & Request.Form("x_First_Name") & ""
PostData = PostData & "&x_Last_Name=" & Request.Form("x_Last_Name") & ""
PostData = PostData & "&x_company=" & Request.Form("x_company") & ""
PostData = PostData & "&x_Address=" & Request.Form("x_Address") & ""
PostData = PostData & "&x_City=" & Request.Form("x_City") & ""
PostData = PostData & "&x_State=" & Request.Form("x_State") & ""
PostData = PostData & "&x_ZIP=" & Request.Form("x_ZIP") & ""
PostData = PostData & "&x_Phone=" & Request.Form("x_Phone") & ""
PostData = PostData & "&x_Fax=" & Request.Form("x_Fax") & ""
PostData = PostData & "&x_Email=" & Request.Form("x_Email") & ""
'Send the transaction info as part of the querystring
set xml = Server.CreateObject("Microsoft.XMLHTTP")
xml.open "POST", "https://secure.authorize.net/gateway/transact.dll?" _
     & PostData & "", false
xml.send ""
strStatus = xml.Status
strRetval = xml.responseText
set xml = nothing
'Response.Write "response = " & strRetVal & "<BR>"  'this will print out the
                                                    'entire return string
                                                    'for troubleshooting
'first we'll create an array from the return value by splitting on the
'commas and then we'll assign each member of the array to values that
'better describe them for the reader.  Of course we'd probably want to
'do something else with these values like save them to a database,
'create an email to send to the webmaster and/or the user
strArrayVal = split(strRetVal, ",", -1)
x_response_code           = strArrayVal(0)
        'Response Code:
        '1 = This transaction has been approved.
        '2 = This transaction has been declined.
        '3 = There has been an error processing this transaction.
x_response_subcode        = strArrayVal(1)
x_response_reason_code    = strArrayVal(2)
x_response_reason_text    = strArrayVal(3)
x_auth_code               = strArrayVal(4)    '6 digit approval code
x_avs_code                = strArrayVal(5)
        'Address Verification system:
        'A = Address (street) matches, Zip does not
        'E = AVS error
        'N = No match on address or zip
        'P = AVS Not Applicable
        'R = Retry, system unavailable or timed out
        'S = service not supported by issuer
        'U = address information is unavailable
        'W = 9 digit Zip matches, address does not
        'X = exact AVS match
        'Y = address and 5 digit zip match
        'Z = 5 digit zip matches, address does not
x_trans_id                = strArrayVal(6)    'transaction id
x_invoice_num             = strArrayVal(7)
x_description             = strArrayVal(8)
x_amount                  = strArrayVal(9)
x_method                  = strArrayVal(10)
x_type                    = strArrayVal(11)
x_cust_id                 = strArrayVal(12)
x_first_name              = strArrayVal(13)
x_last_name               = strArrayVal(14)
x_company                 = strArrayVal(15)
x_address                 = strArrayVal(16)
x_city                    = strArrayVal(17)
x_state                   = strArrayVal(18)
x_zip                     = strArrayVal(19)
x_country                 = strArrayVal(20)
x_phone                   = strArrayVal(21)
x_fax                     = strArrayVal(22)
x_email                   = strArrayVal(23)
x_ship_to_first_name      = strArrayVal(24)
x_ship_to_last_name       = strArrayVal(25)
x_ship_to_company         = strArrayVal(26)
x_ship_to_address         = strArrayVal(27)
x_ship_to_city            = strArrayVal(28)
x_ship_to_state           = strArrayVal(29)
x_ship_to_zip             = strArrayVal(30)
x_ship_to_country         = strArrayVal(31)
x_tax                     = strArrayVal(32)
x_duty                    = strArrayVal(33)
x_freight                 = strArrayVal(34)
x_tax_exempt              = strArrayVal(35)
x_po_num                  = strArrayVal(36)
x_md5_hash                = strArrayVal(37)
%>
<H1>Order Receipt</H1>
<%
'Check the ErrorCode to make sure that the component was able to talk
'to the authorization network
If (strStatus <> 200) Then
     Response.Write "An error occured during processing.  " _
          & "Please try again later."
else
     If x_response_code = 1 Then
          Response.Write("Thank you for your purchase.")
     elseif x_response_code = 2 then
          Response.Write("The transaction was not approved: " _
               & x_response_reason_text)
     Else
          response.Write "An error occured during processing.  " _
               & "Please try again later."
     End If
end if
%>
</BODY>
</HTML>

Success and Personal Validation

One thing that I was worried about, since I had never seen it done (or at least never noticed it) before was the security of passing values in the query string of the URL. I once again did some searching on the Internet and found this tasty gem from Netscape, the original designers of SSL:

"SSL provides a security "handshake" that is used to initiate the TCP/IP connection... this means that all the information in both the HTTP request and the HTTP response are fully encrypted, including the URL the client is requesting..."

My questions, along with my prayers, were answered - when using SSL passing the data in the query string is just as safe as passing it in the content body.

All in all, it wasn't a bad way to spend an evening:

  • I had found a way to query Authorize.Net.
  • My script was completely customizable and I could set it up so that it could be dropped in wherever I needed it.
  • It did not use any 3rd party components that I would have to fight to get installed on a hosting provider's server.
  • I might have found a way to use Microsoft's XMLHTTP component in which it's original designers may have never had intended.
  • And best of all - my solution was completely free.

-DH


Home |  News |  Samples |  Articles |  Lessons |  Resources |  Forum |  Links |  Search |  Feedback

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers