<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alex James Brown &#187; payment processing</title>
	<atom:link href="http://www.alexjamesbrown.com/tags/payment-processing/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.alexjamesbrown.com</link>
	<description>My Words. By Me.</description>
	<lastBuildDate>Wed, 04 Jan 2012 01:02:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Implementing DataCash 3D Secure with ASP.net</title>
		<link>http://www.alexjamesbrown.com/development/implementing-datacash-3d-secure-with-asp-net/</link>
		<comments>http://www.alexjamesbrown.com/development/implementing-datacash-3d-secure-with-asp-net/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 13:04:50 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[datacash]]></category>
		<category><![CDATA[payment processing]]></category>

		<guid isPermaLink="false">http://www.alexjamesbrown.com/?p=446</guid>
		<description><![CDATA[This is an article I’ve been meaning to write for a while now… Mainly, to help others out, who are struggling with the near non-existent documentation provided by Datacash, when ...]]></description>
			<content:encoded><![CDATA[<p>This is an article I’ve been meaning to write for a while now…</p>
<p>Mainly, to help others out, who are struggling with the near non-existent documentation provided by Datacash, when trying to plug 3D Secure into my ASP.net application.</p>
<p>I’m sure you’re already familiar with what 3D Secure is, so I won’t go in to too much detail, nor will I go into much detail with regards to the process.</p>
<p>The purpose of this article is to get you familiar with <em>how</em> to send the details to the DataCash MPI, receive a response, and display and use the 3D Secure window in an iFrame (or framed window for that matter)</p>
<p><strong>Please note:</strong><br />
<small>This code is for tutorial purposes only. It’s dirty, crude, buggy, and not refactored in any way shape or form.<br />
I simplified the code down to bare bones, in order to better explain each element.<br />
Obviously, it comes without warranty… it <em>should</em> work as expected, but has no logging, error trapping or any of that good stuff… and when dealing with online payments, you really should take more care!</small></p>
<h3>Code</h3>
<p><strong><span class="Apple-style-span" style="font-size: 11px;">Update &#8211; 8th September, 2011:</span></strong></p>
<p><a href="http://alexjamesbrown.com.s3.amazonaws.com/wp-content/uploads/github.png"><img class="alignleft size-full wp-image-814" title="github" src="http://alexjamesbrown.com.s3.amazonaws.com/wp-content/uploads/github.png" alt="GitHub" width="100" height="45" /></a>I&#8217;ve now <a href="https://github.com/alexjamesbrown/Datacash-3DSecure" target="_blank">hosted the code on GitHub</a></p>
<p><strong>You will need to edit the web.config to add your own VTID and Password</strong></p>
<h3>Donate</h3>
<p><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=MVCXSJJ3QU4QJ"><img style="margin: 0px 25px 10px 0px; display: inline; border-width: 0px;" title="btn_donate_SM" src="http://www.alexjamesbrown.com/wp-content/uploads/btn_donate_SM.gif" alt="btn_donate_SM" width="74" height="21" align="left" border="0" /></a>I don’t normally do this, but this article took me literally months to pull together, so any small contribution would be gratefully received!</p>
<hr />
<h3>Payment Page</h3>
<p>This is the functionality that processes payment – for example, allows the customer to enter their credit card details etc…</p>
<p>The mark-up is fairly straight forward.</p>
<p>Two things to note are the body, and the form tag:</p>
<pre class="brush: html;gutter:false;">&lt;body id="myBody" runat="server"&gt;</pre>
<p>Note that the body tag is runat server</p>
<pre class="brush: html;">&lt;form id="MainForm" runat="server"&gt;</pre>
<p>Note that  the name is “MainForm” – we will need this later.</p>
<p>Since in this tutorial, I’m showing how to use an iFrame, I have this bit of code, below the payBtn:</p>
<pre class="brush: html;">&lt;asp:Panel ID="ACSFramePanel" runat="server" Visible="false"&gt;
    Please verify.....&lt;br /&gt;
    &lt;br /&gt;
    &lt;iframe src="" name="ACSFrame" width="450" height="400" frameborder="0" /&gt;
&lt;/asp:Panel&gt;</pre>
<p>Line 4 of the above is basically where the 3D Secure frame will appear.</p>
<p>I wrapped it in a Panel, so that we can hide it, while the customer enters their card details etc…</p>
<p>Now, let’s look at some of the code-behind:</p>
<pre class="brush: c#;gutter:false;">private Config config;
private Agent agent;

//this would be our order id / reference in production
private string ourReference = Guid.NewGuid().ToString("n").Substring(0, 8);

protected void Page_Load(object sender, EventArgs e)
{
    config = new Config(AppDomain.CurrentDomain.BaseDirectory + "datacash.conf"); // would probably need to come from web.config
    agent = new Agent(config);
}</pre>
<p>In the above code, Config and Agent are both DataCash objects.</p>
<p>In the Page_Load event, we basically set these two objects up.</p>
<p><strong>config</strong> is set from an xml file (located in the project root) called datacash.conf – this can of course be located anywhere you like (and called anything you like)</p>
<p><strong>agent </strong>is then set using the defined config object.</p>
<p>The config file looks like this:</p>
<pre class="brush: xml;">&lt;Configuration&gt;
  &lt;logfile&gt;datacash.log&lt;/logfile&gt;
  &lt;logging&gt;5&lt;/logging&gt;
  &lt;Obscure&gt;
    &lt;element&gt;Transaction.CardTxn.Card.pan&lt;/element&gt;
    &lt;element&gt;Authentication.password&lt;/element&gt;
    &lt;element&gt;Transaction.CardTxn.Card.Cv2Avs.cv2&lt;/element&gt;
  &lt;/Obscure&gt;

  &lt;!--this would be for the live server--&gt;
  &lt;!--&lt;host&gt;https://mars.transaction.datacash.com/Transaction&lt;/host&gt;--&gt;

  &lt;host&gt;https://testserver.datacash.com/Transaction&lt;/host&gt;
  &lt;port&gt;443&lt;/port&gt;
  &lt;timeout&gt;90&lt;/timeout&gt;
  &lt;setstrict&gt;true&lt;/setstrict&gt;
&lt;/Configuration&gt;</pre>
<p>Of course, this doesn’t <em>have</em> to be done in Page_Load – in “the real world” this would all be part of a payment helper class. But for demo purposes, it’s fine in the Page_Load – just means we have to repeat ourselves on other pages…</p>
<p>Next, we assume the user fills out the form, and presses the Pay button.</p>
<h3>Sending the request to DataCash</h3>
<pre class="brush: c#;">protected void payBtn_Click(object sender, EventArgs e)
{
    //so they don't press the button twice.
    payBtn.Enabled = false;

    //get browser info (for 3d secure stuff)
    var browser = Request.Browser.Browser;

    var request = buildAuthDataCashDocument(
        ourReference,
        cardNumber.Text,
        expiryMonth.Text,
        expiryYear.Text,
        startMonth.Text,
        startYear.Text,
        issueNumber.Text,
        secCode.Text,
        billingAddress1.Text,
        billingAddress2.Text,
        billingAddress3.Text,
        billingAddress4.Text,
        billingAddressPostCode.Text,
        browser);

    //send the request document to the agent.
    //todo: could implement some kind of error trapping / retry here
    var authResponse = agent.send(request);

    //get the datacash transaction reference (just in case we need to try authorizing the payment without 3D Secure)
    var datacashRef = authResponse.get("Response.datacash_reference");

    //get the response code
    var responseCode = authResponse.get("Response.status");</pre>
<p>This code basically generates a XML document with the payment authorisation request, and submits it to DataCash.</p>
<p>I refactored buildAuthDataCashDocument as it was pretty large, and made the code a bit <em>too</em> dirty, even for this demo!</p>
<p>Couple of bits of note within buildAuthDataCashDocument are:</p>
<pre class="brush: c#;">request.set("Request.Authentication.client", ConfigurationManager.AppSettings["DataCashVtid"]);
request.set("Request.Authentication.password", ConfigurationManager.AppSettings["DataCashPassword"]);</pre>
<p>This basically sets the VTID and Password from config (in our case, web.config) which looks like:</p>
<pre class="brush: xml;gutter:false;auto-links:false;toolbar:false;">&lt;appSettings&gt;
   &lt;add key="DataCashVtid" value="99******"/&gt;
   &lt;add key="DataCashPassword" value="bK*******"/&gt;
&lt;/appSettings&gt;</pre>
<p>Also, within buildAuthDataCashDocument is:</p>
<pre class="brush: c#;">request.set("Request.Transaction.TxnDetails.ThreeDSecure.verify", "yes");
request.set("Request.Transaction.TxnDetails.ThreeDSecure.merchant_url", "www.crocus.co.uk"); //or whatever brand??
request.set("Request.Transaction.TxnDetails.ThreeDSecure.purchase_desc", "Items from Crocus"); //or some other short sumary
request.set("Request.Transaction.TxnDetails.ThreeDSecure.purchase_datetime", DateTime.Now.ToString("yyyyMMdd HH:mm:ss"));</pre>
<p>This is important, for 3D Secure – Fairly self explanatory.</p>
<p>After building our request Document, we need to send it to DataCash, and get another Document back – as a response.</p>
<p>To do that, it’s as simple as:</p>
<pre class="brush: c#;">var authResponse = agent.send(request);</pre>
<p>This sets authResponse to the response Document.</p>
<p>We can then use the .get() method on authResponse to retrieve elements from it.</p>
<p>We are most interested in <strong>Response.datacash_reference</strong> and <strong>Response.status</strong></p>
<p>The datacash_reference is unique to each and every transaction processed, so it is useful for later things like refunds, reporting etc…</p>
<p><strong>Response.status</strong> is the DataCash status code for this transaction.</p>
<p>It’s from this, that we determine how to proceed.</p>
<pre class="brush: c#;">switch (responseCode)
{
    //handle 3DS error responses....`
    //Basically, if it's one of these, the transaction is screwed, and shouldn't proceed....
    case "151": 		//	3DS Invalid Transaction type
    case "152": 		//	3DS Manual Authorization not supported
    case "153": 		//	3DS verify element missing
    case "154": 		//	3DS Invalid verify value
    case "155": 		//	3DS field missing
    case "156": 		//	3DS Invalid Browser.device_category
    case "157": 		//	3DS Merchant not enabled
    case "159": 		//	3DS No VERes from DS
    case "160": 		//	3DS Invalid VERes from DS
    case "161": 		//	3DS call auth centre

        //log the error here
        break; //- throw them out of transaction process. Should redirec

    case "56": //speed limit - too many transactions on that card number in short space of time
        break;

    //3ds payer verification required....
    case "60":
    case "150":
        show3DSIframe(authResponse);
        Response.Clear();
        break;
}</pre>
<p>I won’t go in to too much detail, as the comments kind of speak for themselves…</p>
<p>Basically, if you get a <strong>60</strong> or <strong>150</strong> then the transaction requires you to show the 3D Secure window.</p>
<h3>Showing the 3D Secure iFrame</h3>
<p>I’ll spend a bit of time on show3DSIframe, as this is the part that caused me the most hassle – How to actually display the ACS in an iFrame, especially in ASP.net</p>
<pre class="brush: c#;">private void show3DSIframe(Document doc)
{
    ACSFramePanel.Visible = true;

    //this is the data cash reference number for this transaction
    var dataCashReference = doc.get("Response.datacash_reference");

    //this is the url of the ACS - the page generated by the bank, that contains the
    //boxes where the customer enters information etc...
    var acsUrl = doc.get("Response.CardTxn.ThreeDSecure.acs_url");

    //this is a long message / code that is generated for the transaction
    var pareq = doc.get("Response.CardTxn.ThreeDSecure.pareq_message");</pre>
<p>Ok, so in the markup from Part 1, you may remember I wrapped the iFrame in a Panel, called ACSFRamePanel. Now, we need to set the visibility to true.</p>
<p>These first few lines are self explanatory – we need to get the <strong>dataCashReference</strong>, <strong>acsUrl</strong> (the URL of the 3D Secure page – this is usually returned by the customers issuing bank) and the <strong>pareq</strong> – this is a long string, that&#8217;s a bit like a password for the transaction.</p>
<p>These elements are retrieved from the passed in DataCash Document.</p>
<p>We then need to create our Term URL – This is basically a URL that the 3D Secure window POSTs back to:</p>
<div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:46726e71-84a2-4bfc-9dff-92a39d65f426" class="wlWriterEditableSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;">
<pre class="brush: c#;">var termUrlPrefix = Request.ServerVariables["HTTPS"] == "ON" ? "https://" : "http://";

//termUrl is where the ACS page posts back to.
var termUrl = string.Format("{0}{1}",
    termUrlPrefix,
    Request.Url.Authority + "/3DSResponse.aspx");</pre>
</div>
<p>In our demo case, it’s just on our local host machine – this could however, for example, be something like <em>www.myUrl.com/checkout/3DSresponse.aspx</em></p>
<p>This next part is the important part.</p>
<p>This set’s the required hidden fields (PaReq and TermUrl) on our form.</p>
<p>We then register another hidden form &#8211; “MD” – This is <strong>our</strong> order number / reference for this transaction – so we can retrieve it from our database, and update the status when we come out the other side of 3D Secure.</p>
<p>The next line generates a little bit of JavaScript that basically causes this form to submit itself to the acs url.</p>
<p>The result of this, is then output to the target (parameter 3 in our string.format) – ACSFrame.</p>
<p><small><strong>Remember we called our form “MainForm”</strong></small> <img src='http://www.alexjamesbrown.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Then, myBody.Attributes.Add inserts the resulting JavaScript to the onLoad function of our body tag.</p>
<p><small><strong>Remember we made runat server earlier</strong></small></p>
<div id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:d448a460-0b9a-4864-a1b7-a74bfee554e9" class="wlWriterEditableSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;">
<pre class="brush: c#;">//ClientScript.RegisterHiddenField adds a hidden field to the form...
ClientScript.RegisterHiddenField("PaReq", pareq);
ClientScript.RegisterHiddenField("TermUrl", termUrl);

//this is the data cash reference, and our reference -
//so we can update the order on the other side of the verification (paid, failed etc...)
ClientScript.RegisterHiddenField("MD", dataCashReference + "|" + ourReference);

var js = string.Format("javascript: document.{0}.action='{1}'; document.{2}.target=\"{3}\"; document.{4}.submit();",
    MainForm.ID,
    acsUrl,
    MainForm.ID,
    "ACSFrame",
    MainForm.ID
);

//since the body tag of this page is called myBody, and is runat=server, we can access
//it here, and inject our javascript.
myBody.Attributes.Add("onLoad", js);</pre>
</div>
<p>And there we have it – the 3D Secure window is displayed in an iFrame</p>
<p>I’ll edit this post with a link to 3DSResponse.aspx when I finish that article…</p>
<p>Hope this helps! Feel free to <img src='http://www.alexjamesbrown.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><img style="margin: 0px 25px 10px 0px; display: inline; border-width: 0px;" title="btn_donate_SM" src="http://www.alexjamesbrown.com/wp-content/uploads/btn_donate_SM1.gif" alt="btn_donate_SM" width="74" height="21" border="0" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.alexjamesbrown.com/development/implementing-datacash-3d-secure-with-asp-net/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

