Using Connect Checkout

Add an end-to-end checkout flow to your web page

The Checkout Workflow is a set of prebuilt UI components that streamlines making a Payment. By starting a checkout session with the Workflows Javascript library, you can enable the full Checkout UI.

How it works

Implementing the Checkout Workflow can be done in a few steps:

  1. Create a Public Key in the Connect Developer Portal.
  2. Embed the Checkout UI on your page, and supply it with your Public Key.
  3. Create a new Connect Checkout session when a user is ready to use the UI by supplying it with a secure Client Secret.
  4. Users follow the flow and create a Payment.

Client Secrets and Scoping

πŸ“˜

Client Secrets and iFrames

In order to create a valid session where users can securely make Payments, the Checkout Workflow requires a valid Client Secret to be passed in when loading the iFrame. Client Secrets can be made via a backend API call to the Client Secret API.

This guide assumes you have setup the logic to generate a Client Secret for your session, and that you're able to send that Client Secret to your front end code when instantiating the iFrame.

Client Secrets are used to authorize requests from the Checkout Workflow. The following Scenarios outline how you can expect Client Secrets to function during the Workflow:

  • If you are creating a Payer during the Workflow, you must provide a non-Payer-scoped Client Secret during instantiation (that is, your Client Secret should not be scoped to anothe Payer ID). Once a Payer is created, the provided Client Secret will automatically be scoped to that Payer.
  • If you are not creating a Payer and providing a Payer ID during instantiation, you must create a Client Secret uses the same Payer ID.
    • Similarly, if you are using an alternative Workflow to create isolated resources (like Card Capture), you will need to provide a Payer-scoped Client Secret.

See the Client Secrets documentation for more details.

Callbacks

The Checkout Workflow will invoke the callback function you define when you create a new session with a full Connect API payload, so that you can handle the following events during the workflow: successfully creating a resource, errors when creating a resource.

See the sample code below for how you can add callbacks under the handlers object to handle events:

const checkoutWorkflow = ConnectWorkflows.create('checkout', {
	...
  handlers: {
    onSuccess: function (data) {
      console.log('onSuccess Handler, data: ', data)
    },
    onError: function (data) {
      console.log('onError Handler, data: ', data)
    },
    onCancel: function (data) {
      console.log('onCancel Handler, data: ', data)
    },
  },
})

Passing in data

The Checkout Workflow supports passing in data during the instantiation of the app, so that you can preload previously created resources or autofill certain fields. Previously created resources must have been created by the same Payer or be a globally available resource (such as a partner-scoped Recipient).

Below is an example of showcasing passing in both previously created resources, and autofilling payment fields:

const checkoutWorkflow = ConnectWorkflows.create('checkout', {
  ...
  recipient: {
    id: 'recipientId',
  },
  payer: {
    id: 'payerId',
  },
  paymentIntent: {
    readOnly: false,
    details: {
      accountName: 'Test Account',
      accountNumber: "1234567890",
      memo: 'Test memo',
    },
    targetAmount: {
      value: '3000000.00',
    },
  },
})

Note: The paymentIntent pass-in object supports the readOnly boolean flag, which is false by default. If set to true, this will allow you to initiate a Checkout Workflow session with prefilled values that your user can view but not modify.

Custom Styles and Themes

The Checkout Workflow supports passing in a custom theme JSON object that would override the styles for any of the components you select. This object acts as a theme that can be applied globally. We use Material UI themed components in our Workflows Components; you can learn more information about how to override styles here: https://mui.com/material-ui/customization/theme-components/

Below is an example of some custom styles you can use to override base styles that come out of the box:

const customTheme = {
  "typography": {
    "fontFamily": "verdana"
  },
  "palette": {
    "primary": {
      "main": "#FFA500"
    }
  },
  "components": {
    "MuiButton": {
      "styleOverrides": {
        "root": {
          "fontSize": "5rem"
        }
      }
    }
  }
}

const checkoutWorkflow = ConnectWorkflows.create('checkout', {
  ...
  theme: customTheme
})

Setting up Connect Checkout

Include the Workflows Javascript library on your webpage:

<head>
  ...
  <script src="https://workflows.connect.sandbox.plastiq.com/libraries/start-workflows.js"></script>
</head>
<body>
  ...
  <div id='workflows-demo'></div>
</body>

Create a new Workflows instance in your page's Javascript:

const ConnectWorkflows = new window.ConnectWorkflows(result.publicKey, {
  environment: 'sandbox'
})

Generate a Client Secret for your user to make secure requests in a backend service call:

const response = await fetch("https://connect.sandbox.plastiq.com/api/v2/client-secrets", {
  method: 'POST',
  headers: { api-key: 'your-api-key' }
})
const { clientSecret } = await response.json()

Create a new Checkout session with the Client Secret so that user can interact with the iFrame and make a Payment:

const checkoutWorkflow = ConnectWorkflows.create('checkout', {
  clientSecret,
  parentElement: '#connect-checkout'
})

Full Example

<head>
	...
  <script>
    const scriptSrc = 'https://workflows.connect.sandbox.plastiq.com/libraries/start-workflows.js'
    const workflowsAppScript = document.createElement('script')
     workflowsAppScript.src = scriptSrc
     document.head.appendChild(workflowsAppScript)
  </script>
</head>

<body>
  ...
  <div id="start-button" class="start-button" style="margin-top: 24px">
    <button onclick="loadConnectWorkflows()">Start Workflow</button>
  </div>

  <script>
    const customTheme = {
      "typography": {
        "fontFamily": "verdana"
      },
      "palette": {
        "primary": {
          "main": "#FFA500"
        }
      },
      "components": {
        "MuiButton": {
          "styleOverrides": {
            "root": {
              "fontSize": "5rem"
            }
          }
        }
      }
		}

    function loadConnectWorkflows() {
      const ConnectWorkflows = new window.ConnectWorkflows(publicKey, {
        environment: 'sandbox'
      })

      const checkoutWorkflow = ConnectWorkflows.create('checkout', {
        clientSecret,
        parentElement: '#connect-checkout',
        recipient: {
          id: 'recipientId',
        },
        payer: {
          id: 'payerId',
        },
        paymentIntent: {
          readOnly: false,
          details: {
            accountName: 'Test Account',
            accountNumber: "1234567890",
            memo: 'Test memo',
          },
          targetAmount: {
            value: '3000000.00',
          },
        },
        handlers: {
          onSuccess: function (data) {
            console.log('onSuccess Handler, data: ', data)
          },
          onError: function (data) {
            console.log('onError Handler, data: ', data)
          },
          onCancel: function (data) {
            console.log('onCancel Handler, data: ', data)
          },
        },
        theme: customTheme
     })
   }
  </script>
</body>

Alternative workflow configurations

Card Capture

πŸ“˜

Client Secrets

Adding a card requires you to generate and pass in a Client Secret that is scoped to a Payer. See: https://docs.developer.plastiq.com/docs/client-secrets-overview

const customTheme = {
  "typography": {
    "fontFamily": "verdana"
  },
  "palette": {
    "primary": {
      "main": "#FFA500"
    }
  },
  "components": {
    "MuiButton": {
      "styleOverrides": {
        "root": {
          "fontSize": "5rem"
        }
      }
    }
  }
}

...

function loadConnectCardWorkflow() {
  const ConnectWorkflows = new window.ConnectWorkflows(publicKey, {
    environment: 'sandbox'
  })

  const cardWorkflow = ConnectWorkflows.create('cardCapture', {
    clientSecret,
    parentElement: '#connect-card-capture',
    payer: {
      id: 'payerId',
    },
    handlers: {
      onSuccess: function (data) {
        console.log('onSuccess Handler, data: ', data)
      },
      onError: function (data) {
        console.log('onError Handler, data: ', data)
      },
      onCancel: function (data) {
        console.log('onCancel Handler, data: ', data)
      },
    },
    theme: customTheme
  })
}