SFCC Cartridge
Testing
Phone and Offline Order Tests
5 min
if you currently accept orders placed by customers over the phone or have employees who will place retail customer orders through your sfcc oms and want decisions for these order types , please review the \[forter phone solution]\( / /fraud management/checkout/phone orders md) integration options your onboarding team should also be made aware of any designated customer support center ip addresses, email addresses, or wholesale customers so additional analytical adjustments can be made on forter's side review the mapping for offline orders all offline orders or orders placed by employees directly through your oms, should be tagged as ordertype "phone" make sure to update the code in your forterorder ds file () to include logic that will update the ordertype to "phone" in the request object below is an example of how the ordertype key and connection object should appear for a phone order { "orderid" "test order 6469", "ordertype" "phone", "timesenttoforter" 1568128922841, "checkouttime" 1568128908000, "connectioninformation" { "customerip" "127 0 0 1", "useragent" "pca" } } sample forterorder ds file with phone order var forterlogger = require("int forter/cartridge/scripts/lib/forter/forterlogger ds"); / forterorder class is the dto object for request to include this script use var forterorder = require("int forter/cartridge/scripts/lib/forter/dto/forterorder ds"); / function forterorder(args) { var log = new forterlogger("forterorder ds"), order = args order, site = dw\ system site getcurrent(), paymentinstruments = order getpaymentinstruments(), a = null, authresponse = null, shipment = null; for each (var paymentinstrument in paymentinstruments) { if (paymentinstrument paymentmethod == 'credit card') { a = paymentinstrument; authresponse = args creditcardauthresponse; } else { a = paymentinstrument; authresponse = {}; } forterordertype = function { for each (var type in ordertype) { if (ordertype type == 'sfcc storefront web') { return "web"; } else if (ordertype type == 'ps g direct oms' || ordertype type == 'customer/ phone order') { return "phone" } } // general parameters this orderid = order originalorderno; // required this ordertype = order forterordertype; // "web" for web orders, "mobile" for app orders this timesenttoforter = (new date()) gettime(); // required this checkouttime = new number((order creationdate gettime()/1000) tofixed()); // required //must be seconds, not milliseconds this connectioninformation = new forterconnectioninformation(order); // required // calculate totals this totalamount = {}; // required this totalamount amountlocalcurrency = order totalgrossprice value tofixed(2); this totalamount currency = order totalgrossprice currencycode; this amountusd = order totalgrossprice value this additionalidentifiers = { 'merchant' { 'merchantname' site id, 'merchantdomain' site id + ' com' } } //calculate totals for discounts var ordertotal = order getmerchandizetotalprice(), adjordertotal = order getadjustedmerchandizetotalprice(), shiptotal = order getshippingtotalprice(), adjshiptotal = order getadjustedshippingtotalprice(), total = ordertotal add(shiptotal), adjtotal = adjordertotal add(adjshiptotal); // discounts var discountprice = 0; var couponname = ''; var coupontype = ''; if (!order getcouponlineitems() isempty()) { var coupons = order getcouponlineitems(); var couponnames = \[]; for each (let coup in coupons) { couponnames push(coup getcouponcode()); if (!coup getpriceadjustments() isempty()) { var coupadjustments = coup getpriceadjustments(); for each (let coupadj in coupadjustments) { discountprice += coupadj pricevalue; } } } couponname = couponnames join(","); discountprice = discountprice ( 1); if (discountprice > 0) { this totaldiscount = {}; // optional this totaldiscount couponcodeused = couponname substring(0,20); // required this totaldiscount coupondiscountamount = {}; // required this totaldiscount coupondiscountamount amountlocalcurrency = discountprice tofixed(2); this totaldiscount coupondiscountamount currency = order currencycode; this totaldiscount discounttype = "coupon"; // required } } // customer's details this accountowner = new fortercustomer(order); // cart items (regular product) this cartitems = \[]; // required for each (var pli in order productlineitems) { this cartitems push(new fortercartitem(pli)); } // cart items (gift certificate) for each (var gcli in order giftcertificatelineitems) { this cartitems push(new fortercartitem(gcli)); } // payments this a = \[]; // required this a push(new forterpayment(order, authresponse, a , log)); // delivery and recipient (shipping information) if (order shipments length > 0) { shipment = order shipments\[0]; this primarydeliverydetails = {}; this primarydeliverydetails deliveryprice = {}; this primarydeliverydetails deliverymethod = (!empty(shipment getshippingmethod()) && !empty(shipment getshippingmethod() getdisplayname())) ? shipment getshippingmethod() getdisplayname() ""; //"by air"; var deliverytype = "physical"; //default value if (order productlineitems size() > 0 && order giftcertificatelineitems size() == 0) { deliverytype = "physical"; //if real products only } else if (order productlineitems size() == 0 && order giftcertificatelineitems size() > 0) { deliverytype = "digital"; //if gift certificates only this primarydeliverydetails deliverymethod = "email"; } else if (order productlineitems size() > 0 && order giftcertificatelineitems size() > 0) { deliverytype = "hybrid"; //if gift certificates and real products } this primarydeliverydetails deliverytype = deliverytype; this primarydeliverydetails deliveryprice amountlocalcurrency = shipment adjustedshippingtotalprice value tofixed(2); this primarydeliverydetails deliveryprice currency = shipment adjustedshippingtotalprice currencycode tostring(); if (shipment productlineitems size() > 0) { this primaryrecipient = {}; // optional this primaryrecipient personaldetails = {}; this primaryrecipient personaldetails firstname = shipment shippingaddress firstname; //from the shipping address this primaryrecipient personaldetails lastname = shipment shippingaddress lastname; //from the shipping address this primaryrecipient address = {}; this primaryrecipient address address1 = shipment shippingaddress address1; this primaryrecipient address address2 = !empty(shipment shippingaddress address2) ? shipment shippingaddress address2 ""; this primaryrecipient address zip = shipment shippingaddress postalcode; this primaryrecipient address city = shipment shippingaddress city; this primaryrecipient address region = shipment shippingaddress statecode; this primaryrecipient address country = shipment shippingaddress countrycode value touppercase(); this primaryrecipient phone = \[]; if (!empty(shipment shippingaddress phone)){ this primaryrecipient phone push(new forterphone(shipment shippingaddress phone)); } } else if (shipment giftcertificatelineitems size() > 0) { this primaryrecipient = {}; // optional this primaryrecipient personaldetails = {}; this primaryrecipient personaldetails fullname = shipment giftcertificatelineitems\[0] recipientname; //from the gift form this primaryrecipient personaldetails email = shipment giftcertificatelineitems\[0] recipientemail; //from the gift form } if (shipment gift == true) { this primaryrecipient comments = {}; this primaryrecipient comments messagetobeneficiary = shipment giftmessage ? shipment giftmessage ""; } } function forterconnectioninformation(order) { this customerip = request httpremoteaddress; // required this useragent = request httpuseragent; for (var i = 0; i < request httpcookies cookiecount; i++) { if (request httpcookies\[i] name == "fortertoken") { this fortertokencookie = request httpcookies\[i] value; // required } } this useragent = request httpuseragent; // required this fortertokencookie = ""; // conditional for (var i = 0; i < request httpcookies cookiecount; i++) { if (request httpcookies\[i] name == "fortertoken") { this fortertokencookie = request httpcookies\[i] value; } } } } function fortercustomer(order) { if (order customer profile != null) { this firstname = order customer profile firstname; this lastname = order customer profile lastname; this email = order customer profile email; this accountid = order customer id; this created = new number((order customer profile getcreationdate() gettime()/1000) tofixed()); var query = "customerno = {0} and paymentstatus = {1}"; var allorders seekableiterator = dw\ order ordermgr searchorders(query, "creationdate desc", order customer profile customerno, 2); this pastorderscount = new number(allorders count); } else { this firstname = order billingaddress firstname; this lastname = order billingaddress lastname; this email = order customeremail; } } function forterapplepay(auth, ap) { // where var ap is the raw applepay response data from your payment gateway var processorresponsecode = "", processorresponsetext = ""; // format the expiration month from 1 to 01, etc if (ap creditcardexpirationmonth tostring() length == 1) { var creditcardexpmonth = "0" + cc creditcardexpirationmonth tostring(); } else { var creditcardexpmonth = cc creditcardexpirationmonth tostring(); } this nameoncard = ap creditcardholder; this cardbrand = ap creditcardtype; this token = ap token; this lastfourdigits = ap creditcardnumberlastdigits; //optional this expirationmonth = creditcardexpmonth; this expirationyear = cc creditcardexpirationyear tostring(); this verificationresults = {}; this verificationresults avsfullresult = auth avs tostring(); // optional this verificationresults cvvresult = auth cvd code tostring(); // optional this verificationresults authorizationcode = auth authorization num tostring(); processorresponsecode = auth exact resp code tostring(); processorresponsetext = auth exact message tostring(); this verificationresults processorresponsecode = processorresponsecode; this verificationresults processorresponsetext = processorresponsetext; } function fortercartitem(item) { this basicitemdata = {}; if (item instanceof dw\ order productlineitem) { this basicitemdata productid = item productid; //optional this basicitemdata name = item productname; //required this basicitemdata quantity = item quantityvalue; //required var product = item getproduct(); if (product getcategories() isempty() && !empty(product getvariationmodel())) { product = product getvariationmodel() getmaster(); } this basicitemdata category = empty(product) ? "" product getcategories()\[0] getdisplayname(); this basicitemdata type = "tangible"; // add if type is available change according to the actual item type //if any adjustements this basicitemdata price = {}; this basicitemdata price amountlocalcurrency = item adjustedprice value tofixed(2); this basicitemdata price currency = item adjustedprice currencycode tostring(); } if (item instanceof dw\ order giftcertificatelineitem) { this basicitemdata name = item lineitemtext; //required this basicitemdata quantity = 1; //required (set 1 by default for a gift cert?) this basicitemdata type = "non tangible"; // add if type is available change according to the actual item type this deliverydetails = {}; this deliverydetails deliverytype = "digital"; this deliverydetails deliverymethod = "email"; this basicitemdata price = {}; this basicitemdata price amountlocalcurrency = item price value tofixed(2); this basicitemdata price currency = item price currencycode tostring(); this beneficiaries = \[]; this beneficiaries push(new forterbeneficiarydetailsfromgiftcard(item)); } } module exports = forterorder; step 1 confirm decision enablement for phone orders by default, forter's sandbox environment will return a not reviewed decision for phone orders if you would like forter to decision phone orders, make sure that phone order decisions have been enabled for your sandbox environment step 2 testing any email address place a phone order in your sandbox environment using any valid test email address the transaction should show in the portal transactions tab https //portal forter com/transactions and include a phone icon next to the order number declined by forter place a purchase with email address decline\@forter com using a valid test card credit card or payment method this email address will always generate a "decline" decision in forter's sandbox environment and will enable you to test your sfcc cartridge flow for a declined mobile transaction once you've placed this declined order, please check your cartridge business manager and review and (potentially update) your processorresponse json file to either void funds and cancel declined mobile app orders approved by forter create an order using approve\@forter com and a valid test card for the transaction this will generate an "approve" decision and the transaction should show in the portal transactions tab https //portal forter com/transactions and include a phone icon next to the order number make sure to review and update your processorresponse json file to capture the funds and proceed with this order in your oms