SFRA
SFRA Post-Auth Integration
Overview
The below code and instructions are based on the SFRA structure and the section includes a list of all affected controllers.
The relevant SFRA section of the Forter cartridge can be found using the following path in the cartridge
Cartridges >
int_forter_sfra
>
cartridge
>
controllers
>
CheckoutService.js
Integration of the cartridge into your storefront application does not require any modifications to your core cartridge. Instead, we recommend overwriting the existing code in the cartridge. In cases where the storefront application has the same controllers or templates extended or replaced, all affected code modifications must be added to the top level cartridge of the storefront application.
Calling the ForterValidate.js file
Note that the ForterValidate.js file should be called in your actual payment gateway controller (CyberSource, Adyen, Braintree, etc.) as part of the existing authorization flow. Call a require method within the actual gateway authorization. In the below example, its defined as part of the function forterCall.
forterCall = require('int_forter_mfra/cartridge/scripts/pipelets/forter/ForterValidate'),MFRA Code Example
Below is code from the Authorize.net AUTHORIZE_NET-Authorize controller which is triggered as part of authorization flow via the SFRA Integration.
Sample Authorize.net checkout flow (MFRA based)
function Authorize(orderNumber, paymentInstrument, paymentProcessor) {
var serverErrors = [],
fieldErrors = {},
error = false;
try {
Transaction.wrap(function () {
paymentInstrument.paymentTransaction.setTransactionID(orderNumber);
paymentInstrument.paymentTransaction.setPaymentProcessor(paymentProcessor);
});
var argCCAuth = {
orderNumber : orderNumber,
PaymentInstrument : paymentInstrument
},
authResponse = doAuth(argCCAuth);
if (authResponse.result === false) {
var argOrderValidate = {
orderNumber : orderNumber,
orderValidateAttemptInput : 1
},
forterCall = require('int_forter_mfra/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
},
forterCall = require('int_forter_mfra/cartridge/scripts/pipelets/forter/ForterValidate'),
forterDecision = forterCall.validateOrder(argOrderValidate);
}
error = true;
serverErrors.push(
Resource.msg('error.technical', 'checkout', null)
);
}
if (authResponse.result === true) {
var argOrderValidate = {
orderNumber : orderNumber,
orderValidateAttemptInput : 1
},
forterCall = require('int_forter_mfra/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
};
forterCall = require('int_forter_mfra/cartridge/scripts/pipelets/forter/ForterValidate'),
forterDecision = forterCall.validateOrder(argOrderValidate);
}
if (forterDecision.JsonResponseOutput.processorAction === 'skipCapture' || forterDecision.JsonResponseOutput.processorAction === 'notReviewed') {
error = false;
} else if (forterDecision.JsonResponseOutput.processorAction === 'disabled' || forterDecision.JsonResponseOutput.processorAction === 'internalError' || forterDecision.JsonResponseOutput.processorAction === 'capture') {
var argCCCapture = {
AuthorizeNetResponse : authResponse.AuthorizeNetResponse,
orderNumber : orderNumber,
PaymentInstrument : paymentInstrument
},
captureResponse = doCapture(argCCCapture);
if (captureResponse.result === true) {
error = false;
}
if (captureResponse.result === false) {
var argVoid = {
AuthorizeNetResponse : authResponse.AuthorizeNetResponse,
orderNumber : orderNumber,
PaymentInstrument : paymentInstrument
},
voidResponse = doVoid(argVoid);
error = true;
serverErrors.push(
Resource.msg('error.technical', 'checkout', null)
);
}
} else {
var argVoid = {
AuthorizeNetResponse : authResponse.AuthorizeNetResponse,
orderNumber : orderNumber,
PaymentInstrument : paymentInstrument
},
voidResponse = doVoid(argVoid);
error = true;
serverErrors.push(
Resource.msg('error.technical', 'checkout', null)
);
}
}
} catch (e) {
error = true;
serverErrors.push(
Resource.msg('error.technical', 'checkout', null)
);
}
return { fieldErrors: fieldErrors, serverErrors: serverErrors, error: error };
}
function doAuth(argCCAuth) {
var authorizenetCCAuthRequest = require('~/cartridge/scripts/pipelets/AuthorizenetCCAuthRequest'),
authResponse = authorizenetCCAuthRequest.execute(argCCAuth);
return authResponse;
}
function doCapture(argCCCapture) {
var authorizenetCCCaptureRequest = require('~/cartridge/scripts/pipelets/AuthorizenetCCCaptureRequest'),
captureResponse = authorizenetCCCaptureRequest.execute(argCCCapture);
return captureResponse;
}
function doVoid(argVoid) {
var authorizenetVoidRequest = require('~/cartridge/scripts/pipelets/AuthorizenetVoidRequest'),
voidResponse = authorizenetVoidRequest.execute(argVoid);
return voidResponse;
}Sample MFRA Helper Script
The script below is based on the CyberSource checkout flow to handle returning a Forter decision to the payment processor and automate the nadling of each order.
S****ample Helper Script
/**
* Helper script for calling Forter from payment processor scripts
*
*/
var forterCall = require('int_forter_mfra/cartridge/scripts/pipelets/forter/ForterValidate');
function callForter(authResponses, orderNumber) {
var argOrderValidate = {
orderNumber: orderNumber,
authResponses: authResponses,
orderValidateAttemptInput: 1
};
try {
var forterDecision = forterCall.validateOrder(argOrderValidate);
// in case if no response from Forter, try to call one more time
if (forterDecision.result === false && forterDecision.orderValidateAttemptInput == 1) {
var argOrderValidate = {
orderNumber: orderNumber,
authResponses: authResponses,
orderValidateAttemptInput: 2
};
var forterDecision = forterCall.validateOrder(argOrderValidate);
}
if (forterDecision.JsonResponseOutput.processorAction === 'skipCapture' || forterDecision.JsonResponseOutput.processorAction === 'notReviewed') {
return forterDecision;
} else {
if (!empty(forterDecision.PlaceOrderError)) {
return {error : true, forterErrorCode : forterDecision.PlaceOrderError};
} else {
return forterDecision;
}
}
} catch (e) {
return {error : true};
}
}