SFCC Cartridge
...
Mapping Samples
Braintree
1. Full ForterOrder.ds file using Braintree Gateway
Below is the full ForterOrder.ds file including the mapped authorization response for a merchant using the Braintree as the primary Gateway.
** Note that the majority of the mapping takes place in the ForterCreditCard(auth, cc) function. This specific function can be found in the next section, ForterCreditCard(auth, cc)
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(),
payment = null,
authResponse = null,
shipment = null;
for each (var paymentInstrument in paymentInstruments) {
if (paymentInstrument.paymentMethod == 'CREDIT_CARD') { //TODO: adjust to the existing payment instruments
payment = paymentInstrument;
authResponse = {
token: paymentInstrument.custom.braintreePaymentMethodToken,
transactionId: paymentInstrument.getPaymentTransaction().getTransactionID(),
payloadData: JSON.parse(paymentInstrument.custom.braintreeResponsePayloadData)
};
} else if (paymentInstrument.paymentMethod == 'PayPal' || paymentInstrument.paymentMethod == 'BML') { //TODO: adjust to the existing payment instruments
payment = paymentInstrument;
var paymentTransaction = paymentInstrument.getPaymentTransaction();
authResponse = {
transactionId: paymentTransaction.getTransactionID(),
payerId: paymentInstrument.custom.paypalPayerID,
paypalPaymentStatus: paymentInstrument.custom.paypalPaymentStatus,
paypalEmail: paymentInstrument.custom.paypalEmail,
paypalCorrelationId: paymentInstrument.custom.paypalCorrelationId
}
}
}
// General parameters
this.orderId = order.originalOrderNo; // Required
this.orderType = "WEB"; // Required
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.amountUSD = order.totalGrossPrice.value.toFixed(2);
//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.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.payment = []; // Required
this.payment.push(new ForterPayment(order, authResponse, payment, 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;
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.displayValue.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 ForterPayment(order, authResponse, payment, log) {
var billingAddress = order.billingAddress;
this.billingDetails = {};
this.billingDetails.personalDetails = {};
this.billingDetails.personalDetails.firstName = billingAddress.firstName;
this.billingDetails.personalDetails.lastName = billingAddress.lastName;
this.billingDetails.address = {};
this.billingDetails.address.address1 = billingAddress.address1;
this.billingDetails.address.address2 = !empty(billingAddress.address2) ? billingAddress.address2 : "";
this.billingDetails.address.zip = billingAddress.postalCode;
this.billingDetails.address.city = billingAddress.city;
this.billingDetails.address.region = billingAddress.stateCode;
this.billingDetails.address.country = billingAddress.countryCode.displayValue.toUpperCase();
if (!empty(billingAddress.phone)) {
this.billingDetails.phone = [];
this.billingDetails.phone.push(new ForterPhone(billingAddress.phone));
}
this.amount = {};
this.amount.amountUSD = order.totalGrossPrice.value.toFixed(2);
if (!empty(payment)) {
if (payment.paymentMethod == 'PayPal' || payment.paymentMethod == 'BML') {
this.paypal = new ForterPayPal(authResponse, billingAddress.countryCode.value.toUpperCase());
} else if (payment.paymentMethod == 'CREDIT_CARD') {
this.creditCard = new ForterCreditCard(authResponse, payment);
}
} else {
log.error('No payment method information for order: ' + order.originalOrderNo);
}
}
function ForterPhone(phone) {
this.phone = phone;
this.updateTimes = {
"creationTime": (new Date()).getTime(),
"removalTime": (new Date()).getTime()
};
}
function ForterPayPal(authResponse, countryCode) {
this.payerId = authResponse.payerId; //"FD000A45P";
this.payerEmail = authResponse.paypalEmail;
this.payerStatus = "VERIFIED"; //"VERIFIED";
this.payerAddressStatus = "CONFIRMED";//"CONFIRMED";
this.paymentMethod = "Paypal";
this.paymentStatus = authResponse.paypalPaymentStatus.toUpperCase(); //"PENDING"
this.payerAccountCountry = countryCode; //"US";
this.protectionEligibility = "ELIGIBLE"; //"ELIGIBLE";
this.correlationId = authResponse.paypalCorrelationId; //"fdshkj2390sdf";
this.paymentId = "";
this.authorizationId = authResponse.transactionId; //"2WC75407LV7300439";
this.fullPaypalResponsePayload = authResponse;
this.paymentGatewayData = {};
this.paymentGatewayData.gatewayName = "Paypal"; //TODO: must be adjusted according to the payment gateway used
this.paymentGatewayData.gatewayTransactionId = authResponse.transactionId;
}
function ForterCreditCard(auth, cc) {
// format the expiration month. from 1 to 01, etc.
if (cc.creditCardExpirationMonth.toString().length == 1) {
var creditCardExpMonth = "0" + cc.creditCardExpirationMonth.toString();
} else {
var creditCardExpMonth = cc.creditCardExpirationMonth.toString();
}
this.nameOnCard = cc.creditCardHolder;
this.cardBrand = cc.creditCardType;
this.bin = auth.payloadData.bin;
this.lastFourDigits = cc.creditCardNumberLastDigits;
this.expirationMonth = creditCardExpMonth;
this.expirationYear = cc.creditCardExpirationYear.toString();
this.verificationResults = {};
this.verificationResults.avsStreetResult = auth.payloadData.avsStreetResult;
this.verificationResults.avsZipResult = auth.payloadData.avsZipResult;
this.verificationResults.avsFullResult = auth.payloadData.avsFullResult;
this.verificationResults.cvvResult = auth.payloadData.cvvResult;
this.verificationResults.authorizationCode = auth.token;
this.paymentGatewayData = {};
this.paymentGatewayData.gatewayName = "Braintree";
this.paymentGatewayData.gatewayTransactionId = auth.transactionId;
this.verificationResults.processorResponseCode = "";
this.verificationResults.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.amountUSD = item.adjustedPrice.value.toFixed(2);
}
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.amountUSD = item.price.value.toFixed(2);
this.beneficiaries = [];
this.beneficiaries.push(new ForterBeneficiaryDetailsFromGiftCard(item));
}
}
function ForterBeneficiaryDetailsFromGiftCard(item) {
this.personalDetails = {};
this.comments = {};
this.personalDetails.fullName = item.recipientName;
this.personalDetails.email = item.recipientEmail;
this.comments.messageToBeneficiary = item.message ? item.message : "";
}
module.exports = ForterOrder;3. ForterCreditCard(auth, cc) Function
The ForterCreditCard function includes the recommended mapping from the Braintree authorization response payload received from the Braintree cartridge. Note in this example, that the path includes the auth.payloadData objects.
function ForterCreditCard(auth, cc) {
// format the expiration month. from 1 to 01, etc.
if (cc.creditCardExpirationMonth.toString().length == 1) {
var creditCardExpMonth = "0" + cc.creditCardExpirationMonth.toString();
} else {
var creditCardExpMonth = cc.creditCardExpirationMonth.toString();
}
this.nameOnCard = cc.creditCardHolder;
this.cardBrand = cc.creditCardType;
this.bin = auth.payloadData.bin;
this.lastFourDigits = cc.creditCardNumberLastDigits;
this.expirationMonth = creditCardExpMonth;
this.expirationYear = cc.creditCardExpirationYear.toString();
this.verificationResults = {};
this.verificationResults.avsStreetResult = auth.payloadData.avsStreetResult;
this.verificationResults.avsZipResult = auth.payloadData.avsZipResult;
this.verificationResults.avsFullResult = auth.payloadData.avsFullResult;
this.verificationResults.cvvResult = auth.payloadData.cvvResult;
this.verificationResults.authorizationCode = auth.token;
this.paymentGatewayData = {};
this.paymentGatewayData.gatewayName = "Braintree";
this.paymentGatewayData.gatewayTransactionId = auth.transactionId;
this.verificationResults.processorResponseCode = "";
this.verificationResults.processorResponseText = "";
}