Launching the Checkout Experience

How to create a customer/consumer and cart prior to creating a charge.

After loading the SDK, you can launch the Checkout UI with the ChargeAfter.payments.present('checkout', opt) function.

📘

Script Loading

To avoid any impact to the performance of your website, the script is loaded asynchronously. This means that the ChargeAfter.payments.present('checkout', opt) function might not be available immediately after script load.

You must provide the customer information (via the consumerDetails object) and cart information (via the cartDetails object) in a JSON format. Jump to the code sample .

consumerDetails Object

It is recommended to provide all the available customer information when launching the ChargeAfter Checkout UI.

Depending on the specific financial products used, the consumerDetails object can be optional or required. If any of the consumer details are not provided when launching the Checkout UI, ChargeAfter will collect it from the consumer and inform the merchant via the onDataUpdate callback.

The consumerDetails object contains the following fields:

NameTypeDescriptionRequired/OptionalValidations
firstNamestringConsumer first name. For example: "John"Required, except when onDataUpdate function is used.All letters, spaces and hyphens.
lastNamestringConsumer last name. For example: "Doe"Required, except when onDataUpdate function is used.All letters, spaces and hyphens.
emailstringConsumer email. Should be a valid email format. For example: "[email protected]"Required, except when onDataUpdate function is used.All letters, hyphens, numbers, symbols, of periods.
mobilePhoneNumberstringConsumer phone number. For example: "2124454545"Required, except when onDataUpdate function is used.Numbers.
No spaces, periods, or symbols are allowed.
merchantConsumerIdstringThe merchant identifier for the consumer.Required, except when onDataUpdate function is used.
shippingAddressobjectThe shipping address object. See address Object.Required, except when onDataUpdate function is used.See address Object.
billingAddressobjectThe billing address object. See address Object.Required, except when onDataUpdate function is used.See address Object.

shippingAddress and billingAddress Objects

NameTypeDescriptionRequired/OptionalValidations
line1stringAddress line 1RequiredAll letters, spaces, numbers, hyphen, hash symbol (#) and periods.
line2stringAddress line 2OptionalAll letters, spaces, numbers, hyphen, hash symbol (#) and periods.
citystringCity name. For example: "New York" (US) or “Edmonton” (CA)RequiredAll letters, spaces, numbers and hyphens.
zipCodestringZipCode / Postal Code. For example: "10019" or "10019-1232" / “A1A 1A1”Required
statestringState/Province. The value to be set is either 2 character state code or State/Province name. For example: "NY" or "New York"/“Alberta”Required

🚧

Billing and Shipping Address

As an anti-fraud measure, billingAddress and shippingAddress (if provided) must be the same, otherwise, the checkout will not work.

📘

In-store Pickups

If the response object to the onDataUpdate callback is provided and the order is an in-store pickup, then provide only the billing address.

cartDetails Object

cartDetails is an array that contains various elements of the cart:

NameTypeRequired/Optional
itemsarrayRequired
discountsarrayOptional
merchantOrderIdstringOptional
taxAmountnumberRequired
shippingAmountnumberRequired
totalAmountnumberRequired

items Object

items is an array that contains the details of every item in the cart:

NameTypeRequired/Optional
namestringRequired
pricenumberRequired
skustringRequired
quantitynumberRequired, integer
leasablebooleanTrue if the specific item is leasable.
False or undefined if not leasable.
If an item is not leasable, some leasing options will not be available to pay for the order.
productCategorystringProduct category or full taxonomy path
warrantyobjectOptional (See warranty Object.)

Code Sample

f// Present the checkout modal box and pass it an options object
ChargeAfter.checkout.present({
    // Consumer information
    consumerDetails: {
        firstName: "John",
        lastName: "Doe",
        email: "[email protected]",
        mobilePhoneNumber: "2124454545",
        merchantConsumerId: "<consumer-id-by-merchant>",
        shippingAddress: {
            line1: "3 My Street",
            line2: "My Building, 4th floor",
            city: "New York",
            zipCode: "10019",
            state: "NY",
        },
        billingAddress: {
            line1: "3 My Street",
            line2: "My Building, 4th floor",
            city: "New York",
            zipCode: "10019",
            state: "NY",
        }
    },

    // Cart information
    cartDetails: {
        items: [{
            name: "Awesome Product",
            price: 1999.0,
            sku: "AWSMPRDCT",
            quantity: 2,
            leasable: true,
            productCategory: "Product category",
            warranty: {
                name: "Awesome Warranty",
                price: 100.0,
                sku: "AWSMWRNTY"
            }
        }],
        discounts: [{
            name: "Birthday discount",
            amount: 20
        }],

        merchantOrderId: "<order-id-by-merchant>", // OPTIONAL. Passed to interested lenders
        taxAmount: 199.0,
        shippingAmount: 19.0,
        totalAmount: 4296.0
    },

    // This callback allows you to process the result of customers data update 
    onDataUpdate: function(updatedData, callback) {
        callback({
            taxAmount: CALCULATED_TAX_AMOUNT,
            shippingAmount: CALCULATED_SHIPPING_AMOUNT,
            totalAmount: UPDATED_TOTAL_AMOUNT
        });
    },

    // This callback allows you to process the result of the checkout process
    // if onComplete function is provided on sdk init, both will fire
    callback: function(token, data, status) {

    },

    // Available values: E_COMMERCE / IN_STORE / CALL_CENTER / IN_HOME
    channel: "E_COMMERCE",

    // This string is OPTIONAL. Will continue the prequalification to checkout.
    sessionToken: "<id received from apply (prequalify)>",

    // This object is OPTIONAL
    filter: {
        creditTiers: ["SubPrime"], //possible value Prime, NearPrime, SubPrime
    }

    // optional string-string/number/Boolean/Date map
    // tags: {property: 'value'}

    // This parameter is OPTIONAL. This is used to load the Checkout UI directly to a specific lender
    // lenderId : XXXXXXXXX,
  
    // This parameter is OPTIONAL. Used to specify an existing HTML container to contain the checkout 
    // UI
    // containerSelector: '#container-id'
    
    // This parameter is OPTIONAL. Used to specify the promo code that will be used for checkout 
    // experience.
    // promoCode: 'ASDAASD'
});
import { prequalify, checkout } from "@chargeafter/payment-sdk";

await checkout({
  	config: {
        env: {
            name?: "production" | "sandbox", // defaults to "production"
            apiKey: "<your api key>",
        }
    },
    // This callback allows you to process the result of customers data update 
    onDataUpdate: async (updatedData, callback) => {
			// process updated data and trigger callback with updated cart amount
			// see "OnDataUpdate" section below.  
      callback({
        taxAmount: CALCULATED_TAX_AMOUNT,
        shippingAmount: CALCULATED_SHIPPING_AMOUNT,
        totalAmount: UPDATED_TOTAL_AMOUNT
      });
      
    },
     // Consumer information
    consumerDetails: {
        firstName: "John",
        lastName: "Doe",
        email: "[email protected]",
        mobilePhoneNumber: "2124454545",
        merchantConsumerId: "merchant-internal-consumer-id",
        shippingAddress: {
            line1: "3 My Street",
            line2: "My Building, 4th floor",
            city: "New York",
            zipCode: "10019",
            state: "NY",
        },
        billingAddress: {
            line1: "3 My Street",
            line2: "My Building, 4th floor",
            city: "New York",
            zipCode: "10019",
            state: "NY",
        }
    },

    // Cart information
    cartDetails: {
        items: [
            {
                name: "Awesome Product",
                price: 1999.0,
                sku: "AWSMPRDCT",
                quantity: 2,
                leasable: true,
                productCategory: "Product category",
                warranty: {
                    name: "Awesome Warranty",
                    price: 100.0,
                    sku: "AWSMWRNTY"
                }
            }
        ],
        discounts: [
            {
                name: "Birthday discount",
                amount: 20
            }
        ],
        
        merchantOrderId: "<order id>", // OPTIONAL. Passed to interested lenders
        taxAmount: 199.0,
        shippingAmount: 19.0,
        totalAmount: 4296.0
    },
  
    // Available values: E_COMMERCE / IN_STORE / CALL_CENTER / IN_HOME
    channel: "E_COMMERCE",
  
    // This object is OPTIONAL
    currency : "USD",

    // This string is OPTIONAL. Will continue the prequalification to checkout.
    applicationId : "<id received from apply (prequalify)>",
  
    // This object is OPTIONAL
    // appSettings: {
    //     containerSelector: "#my-container-selector",
    // },
  
  	// This parameter is OPTIONAL. This is used to load the Checkout UI directly to a specific lender
    // lenderId : XXXXXXXXX,
});


Optional Fields

discounts Object

The discounts object is an optional array that consists of one or more applied discounts:

NameTypeRequired/Optional
namestringRequired
amountnumberRequired

warranty Object

Optionally nested within each item object, is the warranty object. If added, then all fields below are required as shown:

NameTypeRequired/Optional
namestringRequired
pricenumberRequired
skustringRequired

channel Object

The channelobject is an optional parameter that indicates from where the merchant initiated the flow.

Possible values:

  • E_COMMERCE
  • IN_STORE
  • CALL_CENTER
  • IN_HOME

🚧

Formatting channel Object Values

The values must be entered exactly as above in all uppercase letters.

preferences Object

The preferences object is optional, and has the following fields:

NameTypeDescriptionRequired/Optional
languagestringSpecifies the language in which the Checkout UI will be launched.
The value consists of two letters representing the language.
Default value: En
Other languages: Fr
Optional
currencystringSpecifies currencies in fields and variables.
Default value: USD
Other values: CAD, AUD
Optional
countrystringSpecifies countries and regions supported by ChargeAfter in fields and variables.
Default value: US
Other values: CA, AU
Optional

totalAmount Object

All items from your website's cart must be included in the cartDetails and must be equal to the total amount of the cart. This may include warranty, discounts, and fees (recycling, installation, delivery, etc.). The totalAmount field represents the bottom line for this checkout, after adding tax and shipping cost and subtracting any discounts.

Currency for these fields is determined by merchant country or configuration.

Amount/price fields are restricted to present up to two decimal places. In cases where a number has more than two decimal places, ChargeAfter will automatically round it up to the nearest whole cent.

👍

Formatting Amounts

Remember to pass the correct data types. For example, amount fields (like totalAmount) are typically numbers, and not strings (i.e. 45.9 rather than “45.9”).

onDataUpdate function

If cart information is changed during the checkout flow, such as adjustments for shipping or discounts, the onDataUpdate function is invoked.

The onDataUpdate function can be invoked in three ways:

  • Synchronously
  • Asynchronously with await
  • Asynchronously with promise

Synchronous onDataUpdate function

If the consumer makes changes to their personal information, such as their shipping address state in the ChargeAfter modal, then:

  1. ChargeAfter sends the updated details in the updatedData object to the merchant.
  2. The merchant calculates the new cart, which triggers and returns an object response in the onDataUpdate function.

Synchronous Code Samples

If the onDataUpdate function returns a value immediately, there’s no need to use the callback function. For example, if the updated checkout details are available immediately, then simply return it:

function(updatedData, callback) {
      var zipCode = updatedData.consumerDetails.billingAddress.zipCode;
      if (zipCode) {
          // calculate updated shipping and tax amount and return it
          return {
              taxAmount: CALCULATED_TAX_AMOUNT,
              shippingAmount: CALCULATED_SHIPPING_AMOUNT,
              totalAmount: UPDATED_TOTAL_AMOUNT
          };
      } else {
          // nothing to update, but making sure to return an object
          return {};
      }
  }

This code sample demonstrates a common use case of the automatic application of California state sales tax:

// synchronized function  
function onDataUpdate(updatedData, callback) {  
  var taxAmount = 10;

  if (updatedData.consumerDetails.billingAddress.state === 'CA') {  
    taxAmount = 15;  
  }

  return {  
    taxAmount,  
    shippingAmount: 0,  
    totalAmount: 215,  <- Should be totalAmount that includes the new tax e.g if all items sum to $200, then totalAmount should be $215.
  };  
}

Asynchronous onDataUpdate function with await

In Step 2 above , if you do not immediately return a value via the object response in the onDataUpdate function, the callback argument will be triggered to pass the updated information to ChargeAfter.

Asynchronous Code Sample with await

This code sample demonstrates how you can use await to fetch additional information before returning an object response in the OnDataUpdate function:

// this is async await function
async function onDataUpdate(updatedData, callback) {
  return await fetch('some url');
}

Asynchronous onDataUpdate function with promise

In Step 2 above , if you do not immediately return a value via the object response in the onDataUpdate function, the callback argument will be triggered to pass the updated information to ChargeAfter.

The promise function can also be used to fetch additional information before returning an object response in the OnDataUpdate function.

Code Sample with promise

// this is promise function
function onDataUpdate(updatedData, callback) {
  return new Promise((resolve, reject) => {});
}

updatedData Object

The updatedData object is very similar to the cartDetails object that is provided initially in the ChargeAfter.checkout.present() function. It contains the updated checkout details and is composed of the following fields:

NameType
totalAmountNumber
taxAmountNumber
shippingAmountNumber
itemsArray
consumerDetailsObject
discountsArray

Object Response in the onDataUpdate function

The object returned in the onDataUpdate function has the following structure:

NameRequired/Optional
shippingAmountRequired
taxAmountRequired
totalAmountRequired

📘

Continuing in the Checkout Flow

Do not forget to either immediately return an object in the onDataUpdate function or invoke the callback function. The merchant’s website response is a condition for moving forward in the Checkout flow.

Enabling inline mode

If you prefer to bypass the launching of the ChargeAfter modal so that the consumer experiences all ChargeAfter functionality within your own website, you must enable inline mode.

To enable inline mode, you must specify the containerSelector property in the present function. The value passed should be a valid HTML selector as specified by W3C.

ChargeAfter.payments.present('checkout/apply',{  
  // …,  
  containerSelector:"some container selector", // can be also the dom element  
})

What’s Next