Salesforce B2C Cartridge Integration

Installation and integration guide for Forter's B2C cartridge

Salesforce Commerce Cloud B2C Cartridge Integration

Forter's Salesforce B2C cartridge allows you to expedite your integration with Forter while taking advantage of the latest technology and functionality from Salesforce's B2C platform.

About the Cartridge

  • Forter’s SFCC LINK Cartridge is SFRA compatible and built by Salesforce-certified developers (OSF) using all SFRA best practices.
  • Forter's Cartridge is compatible with latest SFCC version (version 22.1, SFRA 6.1 as of March 2023) as well as legacy Controllers architecture.
  • You can access and download the newest version of the full Forter cartridge directly on the SFCC Partner marketplace. If you do not have an SFCC LINK account, or need an older version of the Forter SFCC cartridge, please contact your Forter onboarding team.

📘

Note: You will need a Forter account and credentials in order to complete the installation of your Forter SFCC Cartridge.

Installing the Cartridge: What's included

In addition to offering versions for both SFRA and Controllers, Forter's SFCC Cartridge includes two main components:

  1. Int_Forter - which includes the code, files, and templates needed to generate and place the the API requests to Forter's endpoints, inject the Forter JavaScript, and supply request mapping templates
  2. Bm_Forter - the Cartridge Business Manager functionality that generates a new "Forter" section in your SFCC platform business manager. In this section, you can set up your order status automations, select certain order actions based on fraud or policy decisions, view orders and Forter decisions, and export reports.

Integration

Forter's cartridge allows merchant flexibility in the placement of the Forter API calls as well as the functionality to handle and customize the handling of Forter decisions and/or policy-based API parameters. The steps below outline the installation flow and the steps needed to implement Forter's cartridge for decisions at checkout.

Step 1: Import the Cartridge and review your BM paths

  1. Connect to your Demandware server, select the Import option and then select “Existing Project into Workspace” option. In Import Projects → Select archive file (or “root directory”) if you have already unzipped the cartridge
  2. Import the Metadata from the Forter Cartridge
  • In the Metadata folder of the cartridge you will find a zip file called site_template.
  • Go to Administration > Site development > Site Import & Export and upload the zip file.
    From there, select your uploaded zip file, click “Import” and then click “OK” to complete.
  1. Cartridge paths
    Go to Administration > Sites > Manage Sites and choose the site(s) you will be adding the cartridge to.. Click on the Settings tab and add in the cartridge path int_forter then click Apply.

You'll also select your storefront sites and add the cartridge path to the business manager by going to: Administration > Sites > Manage Sites and clicking on the Business Manager link.

Step 2: Add your Forter credentials

Now that you've imported the cartridge, you'll see a new "Forter" section available in your SFCC store Business manager.

Go to the Configuration Section to add your API credentials. In this section, you'll enable the cartridge, add your private Forter site credentials and can select your business preferences including approve and decline decision handling and setting up the order status job automation.

Step 3: Add your API version

Your API version should match the version published in your dedicated Forter portal. You can adjust the version in your Salesforce BM by going to Merchant ToolsSite Preferences, clicking on the Forter preference and then searching for API Version attribute.

Step 4: Add Your Payment Settings

Forter's cartridge has "out-of-the-box" options for handling payments based on Forter's decisions such as automatically capturing for approved orders and voiding and canceling declined orders.

📘

Note further decision handling and customizations can be made in the cartridge code of your int_forter directory.

Step 5: View your Forter Orders Section

Upon installation of the cartridge, a new Forter> Orders page will be added that shows Forter's decision for each order that goes through the cartridge. You'll also have options in your site preferences to add custom attributes (like recommendations or external order status as columns to the grid.

Step 6: Set your Order Update Job

The Order update job checks for changes in the Order status and sends these updates to the Forter Order Status API endpoint. Forter recommends setting this to run every 6 hours.

If you use an external OMS and do not send data back to your SFCC platform, please see our Order Status API documentation to integrate this API directly.

Step 7: Script Injection

Forter's cartridge will automatically inject a script into your site footer. The script template can be found in the cartridge. Note that the script is used to collect crucial cyber and behavioral data that optimizes Forter's decisions at checkout. The script does NOT collect any PII data from the customer and loads asynchronously to ensure it has no impact on page load or customer experience.

🚧

Do not modify the JS snippet or adjust the placement of the snippet in your storefront

Step 8: Customizing your Decision placement and handling

Forter's cartridge can return a decision pre-auth (before the payment is sent to the PSP for authorization) or post-auth (after the payment is sent to the PSP for authorization. The cartridge can also return a recommendation as part of PSD2/3DS enforcement or Policy enforcement like return abuse, coupon abuse, seller collusion and other policies.

Pre-Auth and Status

📘

Pre-Auth payment data requirements

Make sure you have access to the required pre-auth payment data to complete a pre-auth+status integration. The data requirements can be found here

SFRA

In the case of SFRA websites, the a CheckoutServices.js file has code that will be default commented out. You will need to UNCOMMENT this code to activate the Pre-Authorization option in the cartridge.

Immediately upon receipt of the authorization status from your PSP, the forter Order Status API endpoint should be called to provide Forter with information about the authorization status of each order. The code below is an example of how to call the order status and include the authorization response from your PSP/payment gateway.

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");
}

📘

In the case of pre-auth integrations, the default order status values should be "CANCELED_BY_MERCHANT" (when processor rejects card) or "PROCESSING" (when the card was authorized)

Controllers

  1. For Controllers-based websites update the COPlaceOrder.js controller file and the handlepayments(order) function.

  1. You'll also need to modify the start() function of the COPlaceOrder.js function for rejected authorizations from the processor.

Pre-Auth with Recommendations

Follow the same steps as the Pre-Auth+Status integration for Controllers or SFRA.

You'll also need to add logic to handle a a "recommendations"parameter as part of the API response to the cartridge. The recommendation will be a string within the "recommendations" array. The recommendation will either be for:

  • Policy (i.e. "MONITOR_POTENTIAL_REFUND_ABUSE" )
  • Payments Optimization ("VERIFICATION_REQUIRED_3DS_CHALLENGE", "REQUEST_SCA_EXEMPTION", "REQUEST_SCA_EXCLUSION")

All Policies are not default enabled but can be exposed and configured by your Forter implementation team

Payments Optimization

The code below shows how the payments optimization recommendation is exposed. You'll need to add logic to your Forter cartridge to retrieve the recommendation and pass it back to your payment gateway to execute the appropriate action (3DSecure, SCA exemption, SCA exclusion etc). This should be custom based on your specific gateway and 3DS implementation.

Only transactions that Forter determines to require payment optimization will receive a recommendation (along with an "approve" decision). In all other cases, you should receive an "approve" or "decline"decision without a payments optimization recommendation.

{
  "message": "",
  "action": "approve",
  "recommendations": [
    [
      "VERIFICATION_REQUIRED_3DS_CHALLENGE"
    ]
  ],
  "transaction": "123456",
  "status": "success"
}

Trusted Policies

The code below shows how a Trusted Policies recommendation is exposed. Logic should be customized in your Forter cartridge to retrieve the policy recommendation and route the order or redirect the customer according to your checkout flows and preferences.

{
  "message": "",
  "action": "approve",
  "recommendations": [
    [
      "MONITOR_POTENTIAL_COUPON_ABUSE"
    ]
  ],
  "transaction": "123456",
  "status": "success"
}

🔥 Note that the decision ("action") will always be "approve" when a Policy recommendation is returned.

Post-Auth

By default, the cartridge is set to a post-auth implementation. You do NOT need to modify the the Forter CheckoutServices.js (SFRA) or COIPlaceOrder.js (Controllers) to receive a post-auth decision in the Forter cartridge but you'll need to modify the mapping and pass the authorization response from you processor back to the cartridge.

  1. Select your Forter decision handling configuration as described here
  2. Update your Processor Rejection/NoAuth handling and customize how you want to route orders based on the payment method and/or Forter decisions
  3. Set up your Order Update (Order Status) Job: This should be sent asynchronously to allow Forter to understand the full lifecycle of the order. For post-auth integrations, the authorization response does not need to be included in the order update job and it can be scheduled (as opposed to called immediately after Forter returns a decision)

Step 9: Mapping the Order data

For both Controllers and SFRA, Forter's cartridge contains a ForterOrder.js file that has a template of the order data mapping. This should be modified based on the data you collect at checkout (billing details, cart items, delivery information, and your specific Payment Service Provider data across different payment methods.

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,
                    request: request
                },
                forterCall = require('int_forter_sfra/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,
                    request: request
            },
            forterCall = require('int_forter_sfra/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,
                    request: request
                },
                forterCall = require('int_forter_sfra/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,
                    request: request
                };
                forterCall = require('int_forter_sfra/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 = {
                    Page 3 - 43
                }
            }
            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;
}

Step 10: Adjust to map your processor response

To optimize Forter's model accuracy, all orders including those that are rejected by the payment processor ("No Auths") should be sent to Forter. Forter will not evaluate NoAuths - they will only receive a "not reviewed" decision, but the No Auth orders are an important data point that allow Forter models to better understand the behavior and attempts of each customer's order and attempted order. To pass the authorization response from your payment processor you'll need to edit the ForterOrder.ds file. The example below shows how the authorization and processor response data is sent from the Authorize.net payment processor usin g the payment instrument as a custom attribute in a script. If your specific checkout flow and processor does not store processor and authorization response data on the payment instrument - you can pass the response object to the validateOrder() function within the ForterValidate.js controller so that it can be sent as a parameter to the ForterOrder.ds file to generate the request object.

👍

For Credit Card orders:

The verificationResults andpaymentGatewayDataobjects of the ForterCreditCard() function must be adjusted to reflect the response from your specific gateway/processor.

Step 9: Handle Authorization Rejects

To handle the customized error massage configured in your Forter business manager adjust the COPlaceOrder.js with the authorization response details.

In the start() function, add the following:

return {
    error: true,
    PlaceOrderError: new Status(Status.ERROR, handlePaymentsResult.forterErrorCode ? handlePaymentsResult.forterErrorCode.code : 'confirm.error.technical')
};

Step 11: Test

Installation Testing

In order to see if the cartridge is installed and configured correctly, you need to go to the Storefront and place some test orders, both as a registered customer and as a guest customer. Then, go to check the order status in the Forter dedicated page Merchant Tools > Forter > Orders.

Decision Handling

Using your sandbox SFCC website, place an order as either a registered customer or a guest. Depending on the site preferences and decision handling you've selected, you should see the appropriate confirmation page or error based on the test payment (no Auth, authorized). In the case of a custom decline message you configured in your bm, you should see the decline message when you force a decline decision.

Example Declined order

You'll also be able to see all orders in the Forter portal as well as any schema or formatting errors.