Overview

With version 2 of our Web SDK, Universal Checkout automatically creates and handles Payments by default. This greatly reduces the complexity and amount of boilerplate required to integrate Primer.

For backward compatibility reasons, it is still possible to manually create and resume payments. Follow this guide to setup Universal Checkout so that you handle the payment lifecycle.

Flow

Manual payment creation flow

  1. Generate a clientToken on your backend by creating a Client Session with
  2. Initialize Universal Checkout with the clientToken to render the UI.
  3. Universal Checkout will generate a paymentMethodToken when the customer submits their payment data, or when they select particular payment methods.
  4. Create a payment using the paymentMethodToken via the Payments API
  5. If the response indicates a requiredAction, you’ll get a new clientToken.
  6. Pass the clientToken back to Universal Checkout to render next steps, like 3DS, and get a resumeToken.
  7. Call with the resumeToken to resume the payment and wrap things up. (If a new requiredAction is returned, you’ll have to go back to step 5.)

Generate a Client Token

Get an API Key

Ensure you have an API key configured. Make sure to set the following scopes for your API Key:

  • client_tokens:write
  • transactions:authorize

Generate a Client Session

Follow the instructions here to create a client session, which will be used to initialize the checkout.

Set up Universal Checkout

Step 1. Turn off automatic payment creation

The Universal Checkout option paymentHandling defines how the SDK should handle payment creation and resume.

Set paymentHandling to MANUAL to turn off automatic payment handling.

This disables the callbacks onBeforePayment and onCheckoutComplete.

Typescript
Primer.showUniversalCheckout(clientToken, {
	/* Other options... */

	paymentHandling: 'MANUAL',
})

Step 2. Handle callbacks for creating and resuming payments

Two callbacks must be implemented:

  • onTokenizeSuccess() to create payments with paymentMethodToken
  • onResumeSuccess() to resume payments with resumeToken

Typescript
Primer.showUniversalCheckout(clientToken, {
	/* Other options... */

	paymentHanding: 'MANUAL',
	async onTokenizeSuccess(paymentMethodTokenData, handler) {
		// Send the Payment Method Token to your server
		// to create a payment using Payments API
		const response = await createPayment(paymentMethodTokenData.token)

		// Call `handler.handleFailure` to cancel the flow and display an error message
		if (!response) {
			return handler.handleFailure('The payment failed. Please try with another payment method.')
		}

		// If a new clientToken is available, call `handler.continueWithNewClientToken` to refresh the client session.
		// The checkout will automatically perform the action required by the Workflow.
		if (response.requiredAction.clientToken) {
			return handler.continueWithNewClientToken(response.requiredAction.clientToken)
		}

		// Display the success screen
		return handler.handleSuccess()
	},

	async onResumeSuccess(resumeTokenData, handler) {
		// Send the resume token to your server to resume the payment
		const response = await resumePayment(resumeTokenData.resumeToken)

		// Call `handler.handleFailure` to cancel the flow and display an error message
		if (!response) {
			return handler.handleFailure('The payment failed. Please try with another payment method.')
		}

		// If a new clientToken is available, call `handler.continueWithNewClientToken` to refresh the client session.
		// The checkout will automatically perform the action required by the Workflow
		if (response.requiredAction.clientToken) {
			return handler.continueWithNewClientToken(response.requiredAction.clientToken)
		}

		// Display the success screen
		return handler.handleSuccess()
	},
})

Handle onTokenizeSuccess() callback

  • When a customer submits their payment data, the payment details are tokenized and you’ll receive a paymentMethodToken in onTokenizeSuccess()
  • Create a payment request with the paymentMethodToken
  • If the payment is successful, call handler.handleSuccess() in order to display a success screen.
  • If the payment is unsuccessful, call handler.handleFailure(errorMessage) to display an error / failed message.
  • Payments API may return a new clientToken for additional steps (in the requiredActions on the response). In this case, call handler.continueWithNewClientToken(clientToken) to the checkout.

Handle onResumeSuccess() callback

Handling onResumeSuccess() is required to fully support 3DS and the majority of payment methods.

  • You will receive a resumeToken via the onResumeSuccess() callback if applicable
  • Send a resume payment request with the resumeToken
  • If the payment is successful, call handler.handleSuccess() in order to display a success screen.
  • If the payment is unsuccessful, call handler.handleFailure(errorMessage) to display an error / failed message.
  • Payments API may again return a new clientToken for additional steps. In this case, call handler.continueWithNewClientToken(clientToken) again.