createCheckoutWithCard

CheckoutWithCard element is an embeddable iframe that allows your buyers to purchase your NFT with credit card.

518518

"Enter card information" page

529529

"Review your purchase" page

The native Javascript offers you three composable pieces to create the CheckoutWithCard element:

  1. createCheckoutWithCard
  2. createCheckoutWithCardLink
  3. createCheckoutWithCardMessageHandler

If you're looking to use the native JS SDK and get started as soon as possible, you'll start with the createCheckoutWithCard which uses both createCheckoutWithCardLink and createCheckoutWithCardMessageHandler under the hood to create the CheckoutWithCard element.

createCheckoutWithCard

Code Snippet

import {
  createCheckoutWithCardElement,
} from '@paperxyz/js-client-sdk';

// Assuming a container exists:
//      <div id="paper-checkout" />

createCheckoutWithCardElement({
  sdkClientSecret,
  elementOrId: 'paper-checkout',
  appName,  
  options,
  onLoad() {},
  onError(error) {
    console.log("error", error);
  },
  onPaymentSuccess({ id }) {
    console.log("transactionId", id);
  },
  onOpenKycModal({ iframeLink }) {
    // You should open the iframeLink in an iframe embedded in a modal of your choice
    console.log("iframeLink", iframeLink);
  },
  onCloseKycModal: () => {
    // you can close the modal that was opened from the KYC previously here
    console.log("close kyc modal");
  },
  onReview({ cardholderName, id }) {
    console.log("cardholderName, id", cardholderName, id);
  },
});

// Alternatively, insert the iframe programmatically:
//      const iframe = createCheckoutWithCardElement(...)
//      document.getElementById('paper-checkout').appendChild(iframe);

Props

PropsTypeDescription
sdkClientSecretstringRequired

The client secret returned from the Checkout SDK intent API.
elementOrIdstring | HTMLElementOptional

If provided, the iframe will be appended this element.

Note that you can either pass in a reference to the containing element or the id associated with the containing element
appNamestring | undefinedOptional

If provided, the wallet card will display your appName.
optionsICustomizationOptionsOptional

See Customizing Checkout Elements.
onLoad() => voidOptional

This callback will be called when the iframe loads.
onError(error: PaperSDKError) => voidOptional

This callback will be called when an error occurs during the payment process.
onPaymentSuccess(props : { id: string }) => void)Optional

This callback will be called when the buyer has successfully paid.
onCloseKycModal() => voidRequired

This callback allows you to close the iframe that was previously displaying the KYC details.
onOpenKycModal(props: { iframeLink: string }) => voidRequired

This callback provides a link which developers must load in an iframe to complete the purchase.

Failing to do so would mean that the buyer's purchase will not complete.
onReview(props: { cardholderName: string, id: string }) => voidOptional

This callback will be called after the user enters their card details.

createCheckoutWithCardLink

This is the core building block that builds up the iframe link required to display the CheckoutWithCard element.

Once you generate the link, you can proceed to display it in an iframe but you'd still need to listen for a couple of events on the document in order to know when a payment is successful or when the user has to KYC. We provide a handler which does most of the heavy lifting.

Code Snippet

const checkoutWithCardUrl = createCheckoutWithCardLink({
    sdkClientSecret,
    appName,
    options,
});

Props

PropsTypeDescription
sdkClientSecretstringRequired

The client secret you get from create checkout SDK intent
appNamestring | undefinedOptional

If provided, the wallet card will display your appName.
optionsICustomizationOptionsOptional

See Customizing Checkout Elements.

createCheckoutWithCardMessageHandler

This is the message handler that is to be registered.

Essentially, this listens to six main events:

  1. checkoutWithCardError
  2. paymentSuccess
  3. reviewComplete
  4. openModalWithUrl
  5. completedSDKModal
  6. sizing.

Code Snippet

const iframe = document.createElement("iframe");

window.addEventListener(
    "message",
    createCheckoutWithCardMessageHandler({
      iframe,
      onCloseKycModal,
      onOpenKycModal,
      onError,
      onPaymentSuccess,
      onReview,
    })
);

Props

PropsTypeDescription
iframeHTMLIFrameElementRequired

The iframe that is displaying the link from createCheckoutWithCardLink
onCloseKycModal() => voidRequired

This callback allows you to close the iframe that was previously displaying the KYC details.
onOpenKycModal(props: { iframeLink: string }) => voidRequired

This callback provides a link which developers must load in an iframe to complete the purchase. Failing to do so would mean that the buyer's purchase will not complete.
onError(error: PaperSDKError) => voidOptional

If provided, the callback will be called when anything wrong happens during the payment process.
onPaymentSuccess(props : { id: string }) => void)Optional

If provided, the callback will be called when the buyer has successfully paid.
onReview(props: { cardholderName: string, id: string }) => voidOptional

If provided, the callback will be called when the user clicks the button after the enter their card details.

Writing your own handler

You can write your own handler if you wish, Here's how:

The event object that is passed by default into the message event contains the data filed which has the following type

type event.data = {
    eventType: 'checkoutWithCardError',
  code: PaperSDKErrorCode,
  error: Error
}   | {
  eventType: 'paymentSuccess',
  id: string
} | {
    eventType: 'reviewComplete',
  id: string,
  cardholderName: string
} | {
    eventType: 'openModalWithUrl',
  iframeLink: string,
} | {
  eventType: 'completedSDKModal'
} | {
    eventType: 'sizing'
  height: string,
  width: string,
}

You simply create a function that handles or ignores either of the two events, exactly the way you want:

window.addEventListener('message', (event: MessageEvent) => {
    // we use this alternate domain to avoid certain firewalls blocking .xyz domains 
        if (!event.origin.startsWith("https://papercheckout.com")) {
      return;
    }
    const data = event.data;
    switch(data.eventType): {
        case "checkoutWithCardError": {
        break;
      }
      case "paymentSuccess": {
        break;
      }
      case "reviewComplete": {
        break;
      }
      case "openModalWithUrl": {
        break;
      }
            case "completedSDKModal": {
        break;
      }
      case "sizing": {
        break;
      }
    }
});