Virtual Checkout

Whether you process $1m or $1bn in sales, adding Zip is straightforward. Zip offers an integration method that enables merchants of any size to add Zip in a few lines of code. This will launch Zip checkout in a pop-up or within an incontext modal so the user never has to leave your site. This approach enables merchants to integrate Zip through a front end integration without requiring any back end API updates.

Using the Zip Virtual Card Checkout, merchants can offer an installment payment option that routes transactions through your existing credit card form in the checkout. Zip generates a unique virtual Visa card for every true transaction and injects the card number into your existing credit card form, making the Zip integration a front-end only integration. The virtual integration bypasses the need to make modifications to your order management system – charges, returns and refunds processed as Zip orders will appear like any other credit card order in your system. You can tokenize the virtual Visa card and interact with it just like you would with any regular debit or credit card. You get paid in full, and your customers pay in four.

How it Works

During checkout, Zip dynamically issues a single-use virtual card for each customer purchase. These are standard Visa credit cards, which are dynamically entered into your existing credit card checkout forms and processed by your existing payment gateway. The virtual card supports multiple authorizations, refunds, voids, and captures by utilizing your existing credit card processor. Because you are not adding a new tender type or payment gateway, your backend systems for order management, fulfillment and customer service remain untouched. If you are integrating with our customer contribution model, known as Merchant Fee For Payment Plan (MFPP), the fee will be charged to the Zip issued virtual card and collected the next business day. Please see our Merchant Fee for Payment Plan Implementation Guide Merchant Fee For Payment Plan Implementation Guide for more information.

The Zip Virtual Checkout can be placed on either the payment page, for a Standard Checkout flow, or the cart, for an Express Checkout flow. If placed on the cart, you will be able to retrieve the shipping information from Zip, speeding up the checkout process for the consumer.

Standard vs. Express Version of Virtual Checkout

Standard
The standard version is placed on a payment page. This enables merchants to pass order details to Zip and for Zip to return a virtual card after the consumer completes the flow.

Express
The express flow can be initiated from either the cart page or product page. Zip will collect the shipping and billing information in this flow, and pass this information back to the merchant. This allows the customer to bypass the shipping and billing information pages for a faster checkout experience.

Getting Started

This implementation does not require any backend integration. With a few lines of HTML and/or JavaScript, you can accept installment payments in their checkout in less than an hour!

The Virtual Checkout integration is based on three components.

  1. A reference to our CDN hosted JavaScript library.
  2. A Quadpay-button element or HTML DOM element
  3. JavaScript code to attach one or many callback functionality(s) and customize the payment flow.

There are two different ways to implement the Virtual Checkout (step 2 above). You can either utilize a Zip-branded button element or a custom DOM element. The Quadpay-button serves as a turnkey solution that is easiest to work with. You may choose to work with a custom DOM element for a more customized integration. Both are fully supported and our button is actually built on top of the same library.

Environments

There are two environments available and you'll get a unique merchant ID for each environment to use it.

Sandbox: https://cdn-sandbox.quadpay.com/v1/quadpay.js
Production: https://cdn.quadpay.com/v1/quadpay.js

Adding the sandbox script will automatically integrate with our sandbox services for testing. Importing the production script will result in real transactions.

🚧

Environment Switching

An even easier method to switch environments is to use functionality within our scripts! If you use the production script, you can change the environment by calling virtualCheckout.updateEnvironment(name). To call our sandbox environment, you would pass sandbox as the name like virtualCheckout.updateEnvironment('sandbox') before launching the QuadPay virtual checkout.

Javascript Reference
The script can be loaded by adding a tag like <script src="https://cdn.quadpay.com/v1/quadpay.js" type="text/javascript"></script>.

The script can be added anywhere in the body or head and can be loaded asynchronously. If loaded asynchronously, be sure to wait for its load to complete before invoking any operations against the library.

📘

Debug Mode

Working through some integration issues with the Zip team? If you add debug=true to your non-production script, you'll be able to enable some logging for the quadpay.js library that will log messages to your console to help address any issues.

Button or Custom DOM Element

Add a Zip button or attach the click event to a custom HTML DOM element.

Zip button
<Quadpay-button id="QPButton" merchantId="44444444-4444-4444-4444-444444444444" merchantReference="xxxyyy111" amount="100" currency="USD"></Quadpay-button>

You can find all available attributes for the Zip button in the below table.

Quadpay Button Attributes

Attribute Name

Type

Optional/Required

Description

Amount

number

Required

The maximum amount that can be authorized on the issued virtual card. It should include all fees, taxes, shipping, and discount codes calculated in its value.

shippingAmount

number

Optional

The cost of shipping.

taxAmount

number

Optional

The cost of taxes.

currency

Required

The currency in which the customer is transacting, in ISO 4217 format.

merchantId

GUID

Required

Your unique ID for your integration. Shared via the Merchant Portal.

merchantReference

string

Required

This is an identifier you will use to reconcile orders made with Zip. Set this to something that is unique for each order that you can preferably reference within your system.

customerFirstName

string

Optional

Customer's first name

customerLastName

string

Optional

Customer's last name

customerEmail

string

Optional

Customer's email address

customerPhoneNumber

string

Optional

Customer's phone number

customerAddressLine1

string

Optional

Customer's primary address information

customerAddressLine2

string

Optional

Customer's secondary address information. May contain - Apartment number, Care of, Attention

customerCity

string

Optional

Customer's address city

customerState

string

Optional

Customer's address state, in ISO 3166-2:US format (two letter state code)

customerPostalCode

string

Optional

5 digit state postal/zip code

customerCountry

string

Optional

Customer's address country, in ISO_3166-2 (two letter country code). E.g., US, CA, MX

isDisabled

bool

Optional

For testing purposes. This blocks openCheckout.

merchantFeeForPaymentPlan

Optional

A customer contribution model that includes an incremental order amount called “Merchant Fee for Payment Plan” (MFPP).

lineItems

Array of line items object

Optional

Product specific information, within an order.

forceIFrame

bool

Optional

Default functionality will launch the Zip checkout flow in a pop-up window, unless forceIFrame is set to 'true'.

checkoutFlow

enum

Optional

Indicates if it’s the standard or express flow. Either “standard” or “express”.

📘

Internet Explorer 11 Support

Because the quadpay-button utilizes webcomponents, you have to take extra care when initializing it within IE11. In modern browsers, you can start working with the quadpay-button as soon as the quadpay.js script executes. However, in IE11, you'll want to configure an event listener on the document for the WebComponentsReady event and then execute your setup code. This is only required if you expect to support IE11. Here's a sample script:

        if (isIe11()) {
            document.addEventListener('WebComponentsReady', function (e) {
                setupQuadPay();
            });
        } else {
            setupQuadPay();
        }

        function isIe11() {
            return !!window.MSInputMethodContext && !!document.documentMode;
        }

Custom DOM Element

The custom DOM element can be any type of element that supports an onclick event. The below example is a button element but this can be anything from radio buttons, dropdown or image.

<input type="button" id="ZipButton" value="Pay with Zip" />

Set an onComplete callback handler that accepts the virtual card details and uses them as the payment method in your system.

Callback Events

onComplete

The onComplete Callback accepts a function as a parameter that will be invoked when a customer successfully completes the Zip checkout. It accepts card and cardholder information, fills in credit card payment details, hides those payment details, and submits the checkout. In the Standard flow this contains - card, cardholder, and customer. In the Express flow the result also includes shippingAddress and optionally, merchantFeeForPaymentPlan. This callback may be invoked asynchronously.

❗️

Billing Address

Please do not hardcode the billing address. While the Zip billing address does not change often, we do periodically update it. If you hardcode the billing address it will break the integration if we ever update the billing address.

🚧

User Experience Gotchas

  • Don't save the card details with the customer for future purchases as cards are issued on a per-transaction basis.
  • It's best to auto-submit the checkout within this hook, but we can support flows where this doesn't happen. Funds will be released back to the customer after an hour (this is configurable)

Code Example:

//On complete callback event
const onCompleteCallback = function (result)
{
    // Fill in your existing credit card form with the details from
    // the dynamically generated Zip single-use card
    document.getElementById("creditCardNumber").value = result.card.number;
    document.getElementById("creditCardCvc").value = result.card.cvc;
    document.getElementById("creditCardExpiryMm").value = result. card.expirationMonth;
    document.getElementById("creditCardExpiryyy").value = result.card.expirationYear;
    document.getElementById("cardholderName").value = result.cardholder.name;

    // Fill in your existing billing address form with details from
    // the card holder.  If your billing address contains first/last name
    // fields, you can leave those as the actual customer values.
    document.getElementById("name").value = result.cardholder.name;
    document.getElementById("addressLine1").value = result.cardholder.address1;
    document.getElementById("addressLine2").value = result.cardholder.address2;
    document.getElementById("city").value = result.cardholder.city;
    document.getElementById("state").value = result.cardholder.state;
    document.getElementById("zipCode").value = result.cardholder.postalCode;
    document.getElementById("country").value = result.cardholder.country;

    //For express version only
    //result.shippingAddress;
};

window.quadpay.virtualCheckout.onComplete(onCompleteCallback);

If you are using the custom DOM element, the openCheckout function needs to be called to open the Zip checkout flow. See below for more specific details.

onClose

The onClose callback is invoked whenever the user closes the Zip checkout. This optional callback may happen if the customer closes the window, clicks back to cart, is not approved, or their session times out. The callback may be asynchronous as it is awaited. The callback will accept one parameter:
message (string): Message about why the checkout was closed.

Code Example

///On close callback event
const onCloseCallback = function (result) {

};

window.quadpay.virtualCheckout.onClose(onCloseCallback);

onError

The onError callback handler will be invoked if the parameters supplied to the openCheckout method are invalid or missing. This optional callback handles technical errors during loading of the Zip checkout flow. The callback may be asynchronous as it is awaited. The callback will return error messages in the format of an array of strings representing error messages about what validation failed.

Code Example:

// On error callback event
const onErrorCallback = function (result) {
};

//Attaching the on error callback event
window.quadpay.virtualCheckout.onError(onErrorCallback);

More details on all Quadpay.virtualCheckout methods can be found in the below tables.

Checkout Flow Functions

openCheckout (with custom DOM element)

This method is required when a custom DOM element is used and will launch the virtual checkout in a popup window (or iframe depending on provided parameters). The method requires 3 parameters with an optional 4th parameter.

Attribute Name

Type

Optional/Required

Description

amount

number

Required

The maximum amount that can be authorized on the issued virtual card. It should include all fees, taxes, shipping, and discount codes calculated in its value.

order

Json

Optional

The order information in json format. See below for a complete example.

checkoutFlow

enum

Required

Indicates if it’s the standard or express flow. Either “standard” or “express”.

forceIFrame

bool

Required

Indicates if the Zip checkout flow will open in an iframe or a modal (popup).

Code Example:

var customButton= document.getElementById("customButton");
customButton.addEventListener("click", () => {
                window.quadpay.virtualCheckout.openCheckout("44444444-4444-4444-4444-444444444444", order, “standard”, false);
 });

focusCheckout

This method allows you to programmatically bring focus to the pop-up window once the virtual checkout has been opened.

Code Example:

window.quadpay.virtualCheckout.focusCheckout();

closeCheckout

This method force-closes the Zip checkout window and ends the user's Zip session.

Code Example:

window.quadpay.virtualCheckout.closeCheckout();

Multi-Page Checkout Handler

The multi page checkout handler is a set of three functions that lets you save a successful onComplete callback result and and later retrieve it. The information is saved for the user’s browser session, and will not persist beyond that. This is used primarily when the Express version of virtual checkout is used and a consumer starts the checkout from the Cart or Product page. This means you can retrieve the result on page load of the payment page and populate shopper, shipping address, billing address and payment information.

1. Save Result

This method accepts the result object returned from the onComplete callback as a parameter that will be invoked when a customer successfully completes the Zip checkout. It is responsible for saving the card, cardholder, customer, shippingAddress, and merchantFeeForPaymentPlan in session storage, for the duration of the user’s browser session. In the event that the checkout process spans multiple pages this information can be saved (and cleared) to allow for checkout information to be available to the merchant through page loads and redirects. This method is designed for express checkout flows.

Code Example:

window.quadpay.virtualCheckout.saveResult(result)

2. Get Complete Result

This method returns the previously stored values from the saveResult() method completed on the previous stage. The result object contains the card, cardholder, customer, shippingAddress, and merchantFeeForPaymentPlan. This allows for checkout information to be accessible to the merchant through page loads and redirects in express checkout flows.

Code Example:

var result = window.quadpay.virtualCheckout.getCompleteResult();

3. Clear Result

This method clears the previously stored values from the saveResult() method from the session storage to ensure that card, cardholder, customer, shippingAddress, and merchantFeeForPaymentPlan information is removed from the browser after multi-page checkout has been completed.

Code Example:

window.quadpay.virtualCheckout.clearResult();

Fee Calculation Functions

calculateMerchantFeeForPaymentPlan

This method calculates the MFFP price depending on country, state, currency and amount.

The calculateMerchantFeeForPaymentPlan() method returns a promise with the below parameters.

Attribute Name

Type

Description

adjustedOrderAmount

number

The new order amount, including the MFPP fee.

currency

string

‘Amount’ currency

merchantFeeForPaymentPlan

number

The per-order fee amount, set as part of the customer contribution model.

Code Example:

window.quadpay.merchantFees.calculateMerchantFeeForPaymentPlan({
merchantId: "44444444-4444-4444-4444-444444444444",
customerState: "NY",
customerCountry: "US",
amount: 100,
currency: "USD"}).then((response) => {
  //response.adjustedOrderAmount
  //response.currency
  //response.merchantFeeForPaymentPlan
});

calculateInstallments

This method takes a number value as a parameter and returns an array with 4 items - each installment amount based on the order amount.

Attribute Name

Type

Description

amount

number

The new order amount, including the MFPP fee.

date

string

e.j., Wed Jul 14 2021 00:00:00 GMT-0400 (Eastern Daylight Time)

sequenceNumber

number

The installment sequence.

Code Example:

var installments = window.quadpay.calculateInstallments(100);

Order in Json Format

order = {
  amount: 166.00,
  currency: 'USD',
  merchantReference: 'your-unique-order-id',
  shippingAmount: 10.00,
  taxAmount: 5.50,
  customer: {
    address1: '123 street ',
    address2: '',
    city: 'New York',
    state: 'NY',
    postalCode: '10000-4311',
    country: 'US',
    email: [email protected]',
    firstName: 'John',
    lastName: 'Doe',
    phoneNumber: '+11111111111'
    },
  lineItems: [
    {
    name: 'Item Name 1',
    description: 'Item description 1',
    quantity: 1,
    price: 100.25,
    sku: '8000148',
    isPreOrder: false,
    releaseDate: '01/01/2021',
    },
    {
    name: 'Item Name 2',
    description: 'Item description 2',
    quantity: 1,
    price: 50.25,
    sku: '8000149',
    isPreOrder: false,
    releaseDate: new Date(),
    },
    ]
    };

Testing

Online Checkout

When testing the virtual checkout in non-production scenarios, there are a few key points that will help you get through the Zip checkout flow easily and consistently.

  1. When the checkout launches, you can choose Force New Customer after entering your phone number. This will allow you to have the new customer user experience and bypass some test approval rules.

  2. If you do not have a US phone number, you may use a free SMS service. If you google receive SMS free, you'll find a number of free services with temporary phone numbers that you can use for your testing.

  3. You can use the following test card data on the Zip payment details page:

    • Card Number: 4242 4242 4242 4242 can be used to see a success within our checkout flow
    • Card Number 4000 0000 0000 0002 can be used to see a decline within our checkout flow
    • Card Expiration: 2/22
    • CVC: 222
    • Name/Postal Code: Anything

Virtual Card Transactions

The virtual card that is issued in our sandbox environment is not a card that can be charged via legitimate payment rails. To be issued a real virtual card that you can actually authorize, you must use the production environment!

For a standard implementation, we suggest working with the sandbox environment to build the integration. Once complete and certified by Zip, you can update your test environment to use the quadpay.js production environment to perform legitimate transactions. If you aren't able to connect to our production environment in your non-production environment, there are strategies around query flags, A/B testing, and more that you can utilize to roll it out and test it in production.

Frequently Asked Questions

I am a pay-on-ship merchant. Will this integration work for me?

Yes! Being that it's a standard Visa card, we are able to handle both multiple authorizations and captures.

Since this processes like a standard Visa card, how can I reconcile the orders in my system with the ones Zip processed?

As part of the integration, you are required to set a merchantReference attribute for each checkout. This identifier will be available in our reporting that you can use to link up which Visa orders in your system are Zip virtual checkout orders.

Can the customer apply a gift card or voucher code to a Zip order?

Yes! You can apply the discount to the order and then set the final order amount as an attribute on the Zip button.

What are the authorization and settlement windows?

Merchants must capture part of the order in 7 days at the very latest or reauthorize. And Merchants have 13 days from the order date to complete all captures to coincide with the customer's 2nd Zip installment on day 14.

Can I reuse the virtual card for future customer purchases?

No. Every card generated is unique per transaction. A customer should go through the Zip checkout for each purchase to get a new virtual card to use.

How do I prevent the card from being charged by other merchants?

All of our virtual cards are locked down to your merchant's network information. We decline all credit card transactions unless they come directly from you.

What address do I use for the billing address?

There are a couple of addresses at play with the virtual checkout. The cardholder will contain address information that is associated with the issued virtual Visa card. You will want to use this for the billing address so that authorizations against that card will succeed. You do not need to save this address as it will be sent each time a virtual card is issued. Additionally, we pass the customer's address they provided to Zip via the customer object. You can use this information should you wish to save additional customer details in your system.

When does the customer starting paying their payment plan?

Customers always have 25% (the first installment amount) authorized on their card when they go through the checkout. If the purchase isn't completed for some reason, this transaction is cancelled and the hold on those funds is removed. This also takes 13 days currently, but may be adjusted to happen sooner. The actual payment plan will start processing as soon as there is an authorization against the issued card.

Is there a static BIN range that your virtual cards use?

Yes, there is a BIN range that we can share to be whitelisted with your fraud tools.

Object Model

Customer

Properties

Type

Optional/Required

Description

firstName

string

Optional

Customer's first name

lastName

string

Optional

Customer's last name

email

string

Optional

Customer's email address

phoneNumber

string

Optional

Customer's phone number

address1

string

Optional

Customer's primary address information

address2

string

Optional

Customer's secondary address information. May contain - Apartment number, Care of, Attention

city

string

Optional

Customer's address city

state

string

Optional

Customer's address state, in ISO 3166-2:US format (two letter state code)

postalCode

string

Optional

5 digit state postal/zip code

country

string

Optional

Customer's address country, in ISO_3166-2 (two letter country code)

Order

Properties

Type

Optional/Required

Description

amount

number

Required

The maximum amount that can be authorized on the issued virtual card. It should include all fees, taxes, shipping, and discount codes calculated in its value.

shippingAmount

number

Required

The cost of shipping.

taxAmount

number

Optional

The cost of taxes.

currency

string

Required

The currency in which the customer is transacting.

merchantReference

string

Required

The merchant's identifier for the order. This is used to reconcile merchant orders in Zip's system.

customer

Customer object

Optional

Customer object is used to prefill data in the Zip checkout to improve the user experience and conversion. This is typically based on the customer's supplied billing or shipping details entered earlier in the checkout process.

merchantFeeForPaymentPlan

number

Optional

The per-order fee amount, set as part of the customer contribution model.

lineItems

LineItem object Array

Optional

The items in the order.

Line Item

Properties

Type

Optional/Required

Description

name

string

Optional

The name of the item

description

string

Optional

The description of the item.
(n.b. the description should have max 100 characters, if it exceeds this limit it will be truncated)

quantity

number

Optional

The quantity of the item in the order.

price

number

Optional

The price of 1 item.

sku

string

Optional

The Stock Keeping Unit number.

isPreOrder

boolean

Optional

Whether the item is a pre-order item.

releaseDate

date

Optional

The anticipated shipment date of the item.

Card

Propoerties

Type

Optional/Required

Description

number

string

Required

The virtual Visa card number.

cvc

string

Required

The card's CVC security code.

expirationMonth

number

Required

The month expiry of the card.

expirationYear

number

Required

The year expiry of the card.

brand

string

Optional

The brand of the credit card.

Cardholder

Properties

Type

Optional/Required

Description

name

string

Required

The cardholder's full name. To be used if you collect a single name field for the cardholder information.

firstName

string

Required

The cardholder's first name. To be used if you collect separate fields for first and last name.

lastName

string

Required

The cardholder's last name. To be used if you collect separate fields for first and last name.

address1

string

Required

Primary billing address information

address2

string

Optional

Secondary billing address information. May contain - Apartment number, Care of, Attention.

city

string

Required

Customer's billing address city.

state

string

Required

The state of the customer's billing address, in ISO 3166-2:US format.

postalCode

string

Required

5 digit state postal/zip code.

country

string

Required

The country of the customer's billing address in ISO_3166-2 (two letter country code).

Address

Properties

Type

Optional/Required

Description

line1

string

Required

Primary shipping address information.

line2

string

Optional

Secondary shipping address information. May contain - Apartment number, Care of, Attention.

city

string

Required

The city of the customer's shipping address.

state

string

Required

The state of the customer's shipping address, in ISO 3166-2:US format.

country

string

Required

The country of the customer's shipping address in ISO_3166-2 (two letter country code).

postalCode

string

Required

5 digit state postal/zip code.

successCallback

Properties

Type

Optional/Required

Description

customer

Customer object

Required

This contains information the customer enters in the Zip checkout. Merchants sometimes collect this data to store in their systems since the billing information needs to be overridden with the cardholder details.

cardholder

Cardholder object

Required

The cardholder includes the billing information attached to the issued virtual card. This will be different from customer information. If you require email or phone number as part of the billing information, you can use the customer's information for those fields.

card

Card object

Required

Details about the issued virtual card for your transaction.

shippingAddress

Address object

Optional

Used in express flows, the customer's shipping address is returned on the result object.

merchantFeeForPaymentPlan

number

Optional

A customer contribution model that includes an incremental order amount called “Merchant Fee for Payment Plan” (MFPP).

Checkout Flow

Properties

type

Description

standard

string

express

string