SFCC Cartridge
...
Pre-Auth Credit Card
SFRA
10 min
sfra pre auth integration the instructions below should be used for a pre authorization forter integration for all storefronts using the sfra version of the sfcc storefront update your checkoutservices js file go to the checkoutservices js file in your forter cartridge the exact path to this file is cartridges > int forter sfra > cartridge > controllers > checkoutservice js open this file and uncomment the following code after the var order = cohelpers createorder(currentbasket); function and before the var handlepaymentresult = cohelpers handlepayments(order, order orderno); function in the file var ordernumber = order getcurrentorderno(); var argordervalidate = { ordernumber ordernumber, ordervalidateattemptinput 1, authorizationstep “pre authorization” }, fortercall = require(‘ /cartridge/scripts/pipelets/forter/fortervalidate’), forterdecision = fortercall validateorder(argordervalidate); // in case if no response from forter, try to call one more time if (forterdecision result === false && forterdecision ordervalidateattemptinput == 2) { var argordervalidate = { ordernumber ordernumber, ordervalidateattemptinput 2, authorizationstep “pre authorization” }, fortercall = require(‘ /cartridge/scripts/pipelets/forter/fortervalidate’), forterdecision = fortercall validateorder(argordervalidate); } if (forterdecision jsonresponseoutput processoraction == ‘void’) { transaction wrap(function () { ordermgr failorder(order, true); }); if (!empty(forterdecision placeordererror)) { res json({ error true, errormessage forterdecision placeordererror code }); } else { res json({ error true, errormessage resource msg(‘error technical’, ‘checkout’, null) }); } this emit(‘route\ complete’, req, res); return; } the screenshot and full code checkoutservices js file included below show where this additional code should be placed within the checkoutservices js file full checkoutservices js file with pre auth 'use strict'; var server = require('server'); server extend(module supermodule); var cohelpers = require(' /cartridge/scripts/checkout/checkouthelpers'); var csrfprotection = require(' /cartridge/scripts/middleware/csrf'); var forterconfig = require('int forter mfra/cartridge/scripts/lib/forter/forterconfig ds') forterconfig; server replace('placeorder', server middleware https, function (req, res, next) { var basketmgr = require('dw/order/basketmgr'); var hookmgr = require('dw/system/hookmgr'); var ordermgr = require('dw/order/ordermgr'); var resource = require('dw/web/resource'); var transaction = require('dw/system/transaction'); var urlutils = require('dw/web/urlutils'); var basketcalculationhelpers = require(' /cartridge/scripts/helpers/basketcalculationhelpers'); var currentbasket = basketmgr getcurrentbasket(); if (!currentbasket) { res json({ error true, carterror true, fielderrors \[], servererrors \[], redirecturl urlutils url('cart show') tostring() }); return next(); } if (req session privacycache get('frauddetectionstatus')) { res json({ error true, carterror true, redirecturl urlutils url('error errorcode', 'err', '01') tostring(), errormessage resource msg('error technical', 'checkout', null) }); return next(); } var validationbasketstatus = hookmgr callhook( 'app validate basket', 'validatebasket', currentbasket, false ); if (validationbasketstatus error) { res json({ error true, errormessage validationbasketstatus message }); return next(); } // check to make sure there is a shipping address if (currentbasket defaultshipment shippingaddress === null) { res json({ error true, errorstage { stage 'shipping', step 'address' }, errormessage resource msg('error no shipping address', 'checkout', null) }); return next(); } // check to make sure billing address exists if (!currentbasket billingaddress) { res json({ error true, errorstage { stage 'payment', step 'billingaddress' }, errormessage resource msg('error no billing address', 'checkout', null) }); return next(); } // calculate the basket transaction wrap(function () { basketcalculationhelpers calculatetotals(currentbasket); }); // re validates existing payment instruments var validpayment = cohelpers validatepayment(req, currentbasket); if (validpayment error) { res json({ error true, errorstage { stage 'payment', step 'paymentinstrument' }, errormessage resource msg('error payment not valid', 'checkout', null) }); return next(); } // re calculate the payments var calculatedpaymenttransactiontotal = cohelpers calculatepaymenttransaction(currentbasket); if (calculatedpaymenttransactiontotal error) { res json({ error true, errormessage resource msg('error technical', 'checkout', null) }); return next(); } // creates a new order var order = cohelpers createorder(currentbasket); if (!order) { res json({ error true, errormessage resource msg('error technical', 'checkout', null) }); return next(); } // add or uncomment the new pre auth code here var argordervalidate = { order order, ordervalidateattemptinput 1 }, fortercontroller = require('int forter/cartridge/controllers/fortervalidate'), forterdecision = fortercontroller validateorder(argordervalidate); // in case if no response from forter, try to call one more time if (forterdecision result === false && forterdecision ordervalidateattemptinput == 2) { var argordervalidate = { order order, ordervalidateattemptinput 2 }, fortercontroller = require('int forter/cartridge/controllers/fortervalidate'), forterdecision = fortercontroller validateorder(argordervalidate); } if (forterdecision jsonresponseoutput processoraction == 'void') { if (!empty(forterdecision placeordererror)) { return {error true, fortererrorcode forterdecision placeordererror}; } else { return {error true}; } } // end of pre auth code var handlepaymentresult = cohelpers handlepayments(order, order orderno); // handles payment authorization if (handlepaymentresult error) { if (forterconfig fortershowdeclinedpage == true && !empty(forterconfig fortercustomdeclinemessage)) { res json({ error true, errormessage forterconfig fortercustomdeclinemessage }); } else { res json({ error true, errormessage resource msg('error technical', 'checkout', null) }); } return next(); } var frauddetectionstatus = hookmgr callhook('app fraud detection', 'frauddetection', currentbasket); if (frauddetectionstatus status === 'fail') { transaction wrap(function () { ordermgr failorder(order); }); // fraud detection failed req session privacycache set('frauddetectionstatus', true); res json({ error true, carterror true, redirecturl urlutils url('error errorcode', 'err', frauddetectionstatus errorcode) tostring(), errormessage resource msg('error technical', 'checkout', null) }); return next(); } // places the order var placeorderresult = cohelpers placeorder(order, frauddetectionstatus); if (placeorderresult error) { res json({ error true, errormessage resource msg('error technical', 'checkout', null) }); return next(); } cohelpers sendconfirmationemail(order, req locale id); // reset usingmultiship after successful order placement req session privacycache set('usingmultishipping', false); // todo exposing a direct route to an order, without at least encoding the orderid // is a serious pii violation it enables looking up every customers orders, one at a // time res json({ error false, orderid order orderno, ordertoken order ordertoken, continueurl urlutils url('order confirm') tostring() }); return next(); }); module exports = server exports(); option 1 pre auth and post auth decisions follow the steps below to receive a decision post authorization decision from forter in this flow, you'll receive a binary approve/decline decision prior to calling your payment gateway and after receiving an authorization response from your gateway 1\ include mapping for the post auth validation call after uncommenting the code in the checkoutservices js file, you'll need to customize the mapping in the forterorder js file ( cartridges > int forter sfra > cartridge > scripts > lib > forter > dto > forterorder js ) to include the authorization response from your gateway in the post auth call to forter the exact mapping can be found in the fortercreditcard(auth, cc) function within the verificationresults object sample forterorder js mapping function fortercreditcard(auth, cc) { var processorresponsecode = ''; var processorresponsetext = ''; var creditcardexpmonth; // format the expiration month from 1 to 01, etc if (cc creditcardexpirationmonth tostring() length === 1) { creditcardexpmonth = '0' + cc creditcardexpirationmonth tostring(); } else { creditcardexpmonth = cc creditcardexpirationmonth tostring(); } this nameoncard = cc creditcardholder; this cardbrand = cc creditcardtype; if (cc creditcardnumber substring(0, 6) indexof(' ') > 1) { this bin = session forms billing creditcardfields cardnumber value substring(0, 6); // session forms billing paymentmethods creditcard number value substring(0, 6); } else { this bin = cc creditcardnumber substring(0, 6); } this lastfourdigits = cc creditcardnumberlastdigits; this expirationmonth = creditcardexpmonth; this expirationyear = cc creditcardexpirationyear tostring(); this verificationresults = {}; this verificationresults avsfullresult = auth ? auth avsresultcode tostring() ''; // must be adjusted according to the payment gateway used this verificationresults cvvresult = auth ? auth cvvresultcode tostring() ''; // must be adjusted according to the payment gateway used this verificationresults authorizationcode = auth ? auth authcode tostring() ''; // must be adjusted according to the payment gateway used this paymentgatewaydata = {}; this paymentgatewaydata gatewayname = 'authorize net'; // must be adjusted according to the payment gateway used this paymentgatewaydata gatewaytransactionid = auth ? auth transid tostring() ''; // must be adjusted according to the payment gateway used if (auth && auth errors errorcode length > 0) { // must be adjusted according to the payment gateway used processorresponsecode = auth errors errorcode tostring(); // must be adjusted according to the payment gateway used processorresponsetext = auth errors errortext tostring(); // must be adjusted according to the payment gateway used } else if (auth && auth messages code length > 0) { // must be adjusted according to the payment gateway used processorresponsecode = auth messages code tostring(); // must be adjusted according to the payment gateway used processorresponsetext = auth messages description tostring(); // must be adjusted according to the payment gateway used } this verificationresults processorresponsecode = processorresponsecode; this verificationresults processorresponsetext = processorresponsetext; } 2\ update your business manager the additional code that you have added above to your checkoutservices js file allows your storefront to send order information to the forter endpoint before an authorization call is made to your payment gateway make update your forter business manager extension to show a customized error message for this updated pre authorization flow option 2 pre auth decisions with post auth order status in this configuration, you'll only receive a forter decision pre auth ( prior to calling your payment gateway) and the authorization response from the gateway will be included in a subsequent order status call to forter 1\ update the order status the example authorize net script below outlines how to update the script that handles credit card processing so that it includes the relevant post authorization order status call to forter note that the two default order statuses are "processing" (when the gateway has authorized the payment) "canceled by merchant" (when the gateway/processor has not authorized payment) the code example below applies to all sfra and sg pre auth/status implementations and the full postauthorderstatusupdate() function can be found in fortervalidate js file ( cartridges > int forter sfra > cartridge > scripts > pipelets > forter > fortervalidate js ) var argorderupdate = { ordernumber ordernumber, updateattempt 1 }, fortercall = require(' /cartridge/scripts/pipelets/forter/fortervalidate'), forterdecision = fortercall postauthorderstatusupdate(argorderupdate, "processing"); if (forterdecision result === false && forterdecision updateattempt == 2) { forterdecision updateattempt = 2; fortercall postauthorderstatusupdate(argorderupdate, "processing"); } 2\ customize forterupdate js file after uncommenting the pre auth code checkoutservices js file, customize the forterupdate js file to include your gateway's authorization response in the status call to forter the exact path to the forterupdate js file is cartridges > int forter sfra > cartridge > scripts > lib > forter > dto > forterupdate js ) customize the forterpayment(payment, order) function to map your specific gateway authorization response example fortercreditcard() auth function function fortercreditcard(auth, cc) { var processorresponsecode = ''; var processorresponsetext = ''; var creditcardexpmonth; // format the expiration month from 1 to 01, etc if (cc creditcardexpirationmonth tostring() length === 1) { creditcardexpmonth = '0' + cc creditcardexpirationmonth tostring(); } else { creditcardexpmonth = cc creditcardexpirationmonth tostring(); } this nameoncard = cc creditcardholder; this cardbrand = cc creditcardtype; if (cc creditcardnumber substring(0, 6) indexof(' ') > 1) { this bin = session forms billing creditcardfields cardnumber value substring(0, 6); // session forms billing paymentmethods creditcard number value substring(0, 6); } else { this bin = cc creditcardnumber substring(0, 6); } this lastfourdigits = cc creditcardnumberlastdigits; this expirationmonth = creditcardexpmonth; this expirationyear = cc creditcardexpirationyear tostring(); this verificationresults = {}; this verificationresults avsfullresult = auth ? auth avsresultcode tostring() ''; // must be adjusted according to the payment gateway used this verificationresults cvvresult = auth ? auth cvvresultcode tostring() ''; // must be adjusted according to the payment gateway used this verificationresults authorizationcode = auth ? auth authcode tostring() ''; // must be adjusted according to the payment gateway used this paymentgatewaydata = {}; this paymentgatewaydata gatewayname = 'authorize net'; // must be adjusted according to the payment gateway used this paymentgatewaydata gatewaytransactionid = auth ? auth transid tostring() ''; // must be adjusted according to the payment gateway used if (auth && auth errors errorcode length > 0) { // must be adjusted according to the payment gateway used processorresponsecode = auth errors errorcode tostring(); // must be adjusted according to the payment gateway used processorresponsetext = auth errors errortext tostring(); // must be adjusted according to the payment gateway used } else if (auth && auth messages code length > 0) { // must be adjusted according to the payment gateway used processorresponsecode = auth messages code tostring(); // must be adjusted according to the payment gateway used processorresponsetext = auth messages description tostring(); // must be adjusted according to the payment gateway used } this verificationresults processorresponsecode = processorresponsecode; this verificationresults processorresponsetext = processorresponsetext; } var billingaddress = order billingaddress; this billingdetails = {}; this billingdetails personaldetails = {}; this billingdetails personaldetails firstname = billingaddress firstname; this billingdetails personaldetails lastname = billingaddress lastname; if (billingaddress phone) { this billingdetails phone = \[]; this billingdetails phone push(new forterphone(billingaddress phone)); } this amount = { amountlocalcurrency order totalgrossprice value tofixed(2), currency order totalgrossprice currencycode }; if (payment) { if (payment paymentmethod === 'credit card') { this creditcard = new fortercreditcard(authresponse, payment); } } else { log error('no payment method information for order ' + order originalorderno); } } 3\ update your business manager the additional code that you have added above to your checkoutservices js file allows your storefront to send order information to the forter endpoint before an authorization call is made to your payment gateway you will also need to update your forter business manager extension to show a customized error message for this updated pre authorization flow