Search: 
Tutorial - A complete 3-D Secure Integration & Payment Processing Solution.

By Lance Robinson - Technology Evangelist, /n software,
and Charles Smith - Software Developer, /n software.
Requirements: /n software 3-D Secure MPI
Download Demo: Included in the installation of /nsoftware 3-D Secure MPI

Contents

  1. Introduction
  2. What is 3-D Secure?
  3. Visa, MasterCard, JCB, and URLs
  4. Eligible Card Ranges
  5. Verifying Customer Enrollment
  6. Payer Authentication Request (PAReq)
  7. Payer Authentication Response (PARes)
  8. Authorization
  9. Testing

Introduction

In this document we will demonstrate how to integrate the 3-D Secure services Verified By Visa, MasterCard SecureCode, and JCB J/Secure into a merchant order page. We'll do this by using the /n software 3-D Secure MPI (merchant plug-in interface) to authenticate cardholders. This particular example uses the /n software 3-D Secure MPI ASP.NET edition to create an ASP.NET solution, but the same functionality can be performed using the ASP Edition (classic asp), the Java Server Edition (jsp), or even the C++ Edition (cgi).

Next, we'll go over setting up an account with Visa's PIT test server. Finally, we'll show how to pass on the 3-D Secure authentication tokens during the credit card authorization process. Note that although our 3-D Secure MPI is certified and has gone through interoperability testing with Visa, every merchant that signs up for 3-D Secure (whether they develop the application themselves, use a certified component, or buy an off-the-shelf solution) is required to complete PIT testing.

What is 3-D Secure?

3-D Secure is a protocol developed by Visa to make online payments more secure through password authentication and cardholder verification. Visa has licensed this technology out to other major credit card brands, giving us Verified By Visa, MasterCard SecureCode, and JCB J/Secure. All three of these 3-D Secure services are supported by the /n software 3-D Secure MPI component. Here are the basics of how 3-D Secure works:

In order for a cardholder to be able to use the service, they must enroll, at which time they set a password. Information about the cardholder is then created in Visa's (or MasterCard's, or JCB's) "Enrollment Server", which keeps track of cardholders participating in the 3-D Secure service, and in the Access Control Servers (ACS), which are used at the time of purchase to verify cardholder enrollment. After enrollment, the cardholder is eligible to take advantage of 3-D Secure services offered by online merchants.

At the time of purchase, the merchant plug-in interface (MPI - i.e., the /n software 3-D Secure MPI component) contacts a "Directory Server" to check for enrollment. If the cardholder is enrolled, the directory will respond back with the URL of an Access Control Server (ACS) which can be used to authenticate the cardholder.

Next, the merchant sends a payer authentication request (PAReq) to the ACS through the cardholder's browser/device (important: this request comes FROM the cardholder's computer - NOT from the merchant). Then the ACS will communicate directly with the cardholder (the merchant is not involved in this part of the process) in order to authenticate the cardholder's password. After this, the ACS will send a signed payer authentication response (PARes) to the MPI containing results of the cardholder authentication. Finally, the MPI will verify the ACS signature on the PARes, and parse the response, which will contain information confirming the cardholder's authentication. At this point, the merchant continues with the normal credit card authorization process, the only difference is that when the customer's credit card information is sent for authorization, the merchant can submit additional values returned in a successful 3-D Secure authentication: XID (transaction Id), ECI (electronic commerce indicator), and CAVV (cardholder authentication verification value). Submitting these values is required in order to qualify for the protections and discounted rates that 3-D Secure transactions guarantee.

Visa, MasterCard, JCB, and URLs

The same code you write for Visa will also work for MasterCard and JCB, except you'll use different property values depending on which card brand is in use. These values will be provided by the merchant's acquiring bank when the account is setup for VbV, SecureCode, or J/Secure. When the customer presents his or her card, we'll examine it to find out what kind it is (Visa, MasterCard, JCB, etc). Most credit card processing software will do this for you (for example, all of the /n software Integrator products that are for credit card payments ship with a CardValidator component, which determines the card type and performs validation algorithms.

Once we know what kind of card it is, we can set up the MPI for use with Visa, MasterCard, or JCB. The only things you will need to change depending on the card type are:

  • DirectoryServerURL

    The DirectoryServerURL property should be set to the URL of the directory server provided to you by Visa, MasterCard, or JCB. This URL is used by the RequestCardRanges and VerifyEnrollment methods of the component.

  • SSLAcceptServerCert

    Setting the SSLAcceptServerCert property is optional, since the SSLServerAuthentication event could also be used (except in classic ASP). If it finds any issues with the certificate presented by the server, the component will normally terminate the connection with an error. You can override that behavior by setting this property to the base64 encoded public key of the certificate to trust. This value is compared with the certificate presented by the server during SSL negotiation, and if they match, the server certificate is accepted and the connection will continue normally. Alternatively, you can also override the certificate authentication by setting the SSLServerAuthentication event's Accept parameter to true or false.

  • RootCertificate

    The RootCertificate property is used to verify the digital signature of the payer authentication response when it is passed to the CheckAuthenticationResponse method. It should be set to the base64 encoded public key value of the certificate to verify with. There may be more than one possible signing certificate, so you can append to the RootCertificate property (instead of overwriting) by prepending a "+" character to the base64 encoded string value, as shown in a later example in this tutorial.

  • Client Certificate Properties

    SSLCertStore and SSLCertSubject must be set to point to the SSL client certificate required for authenticating yourself to the directory and access control servers during SSL negotiation.

  • You may also need to change the merchant number and password as well, if they are different between the various card brands.

Other information provided to the merchant by the acquiring bank are the merchant number (id) and password, certificates for signature verification, graphics, and client certificates (if applicable). The graphics (Visa, MasterCard, or JCB graphics) can be displayed on your websites to show that you are able to use 3-D Secure Authentication. The client certificate is not necessarily required - this depends on your location. Your acquiring bank will let you know which type of authentication you need to use when you sign up with them (either a password or a client certificate).

Eligible Card Ranges

Not all credit cards are eligible for 3-D Secure authentication, such as some check cards, gift cards, and corporate cards. To find out if a card is eligible, you can download a list of eligible card ranges from the server, and check those ranges to see if the card in question is included. This step is optional, but is useful to avoid unnecessary authentication attempts.

The RequestCardRanges method of the 3-D Secure MPI component sends a "Card Range Request" to the directory server. The response to this request contains a list of card number ranges that are eligible for 3-D Secure enrollment. If the card number presented by the customer falls within one of these ranges, the customer might be enrolled in 3-D Secure service, but the VerifyEnrollment method needs to be used to find out for sure (code sample below). If the customer card number does not fall within any of these ranges, then you know the customer is definitely not enrolled in 3-D Secure, and regular credit card authorization should continue on without any 3-D Secure authentication.

After the RequestCardRanges method returns, the component's CardRangeBegin, CardRangeEnd, and CardRangeAction property arrays will be populated with the ranges. RequestCardRanges can either return all eligible card ranges, or it can return the changes in eligible card ranges since a previous request. This behavior is controlled by the Serial Number property. If the SerialNumber property has a value of "" (empty string) before calling RequestCardRanges, the full list of eligible card ranges will be returned. If the SerialNumber property has a non-empty value prior to calling the RequestCardRanges method, then only the changes since the last response matching the specified SerialNumber will be returned. So you can send a request for the full list, save the results, and then for subsequent card range requests you can simply get the changes and update your saved list of ranges. This allows you to avoid downloading a large list of eligible card ranges too often, but it is recommended that you refresh your local cache with a full list periodically.

For example, CardRangeBegin[0] and CardRangeEnd[0] may be one range of eligible card numbers. If CardRangeAction[0] is "A", the cards in that range are eligible. If CardRangeAction[0] is "D", the cards in that range are no longer eligible and should be deleted from any locally saved cache of card ranges.

Verifying Customer Enrollment

To find out for sure if a cardholder is enrolled in a 3-D Secure service like Verified By Visa or MasterCard SecureCode, we use the VerifyEnrollment method of the ThreeDSecure component. When the VerifyEnrollment method returns, the CardEnrolled property will have one of the values "Y" (yes, they are enrolled), "N" (no, they are not enrolled), or "U" (yes, they are enrolled, but authentication is currently unavailable). If the CardEnrolled value is "Y", we can continue with 3-D Secure authentication and verify the cardholder. Otherwise, we go back to regular credit card authorization without 3-D Secure authentication. Note that many US card issuers automatically enroll cards in 3-D Secure programs, so this may return "Y" unexpectedly. In this case, the card is enrolled even if the cardholder hasn't set a password, the issuing bank will behave appropriately when the payer authentication request is sent to them, and the payer authentication response will contain a specific ECI value that means the merchant attempted to authenticate - giving the merchant chargeback protection.
1ThreeDSecure1.CardNumber = tbCardNumber.Text;
2ThreeDSecure1.DirectoryServerURL = "https://<url.obtainedfrom.acquiringbank>/"; 3ThreeDSecure1.VerifyEnrollment(); 4if (ThreeDSecure1.CardEnrolled == "Y") 5{ 6 SendAuthenticationRequest(); 7} 8//else the customer is not enrolled
In the example above, if the customer is enrolled we'll go on to the next step of 3-D Secure authentication: sending an authentication request.

Payer Authentication Request

The next step of a 3-D Secure authentication is to send a payer authentication request (PAReq) to an access control server (ACS). The URL of the ACS that we'll post to was provided to us in the response to the VerifyEnrollment method, and is already stored and ready to use in the ACSURL property of the component.

In order to send the payer authentication request to the 3-D secure service, first we'll need to generate it. The component will do this for you with the GetAuthenticationPacket method, which uses the properties of the component to generate a compressed and encoded payer authentication request. Prior to calling GetAuthenticationPacket, you'll need to set at least the MessageId, TransactionId, TransactionAmount, TransactionDisplayAmount, and the card properties:

1ThreeDSecure1.MessageId = "11292007120208046";
2ThreeDSecure1.TransactionId = "11292007120208046";
3ThreeDSecure1.CardNumber = tbCardNumber.Text;
3ThreeDSecure1.CardExpMonth = tbCardExpMonth.Text;
4ThreeDSecure1.CardExpYear = tbCardExpYear.Text;
5ThreeDSecure1.TransactionAmount = "7256";
6ThreeDSecure1.TransactionDisplayAmount = "$72.56";
7string PAReq = ThreeDSecure1.GetAuthenticationPacket();
Notice the transaction amount, on line 5 in the code sample above, is specified without a decimal point ($72.56 is represented as 7256).

Besides the payer authentication request, we also need to send two other pieces of data: "TermUrl" and "MD". TermUrl (termination URL) is the URL that we want the ACS to post back to after it has authenticated the user. MD is the "merchant data" that we want the ACS to include in its response back to us so that we can match their response to our sale. Typically this would be some unique identifier associated with the transaction we're about to authorize (note that you should never send the card number in the MD field on a production system). For this example, the MD will be a key into a database where we'll store the transaction information temporarily (while we await the response from the ACS). The transaction information we need to store is exactly the same information used to generate the payer authentication request (MessageId, TransactionId, CardNumber, TransactionAmount). Note: when storing data, be sure to follow payment application best practices. For more information on CISP and PABP, see the /n software 3-D Secure MPI documentation.

Next, we need to send the request, TermUrl, and MD to the access control server (ACS). Important: the request must be sent through the cardholder's browser, and thus cannot be sent by the ThreeDSecure component itself. Instead, you must handle sending the request yourself. One way to do this is with javascript, like so::

1myForm.Controls.Clear();
2ClientScript.RegisterHiddenField("PAReq", PAReq);
3ClientScript.RegisterHiddenField("TermUrl", Request.Url.Authority + 
4    "/3dsResponse.aspx";);
5ClientScript.RegisterHiddenField("MD", mytransactionkey);
6myBody.Attributes.Add("onLoad", "javascript: document." + myForm.ID + 
7    ".action='" + ThreeDSecure1.ACSURL +  "'; document." +
8    myForm.ID + ".submit();");
The above sample code will write the javascript code to the html page body, setting the action of the HTML form named "myForm" (the form where the cardholder submitted their data) to the ACSURL, and submitting the form. Note that it adds three hidden fields that will be submitted to the ACS URL: PAReq, TermUrl, and MD.

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, 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.

Payer Authentication Response

At this point, the merchant has sent the customer on to the credit card brand's ACS for authentication. When the customer comes back, they will be sent back to us from the ACS to the TermURL. As you can see from the previous sample code, on line 3 the TermURL was sent as Request.Url.Authority + "/3dsResponse.aspx". Inside 3dsResponse.aspx, we'll get the two form variables that were posted back to us by the ACS, "MD" and "PARes". "MD" is the value that we passed in with the authentication request, and we'll use it to look up the details of the transaction in progress. Using this transaction key we'll look up the transaction id, amount, cardnumber, and any other previously stored information that we need to continue. "PARes" is the payer authentication response which we will pass to the CheckAuthenticationResponse method after setting the appropriate transaction properties, like so:
1ThreeDSecure1.RootCertificate = "MIIBwDCCASmgAwIB...";
1ThreeDSecure1.RootCertificate = "+MIICHjCCAYegAwIB...";
2ThreeDSecure1.MerchantBankId = "999999";
3ThreeDSecure1.MerchantNumber = "TEST_NUMBER";
4ThreeDSecure1.TransactionId = transaction_id;
5ThreeDSecure1.TransactionAmount = transaction_amount;
6ThreeDSecure1.CardNumber = transaction_cardnumber;
7ThreeDSecure1.MessageId = transaction_messageid;
8ThreeDSecure1.CheckAuthenticationResponse(Request.Form["PARes"]);
Note the RootCertificate property settings on lines 1 and 2 in the sample code above. Visa, MasterCard, and/or JCB will have provided you with one or more public keys that you can use to verify their signature. These public keys should be passed to the component through this RootCertificate property. Prepend a "+" character to the base64 encoded certificate body to append to the RootCertificate list instead of overwriting. The CheckAuthenticationResponse method will verify that the response really came from the ACS (through signature verification). If no errors are thrown by CheckAuthenticationResponse, then the signature was verified and you can trust that the response is valid.

If the authentication was successful, AuthenticationStatus will contain "Y". If authentication fails, the AuthenticationStatus will contain "N". If the authentication is successful, you must pass the TransactionId, AuthenticationCAVV, and AuthenticationECI properties in the credit card authorization request (handled by other software, such as one of the /n software Integrator products that are for credit card payments) in order to qualify for the extra protection and discount. If the AuthenticationStatus is "N" you MUST NOT complete the transaction.

Note: Even if the AuthenticationStatus contains "Y", the transaction should not be considered authenticated if the signature verification fails. A transaction may only be considered authenticated if no errors are generated by the CheckAuthenticationResponse method and the value of AuthenticationStatus is "Y".

Authorization

Finally, the 3-D secure authentication is completed, CheckAuthenticationResponse succeeded and AuthenticationStatus was "Y", so we can charge the customers credit card. Here are a few examples of how this can be done:
  • Vital/TSYS Integrator

    1directcharge1.CardNumber = transaction_cardnumber;
    2directcharge1.CardExpMonth = transaction_cardexpmonth;
    3directcharge1.CardExpYear = transaction_cardexpyear;
    4directcharge1.CustomerAddress transaction_customeraddress;
    5directcharge1.CustomerZip = transaction_customerzip;
    6directcharge1.TransactionAmount = transaction_amount;
    7directcharge1.TransactionNumber = "0001" 'increment for each transaction
    8directcharge1.XID = ThreeDSecure1.TransactionId;
    9directcharge1.ECI = ThreeDSecure1.AuthenticationECI;
    10directcharge1.CAVV = ThreeDSecure1.AuthenticationCAVV;
  • E-Payment Integrator

    How to support 3-D Secure in the E-Payment Integrator depends on which gateway you're using, because each gateway might expect the transactionId, authenticationECI, and authenticationCAVV to be called different things. Once you know what the gateway you're using calls these fields, you can simply use the AddSpecialFields method of the ICharge component to add these fields to the outgoing request. Prior to calling the Authorize method, simply add each special field. For example:

    USAEPay:

    1icharge1.AddSpecialField("UMxid", ThreeDSecure1.TransactionId);
    2icharge1.AddSpecialField("UMeci", ThreeDSecure1.AuthenticationECI);
    3icharge1.AddSpecialField("UMcavv", ThreeDSecure1.AuthenticationCAVV);

    Paymentech Orbital:

    1icharge1.AddSpecialField("XID", ThreeDSecure1.TransactionId);
    2icharge1.AddSpecialField("AuthenticationECIInd", ThreeDSecure1.AuthenticationECI);
    3icharge1.AddSpecialField("CAVV", ThreeDSecure1.AuthenticationCAVV);
    4//If
    		this is a MasterCard instead of a Visa, use AAV instead of CAVV.

    Authorize.Net:

    1icharge1.AddSpecialField("x_authentication_indicator", 
    2    ThreeDSecure1.AuthenticationECI);
    3icharge1.AddSpecialField("x_cardholder_authentication_value", 
    4    ThreeDSecure1.AuthenticationCAVV);

Testing

The "dummy" test servers used in this tutorial and in the accompanying demo applications are not real and should not be used with real customer data. These servers are not complete servers, but basic stubs designed to allow simple code testing, and they will only respond with hard-coded transaction information, and will only work with the supplied example values. Feel free to use these servers during your development.

After you are confident in your solution, you'll need to undergo some amount of testing with Visa, MasterCard, and/or JCB (depending on which of their programs you would like to support). If you are going to support Verified By Visa, you'll have to complete Visa's PIT testing process. As stated earlier in this tutorial, the /nsoftware 3-D Secure MPI is certified and has gone through interoperability testing with Visa. Even so, every merchant that signs up for Verified By Visa is required to complete PIT testing. You can use our PIT Testing overview for a step-by-step explanation of how to complete PIT testing. MasterCard SecureCode and JCB J/Secure also have test infrastructures for your convenience.

For debugging, the component provides a ResponsePacket property, a DataPacketIn event, and a DataPacketOut event. The ResponsePacket property can be used to access the responses received from the directory server after a call to RequestCardRanges or VerifyEnrollment. It can also be used to access the PARes received from the ACS after calling CheckAuthenticationResponse. The two events, DataPacketOut and DataPacketIn, are fired when sending/receiving data packets to/from a remote server. You can also use the DataPacketOut event to view the unencrypted XML version of the PAReq after a call to GetAuthenticationPacket. Note that in the classic asp edition, where there are no events, the DataPacketOut and ResponsePacket properties can be used to read the last data sent to and received from the directory server and/or access control server.

Conclusion

This article showed how to add 3-D Secure authentication to any merchant payment system. The /nsoftware 3-D Secure MPI can be used to plug-in to an existing system, or it can be combined with one of the /n software Integrator products to create a complete solution from scratch. Here we talked about the basics that you need to get started, but we recommend that you also take a look at the documentation of the /nsoftware 3-D Secure MPI that comes installed with the product, as it goes into details about all available properties of the component, including many that were not discussed here.

Please note that in a real production environment you will want to log all messages from both the 3-D Secure MPI and Vital/TSYS or E-Payment Integrator 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: /n software 3-D Secure MPI, E-Payment Integrator, & Vital/TSYS Integrator.

| About | Privacy Policy | Terms of Use |
© Copyright 2008 /n software inc.