This article is by Charles Smith - Software Developer, /n software.
Requirements
The purpose of this article is to explain how to build a merchant order page using Verified By Visa and Vital together. To that end, we'll use two components from /n software; IBiz VitalPS Integrator and IP*Works! 3-D Secure MPI. This particular example uses the ASP edition, though the same functionality can be performed using the .NET Edition in an ASP.NET web application, or using the C++ Edition to create a CGI application running on a web server. In addition to these two components, we are going to need to set up an account with Visa's PIT test server, and then download and install several certificates.
Merchant.inc
To make things simple, we are going to split this demo into four separate pages; Mechant.inc, OrderPage.asp, VerifyEnrollment.asp, ProcessPARes.asp, and PaymentPage.asp. To begin with, we have Merchant.inc, which will contain all of our setup information, and will be included in all the other pages. In this file, both the IBiz VitalPS Integrator and the 3-D Secure MPI components should be initialized with your merchant data. In this example, we are using test account data.
'===================
'3-D Secure MPI setup:
'===================
Dim o3DS
Set o3DS = Server.CreateObject("IPWorksMPIASP.ThreeDSecure")
o3DS.MerchantBankId = "999995" ' Must match "BIN" in PIT profile
o3DS.MerchantNumber = "999999999911" ' Must match "Merchant ID" in PIT profile
o3DS.MerchantPassword = "12345678" ' Must match "Password" in PIT profile
o3DS.MerchantName = "TEST_MERCHANT"
o3DS.MerchantURL = "http://www.testmerchant.com"
o3DS.DirectoryServerURL = "https://dropit.3dsecure.net:7443/PIT/DS"
' Client-side certificate acquired from PIT.
' Your IP address will be your cert subject
o3DS.SSLCertStoreType = 2 'sstPFXFile
o3DS.SSLCertStore = "PFX\C:\pitclient.pfx"
o3DS.SSLCertStorePassword = "pitpass"
o3DS.SSLCertSubject = "12.34.56.78"
' Add the Root and CA signing certificates: (Prepending a "+" character adds
' another certificate instead of overwriting. NOTE: These are sample
' certificates. Please download the latest certs from the PIT main page.
o3DS.RootCertificate = "MIICHzCCAYigAwIBAgIUBJvEyXmLs6Ub9MX9W0Nn4w2JzY4w..."
o3DS.RootCertificate = "+" & "MIICHjCCAYegAwIBAgIVAJyspltGwoe8VGp..."
'===============
'IBiz VitalPS Integrator setup:
'===============
Dim oVPS
Set oVPS = Server.CreateObject("IBizPayASP.CCCharge")
' This is sample merchant data.
oVPS.MerchantBankId = "999995"
oVPS.MerchantCategoryCode = "5999"
oVPS.MerchantLanguage = "00"
oVPS.MerchantName = "TEST_MERCHANT"
oVPS.MerchantNumber = "999999999911"
oVPS.MerchantServiceNumber = "800-1234567"
oVPS.MerchantState = "NC"
oVPS.MerchantStoreNumber = "0011"
oVPS.MerchantTerminalNumber = "9911"
oVPS.MerchantTimeZone = "705"
oVPS.MerchantZip = "27709"
OrderPage.asp
This is the page where the customer's credit card information is gathered. Existing merchants will already have something much more elaborate, but for the sake of this demo we will compress it down to a simple form. This form will post to our VerifyEnrollment.asp page, where the 3-D Secure MPI component is used to verify the cardholder's identity. The great majority of merchants will have to make very few changes to their existing order pages to add 3-D Secure support. The difference is merely two intermediate pages. Please note that the following is test data, and that the amount is indicated without a decimal point.
Billing Information:
<FORM method="post" action="VerifyEnrollment.asp">
<INPUT type="text" name="CardNumber" value="4012001037141112">
<INPUT type="text" name="ExpMonth" value="05">
<INPUT type="text" name="ExpYear" value="06">
<INPUT type="text" name="CustomerName" value="John Doe">
<INPUT type="text" name="Address" value="8320 S. Hardy Dr.">
<INPUT type="text" name="City" value="Tempe">
<INPUT type="text" name="State" value="AZ">
<INPUT type="text" name="ZipCode" value="85284">
<INPUT type="text" name="Amount" value="5500">
<INPUT type="submit" name="Purchase" value="Purchase">
</FORM>
VerifyEnrollment.asp
After the customer presses the Purchase button, his credit card data is posted to the VerifyEnrollment.asp page. The first thing we do here is save the order information to the merchant's order database. After saving the info, we use the 3-D Secure MPI component to check if the customer's credit card is enrolled in Visa's Verified By Visa program.
<!--#include file = "merchant.inc" -->
<%
'Save order info and returns a unique key to access data
key = SaveOrderInfoToDatabase()
o3DS.MessageId = "123456" ' Must be unique for each transaction
o3DS.CardNumber = Request.Form("CardNumber")
o3DS.VerifyEnrollment()
If there is an error communicating with the Directory Server or the card is not enrolled, the transaction should proceed normally to the Payment Page. In this case the merchant does not receive the benefits of a 3-D Secure MPI authenticated transaction, but the customer still needs to pay. Note that this is completely transparent to the customer. If his card is not signed up for Verified By Visa or Mastercard SecureCode, the transaction processes as it always has. However, if the card is enrolled then the customer is to be redirected to the site specified in the 3-D Secure component's ACSURL property.
If (Err.Number <> 0 Or o3DS.CardEnrolled <> "Y") Then
' If there's an error, here is where you can log it.
' Also, redirect the cardholder to the paymentpage.
' Send key so trans can be retrieved
Response.Redirect("PaymentPage.asp?" & "MD=" & key)
Else
'no error and the card is enrolled:
o3DS.MessageId = key 'Using unique database access key
o3DS.TransactionId = key 'Using unique database access key
o3DS.CardExpMonth = Request.Form("ExpMonth")
o3DS.CardExpYear = Request.Form("ExpYear")
o3DS.TransactionAmount = Request.Form("Amount")
%>
<SCRIPT LANGUAGE="Javascript" >
<!--
function OnLoadEvent() { document.downloadForm.submit(); }
//-->
</SCRIPT>
<body OnLoad="OnLoadEvent();">
<form name="downloadForm" action="<% =o3DS.ACSURL %>" method="POST">
<INPUT type="hidden" name="PaReq" value="<% =o3DS.GetAuthenticationPacket()%>">
<input type="hidden" name="TermUrl" value="https://yourserver/ProcessPARes.asp">
<input type="hidden" name="MD" value="<% =key %>">
</form>
</body>
<%
End If
%>
Please note that the above Javascript code, or something similar, is essential to the way 3-D Secure MPI works. The customer must be redirected from his own browser window. The customer leaves the merchant's site and goes to the location specified in the ACSURL property. After the customer inputs the password for his credit card, he will be redirected back to the TermUrl, which in this case is the "ProcessPARes.asp" file residing on the merchant's server. The Merchant Data, or "MD" field contains the key into our database to retrieve the transaction data, and is posted back to the TermUrl after the customer inputs his password.
ProcessPARes.asp
The ProcessPARes.asp page is where the Access Control Server indicated in the ACSURL property above posts whether the customer has been authenticated or not back to the merchant. The post from the ACS will include the form variables "PaRes" and "MD". "PaRes" contains the signed and encrypted response, and "MD" passes back the merchant data required to retrieve the transaction from the merchant's database. (In our case, the key variable). To parse this response packet, simply pass the contents of the PaRes to the CheckAuthenticationResponse method. If there are no errors and the AuthenticationStatus property is "Y" (authenticated) or "A" (attempts authentication), then the customer is considered authenticated. If authenticated, you must pass the TransactionId, AuthenticationCAVV, and AuthenticationECI properties to the IBiz VitalPS oVPS component in order to qualify for the extra protection and discount. If the AuthenticationStatus is "N" you MUST NOT complete the transaction.
<!--#include file = "merchant.inc" -->
<%
key = Request.Form("MD")
LoadFromDatabase(key)
o3DS.MessageId = key
o3DS.TransactionId = key
o3DS.TransactionAmount = LoadFromDatabase(key, "TransactionAmount")
o3DS.CardNumber = LoadFromDatabase(key, "CardNumber")
o3DS.CardExpMonth = LoadFromDatabase(key, "CardExpMonth")
o3DS.CardExpYear = LoadFromDatabase(key, "CardExpYear")
o3DS.CheckAuthenticationResponse(Request.Form("PaRes"))
if (Err.Number <> 0) Then
' Log the error and then process the credit card. This should be
' completely transparent to the customer.
Response.Redirect("PaymentPage.asp?" & "MD=" & key)
Else
If (o3DS.AuthenticationStatus = "Y" Or o3DS.AuthenticationStatus = "A") Then
' Redirect to the payment page, including the ECI, XID, and CAVV values
' which are to be passed to the Vital processor.
Response.Redirect("PaymentPage.asp?" & "MD=" & key & "&XID=" & _
o3DS.TransactionId & "&ECI=" & o3DS.AuthenticationECI & _
"&CAVV=" & o3DS.AuthenticationCAVV)
Else
%>
<b>Authentication Failed.</b><BR>
Your financial institution has indicated that it could not authenticate this
transaction via Verified by Visa. To protect against unauthorized use, this
Visa card cannot be used to complete your purchase. You may complete the
purchase by clicking <a href=orderpage.asp>here</a> to select
another form of payment.
<%
End If
End If
%>
PaymentPage.asp
The last step is PaymentPage.asp. This is where the customer's credit card is actually charged. The Vital PS oVPS component was set up in the merchant.inc step above. Now we are going to use this component to authorize the customer's card. We simply load the transaction from the database, add the 3D Secure XID, ECI, and CAVV properties (if they are not in the query string the value will be ""), and then finally charge the card.
<!--#include file = "merchant.inc" -->
<%
key = Request.QueryString("MD")
oVPS.CardNumber = LoadFromDatabase(key, "CardNumber")
oVPS.CardExpMonth = LoadFromDatabase(key, "CardExpMonth")
oVPS.CardExpYear = LoadFromDatabase(key, "CardExpYear")
oVPS.CustomerAddress = LoadFromDatabase(key, "CustomerAddress")
oVPS.CustomerZip = LoadFromDatabase(key, "CustomerZip")
oVPS.TransactionAmount = LoadFromDatabase(key, "Amount")
oVPS.TransactionNumber = "0001" ' This should increment for each transaction
oVPS.XID = Request.QueryString("XID") 'If not present = ""
oVPS.ECI = Request.QueryString("ECI") 'If not present = ""
oVPS.CAVV = Request.QueryString("CAVV") 'If not present = ""
oVPS.Authorize()
If (Err.Number <> 0) Then
'log the error and alert the customer
%>
We're sorry, our payment system is currently experiencing technical
difficulties. Please call 1-800-555-5555 to place your order over the
phone. We are sorry for any inconvenience.
<%
ElseIf (DirectCharge.ResponseCode = "00" Or _
DirectCharge.ResponseCode = "85") Then
Response.Write("Thank you for your purchase. Your tracking number is:" & key)
Else
Response.Write("Your card has been declined for the following reason:")
Response.Write(oVPS.ResponseText)
End If
UpdateDatabaseEntry(key)
%>
Conclusion
This article showed how to write a very simple merchant payment system from scratch. However, the 3-D Secure MPI component and IBiz VitalPS Integrator can be easily integrated into an existing system. If the gateway or processor you're using supports 3-D Secure data transport (XID, CAVV, and ECI) you can use the IP*Works! 3-D Secure MPI component to authenticate cardholders by creating intermediate pages between checkout and payment as shown above.
Please note that in a real production environment you will want to log all messages from both the 3-D Secure MPI and VitalPS components. You will also want to use your own database code to load and store partially completed transactions.
Read more information about the products mentioned above: IP*Works! 3-D Secure MPI & IBiz VitalPS Integrator.