Integrating with 3D Secure

To integrate your SSP application's checkout with 3D Secure, you must do the following for the Proceed to Checkout touch point:

In an .ss file, call the submit method on the order shopping object, and pass the following paymentauthorization object fields as checkoutsettings parameters:

  • type - set to “threedsecure”

  • noredirect - indicates whether platform returns a status object with required fields for 3D Secure instead of doing a redirect when 3D Secure authorization is required, default is F

    Note the following:

    • If noredirect is set to F threedsecure , redirect goes to the default 3D Secure authorization page.

    • If noredirect is set to T when 3D Secure authorization is required, the submit method returns the order status as error, with a reason code of ERR_WS_REQ_PAYMENT_AUTHORIZATION, along with values for the paymentauthorization JSON object. You can use these values to handle the integration with 3D Secure.

  • termurl - URL for client-side handler to process 3D Secure callback, to submit order with 3D Secure response parameters

In addition to the .ss file, 3D secure integration requires client-side code to display 3D Secure information in the user interface and to provide order handling. For examples of this code, see the following:

Note

Integration with third party checkout providers is not available for SSP applications written in Suitescript 2.0.


Sample .ss File for 3D Secure Integration

function service(request,response)
{
   var returnval = null;
   
   try
   {
      var shoppingSession = nlapiGetWebContainer().getShoppingSession();
      
      var shipMethod = shoppingSession.getOrder().getShippingMethod();
      
      if (!shipMethod || !shipMethod.shipMethod)
      {
         var shipMethods = shoppingSession.getOrder().getAvailableShippingMethods();
         nlapiLogExecution("DEBUG", "setShippingMethod", JSON.stringify(shipMethods));
         shoppingSession.getOrder().setShippingMethod(shipMethods[0]);
      }
      
      var orderHandlerUrl = shoppingSession.getAbsoluteUrl('checkout', 'samplePlaceOrder.ss');
      var orderSetting = {paymentauthorization:{type: 'threedsecure', noredirect : 'T', termurl : orderHandlerUrl}};
      returnval = shoppingSession.getOrder().submit(orderSetting);
   }
   catch (e)
   {
      var nle = nlapiCreateError(e);
      returnval = {status : 'error', reasoncode : nle.getCode(), message : nle.getDetails()};
   }
   response.writeLine(JSON.stringify(returnval)); 

Sample for Adding 3D Secure Frame in User Interface

<html>
<head><%=getPageFullHead()%>
<!--add css, js packages here -->
<link rel="stylesheet" type="text/css" href="css/style2.css" >
<script language='JavaScript' type='text/javascript'>
try {
   if (window.parent != window && window.parent.document.getElementById('threedsecureframe') != null) { window.parent.location.href = window.location.href; }
   } catch(e){ }
</script>
<script type="text/javascript" src="lib/sampleShoppingLib.js"></script>
<script type="text/javascript" src="lib/sampleClientLib.js"></script>
</head>   
<body onLoad="loadShoppingCart();">

<table cellpadding=0 cellspacing=0 border=0 width=100%><NLPAGETOP></table>

<%nlapiGetWebContainer().getPageGenerator().setSelectedTab(3);%>
<table width="100%">
<tr>
<td><div id="mainContents"></div></td>
</tr>
</table>
<table border=0>
<% var checkoutSettings = nlapiGetWebContainer().getShoppingSession().getSiteSettings(['checkout']); 
var paypalUrl = nlapiGetWebContainer().getShoppingSession().getAbsoluteUrl("checkout", "samplePaypalCheckout.ss");
<tr>
<td>
<input type="submit" name="placeorder" id="placeorder" value="Submit" style="" class="nlbutton" onclick="placeOrder()">
</td>
<td>&nbsp;</td>
<td >
<form name='paypalform' action='<%=paypalUrl%>' method='post'>
<input type='image' src='<%=checkoutSettings.checkout.paypalexpress.imageurl%>' class="nlbutton"/>
</form>
</a>
</td>
</tr>
</table>
<div id="paymentauthenticator"></div>
</body>
</html> 

Sample Client-Side Handler for 3D Secure Order Submission

function placeOrderCallBack(req)
{
    var responseObj = JSON.parse(req.responseText);
    if (responseObj.statuscode && responseObj.statuscode == "error")
    {
        // Order is not successful since payment authorization is required
        if (responseObj.reasoncode && responseObj.reasoncode == "ERR_WS_REQ_PAYMENT_AUTHORIZATION")
        {
            if (responseObj.paymentauthorization)
            {
                // grab the frame html for threedsecure and inject it into the page. this will trigger the autherization flow
                document.getElementById('paymentauthenticator').innerHTML = responseObj.paymentauthorization.servicehtml;
                var placeOrderBtn = document.getElementById('placeorder');
                if (placeOrderBtn)
                    placeOrderBtn.parentNode.removeChild(placeOrderBtn);
                var paypalBtn = document.getElementById('paypalcheckout');
                if (paypalBtn)
                    paypalBtn.parentNode.removeChild(paypalBtn);
                
            }
        }
    }
 
}
function service(request,response)
{
   var returnval = null;
 
   try
   {
      var shoppingSession = nlapiGetWebContainer().getShoppingSession();
      var orderHandlerUrl = shoppingSession.getAbsoluteUrl('checkout', 'samplePlaceOrder.ss');
        var orderSetting = {paymentauthorization:{type: 'threedsecure', noredirect : 'T', termurl : orderHandlerUrl}};
        returnval = shoppingSession.getOrder().submit(orderSetting);   }
   catch (e)
   {
      var nle = nlapiCreateError(e);
      returnval = {status : 'error', reasoncode : nle.getCode(), message : nle.getDetails()};
   }
   response.writeLine(JSON.stringify(returnval));
function placeOrderCallBack(req)
{
   var responseObj = JSON.parse(req.responseText);
   if (responseObj.statuscode && responseObj.statuscode == "error")
   {
      // Order is not success since payment autherization is required
      if (responseObj.reasoncode && responseObj.reasoncode == "ERR_WS_REQ_PAYMENT_AUTHORIZATION")
      {
         if (responseObj.paymentauthorization)
         {
            // grab the frame html for threedsecure and inject it into the page. this will trigger the autherization flow
            document.getElementById('paymentauthenticator').innerHTML = responseObj.paymentauthorization.servicehtml;
            var placeOrderBtn = document.getElementById('placeorder');
            if (placeOrderBtn)
               placeOrderBtn.parentNode.removeChild(placeOrderBtn);
            var paypalBtn = document.getElementById('paypalcheckout');
            if (paypalBtn)
               paypalBtn.parentNode.removeChild(paypalBtn);
         }
      }
   }
 
}

sampleShoppingLib.js

function createCartItemRow(nlCartItem, itemAttributes)
{
   var row = document.createElement('tr');
   
   for (var i = 0; i < itemAttributes.length; i++)
   {
      row.appendChild(createCartItemCell(getCartItemAttributeText(itemAttributes[i], nlCartItem[itemAttributes[i]])));
   }

   return row;
}
function getCartItemAttributeText(attrName, attrValue)
{
   if (attrName === 'options')
   {
      var attrText = '';
      if (attrValue)
      {
         for (var i = 0; i < attrValue.length; i++)
         {
            var itemOption = attrValue[i];
            attrText += itemOption.name + ':' + itemOption.displayvalue + '\n';
         }
      }
      return attrText;
   }
   else
      return attrValue;
}

function createCartItemCell(nlCartItemAttr)
{
   var cell = document.createElement('td');
   cell.setAttribute('class', 'texttable');
   var txtCell = document.createTextNode(nlCartItemAttr);
   cell.appendChild(txtCell);
   return cell;
}

function createCartTableHeader(headerItems)
{
   var theader = document.createElement('thead');
   theader.setAttribute('id', 'carttableheader');
   for (var i = 0; i < headerItems.length; i++)
   {
      theader.appendChild(createCartHeaderCell(headerItems[i]));
   }
   return theader;
}
function createCartHeaderCell(nlCartHeaderItem)
{
   var cell = document.createElement('th');
   var txtCell = document.createTextNode(nlCartHeaderItem);
   cell.appendChild(txtCell);
   return cell;
}

function createShoppingCart(nlShoppingOrder)
{   
   var headerItems = ['Name', 'Description', 'Options', 'Quantity', 'Rate', 'Amount'];
   var itemAttributes = ['name', 'salesdesc', 'options', 'quantity', 'rate', 'amount'];   
   var shoppingCart = document.createElement('table');
   shoppingCart.setAttribute('id', 'carttable');
   shoppingCart.setAttribute('width', '100%');
   
   var theader = createCartTableHeader(headerItems);
   shoppingCart.appendChild(theader);

   var tbody = document.createElement('tbody');
   
   if (nlShoppingOrder && nlShoppingOrder.items)
   {
      for (var i = 0; i < nlShoppingOrder.items.length; i++)
      {
         tbody.appendChild(createCartItemRow(nlShoppingOrder.items[i], itemAttributes));
      }
   }

   shoppingCart.appendChild(tbody);
   document.getElementById('mainContents').appendChild(shoppingCart);
}

function loadShoppingCart() {
   sendRequest('sampleGetOrderFields.ss', loadShoppingCartCallback);
   sendRequest('sampleGetCheckoutUrl.ss', loadCheckoutSettingCallback);
}

function loadCheckoutSetting() {
   sendRequest('sampleGetCheckoutUrl.ss', loadCheckoutSettingCallback);
}

function loadCheckoutSettingCallback(req) {
   var checkoutSetting = JSON.parse(req.responseText);
   var paypalBtn = document.getElementById('paypalcheckout');
   if (paypalBtn)
      paypalBtn.href = checkoutSetting.paypalexpress;
   }

function loadShoppingCartCallback(req) {
   //render the items table
   var order = JSON.parse(req.responseText);
   createShoppingCart(order);
}

function placeOrder() 
{
   sendRequest('samplePlaceOrder.ss', placeOrderCallBack);
}
function placeOrderCallBack(req)
{   
   var responseObj = JSON.parse(req.responseText);
   if (responseObj.statuscode && responseObj.statuscode == "error")
   {
      // Order is not success since payment autherization is required
      if (responseObj.reasoncode && responseObj.reasoncode == "ERR_WS_REQ_PAYMENT_AUTHORIZATION")
      {
         if (responseObj.paymentauthorization) 
         {
            // grab the frame html for threedsecure and inject it into the page. this will trigger the autherization flow
            document.getElementById('paymentauthenticator').innerHTML = responseObj.paymentauthorization.servicehtml;
            var placeOrderBtn = document.getElementById('placeorder');
            if (placeOrderBtn)
               placeOrderBtn.parentNode.removeChild(placeOrderBtn);
            var paypalBtn = document.getElementById('paypalcheckout');
            if (paypalBtn)
               paypalBtn.parentNode.removeChild(paypalBtn);
         }
      }
   }

}

sampleClientLib.js

function sendRequest(url,callback,postObjName, postData) {
   var req = createXMLHTTPObject();
   if (!req) return;
   var method = (postData) ? "POST" : "GET";
   req.open(method,url,true);
   req.setRequestHeader('User-Agent','XMLHTTP/1.0');
   if (postData) {
      req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
      req.setRequestHeader(postObjName, JSON.stringify(postData));
      }
   req.onreadystatechange = function () {
      if (req.readyState != 4) return;
      if (req.status != 200 && req.status != 304) {
//         alert('HTTP error ' + req.status);
         return;
      }
      callback(req);
   }
   if (req.readyState == 4) return;
   req.send();
   //req.send(postData);
}

var XMLHttpFactories = [
   function () {return new XMLHttpRequest()},
   function () {return new ActiveXObject("Msxml2.XMLHTTP")},
   function () {return new ActiveXObject("Msxml3.XMLHTTP")},
   function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
   var xmlhttp = false;
   for (var i=0;i<XMLHttpFactories.length;i++) {
      try {
         xmlhttp = XMLHttpFactories[i]();
      }
      catch (e) {
         continue;
      }
      break;
   }
   return xmlhttp;
}

samplePaypalCheckout.ss

function service(request,response)
{
   var returnval = null;
   
   try
   {
      
      var shoppingSession = nlapiGetWebContainer().getShoppingSession();
      var siteSetting = shoppingSession.getSiteSettings(['touchpoints']);
   
      var viewcart = siteSetting.touchpoints.viewcart;
      var homeurl = siteSetting.touchpoints.home;
      var checkouturl = siteSetting.touchpoints.checkout;
      
      var testUrl = shoppingSession.getAbsoluteUrl('/sampleGcoCheckout.ss');
      var testUrl2 = shoppingSession.getAbsoluteUrl('lib/sampleShoppoingLib.js');
   
      var paypalSetting = {type: 'paypalexpress', continueurl : checkouturl, cancelurl : viewcart};
   
      nlapiGetWebContainer().getShoppingSession().proceedToCheckout(paypalSetting);
   }
   catch (e)
   {
      var nle = nlapiCreateError(e);
      returnval = {status : 'error', reasoncode : nle.getCode(), message : nle.getDetails()};
      
      response.writeLine(JSON.stringify(returnval));
   }
}