> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gr4vy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Click to Pay Setup

## Merchant setup

To process Click to Pay payments, register as
a Digital Payments Application (DPA). Set up Click to Pay in the
Connections dashboard which automatically registers
and configures the DPA with Mastercard.

## Prepare the server

Before loading Click to Pay with Secure Fields into the checkout, generate a checkout session via the API. This is made easy with the
server-side SDKs.

### Install a server-side SDK

Use the package manager in the preferred programming language to install the
server-side SDK. Generating a checkout session can only be done server side and
doing this client side is not recommended as it exposes the API key to
customers.

<CodeGroup>
  ```sh C# theme={"system"}
  dotnet add package Gr4vy
  ```

  ```sh Go theme={"system"}
  go get github.com/gr4vy/gr4vy-go
  ```

  ```sh Java theme={"system"}
  # Please check for the latest version
  implementation 'com.gr4vy:sdk:1.0.0'
  ```

  ```sh PHP theme={"system"}
  composer require "gr4vy/gr4vy-php"
  ```

  ```sh Python theme={"system"}
  pip install gr4vy
  ```

  ```sh TypeScript theme={"system"}
  npm install @gr4vy/sdk
  # or: yarn add @gr4vy/sdk
  ```
</CodeGroup>

<Warning>
  Please install the [latest release](/guides/get-started#sdks-and-plugins) of the preferred SDK.
</Warning>

### Initialize the SDK client

Next, initialize the SDK with the ID of the instance and the private key.

<CodeGroup>
  ```csharp C# theme={"system"}
  using Gr4vy;
  using Gr4vy.Models.Components;
  using System.Collections.Generic;

  // Loaded the key from a file, env variable, 
  // or anywhere else
  var privateKey = "..."; 

  var sdk = new Gr4vySDK(
      id: "example",
      server: SDKConfig.Server.Sandbox,
      bearerAuthSource: Auth.WithToken(privateKey),
      merchantAccountId: "default"
  );
  ```

  ```go Go theme={"system"}
  package main

  import (
  	"context"
  	gr4vy "github.com/gr4vy/gr4vy-go"
  	"github.com/gr4vy/gr4vy-go/models/operations"
  	"log"
  	"os"
  )

  func main() {
  	ctx := context.Background()

  	privateKey := "...." // Private key loaded from disk or env var
  	withToken := gr4vy.WithToken(privateKey, []JWTScope{ReadAll, WriteAll}, 60)

  	s := gr4vy.New(
  		gr4vy.WithID("example"),
  		gr4vy.WithServer(gr4vy.ServerSandbox),
  		gr4vy.WithSecuritySource(withToken),
  		gr4vy.WithMerchantAccountID("default"),
  	)
  }
  ```

  ```java Java theme={"system"}
  package hello.world;

  import com.gr4vy.sdk.BearerSecuritySource;
  import com.gr4vy.sdk.Gr4vy;
  import com.gr4vy.sdk.Gr4vy.AvailableServers;
  import com.gr4vy.sdk.models.components.AccountUpdaterJobCreate;
  import com.gr4vy.sdk.models.errors.*;
  import com.gr4vy.sdk.models.operations.ListTransactionsRequest;
  import java.lang.Exception;
  import java.util.List;

  public class Application {

      public static void main(String[] args) throws Exception {

          String privateKey = "-----BEGIN PRIVATE KEY-----\n...."; // a valid private key

          Gr4vy sdk = Gr4vy.builder()
                  .id("example")
                  .server(AvailableServers.SANDBOX)
                  .merchantAccountId("default")
                  .securitySource(new BearerSecuritySource.Builder(privateKey).build())
              .build();
      }
  }
  ```

  ```php PHP theme={"system"}
  declare(strict_types=1);

  require 'vendor/autoload.php';

  use Gr4vy;
  use Gr4vy\Auth;

  // Loaded the key from a file, env variable, 
  // or anywhere else
  $privateKey = "..."; 

  $sdk = Gr4vy\SDK::builder()
      ->setId('example')
      ->setServer('sandbox')
      ->setSecuritySource(Auth::withToken($privateKey))
      ->setMerchantAccountId('default')
      ->build();
  ```

  ```python Python theme={"system"}
  from gr4vy import Gr4vy, auth
  import os

  client = Gr4vy(
      id="example",
      server="production",
      merchant_account_id="default",
      bearer_auth=auth.with_token(open("./private_key.pem").read())
  )
  ```

  ```ts TypeScript theme={"system"}
  import fs from "fs";
  import { Gr4vy, withToken } from "@gr4vy/sdk";

  const gr4vy = new Gr4vy({
      server: "sandbox",
      id: "example",
      bearerAuth: withToken({
        privateKey: fs.readFileSync("private_key.pem", "utf8"),
      }),
  });
  ```
</CodeGroup>

<Warning>
  This SDK needs to be initialized on your server-side. Please do not expose
  your private key to your client-side code.
</Warning>

This assumes the key you created in the previous step is kept in a secure location and
can be loaded as a string. You could store this key in an environment variable or a secure vault.

<Info>
  To learn more about the API authentication, and how to generate a bearer token
  for use without the SDKs, please see the more extensive [authentication
  guide](/guides/api/authentication).
</Info>

### Create a Checkout Session

With the SDK installed, use it to create a checkout session for use with
Click to Pay.

<CodeGroup>
  ```js Node theme={"system"}
  const response = await client.newCheckoutSession();
  ```

  ```py Python theme={"system"}
  response = client.create_new_checkout_session()
  ```

  ```php PHP theme={"system"}
  $checkout_session = $client->newCheckoutSession()
  ```

  ```java Java theme={"system"}
  CheckoutSession session = client.newCheckoutSession()
  ```

  ```shell cURL theme={"system"}
  curl -i -X POST "https://api.{instance_id}.gr4vy.app/checkout-sessions" \
      -H "Authorization: Bearer [JWT_TOKEN]" \
      -H "Content-Type: application/json"
  ```
</CodeGroup>

<br />

<Info>
  Please refer to the API reference to [learn more about our Checkout
  Sessions](/reference/checkout-sessions/new-checkout-session) and the
  additional options that can be passed when creating them.
</Info>

## Create your checkout

With your checkout session ready, it's time to start creating a card form that
can support Click to Pay.

The frontend integration is called Secure Fields and it essentially wraps each
of your credit card input fields in a secure element, keeping you PCI-compliant
and allowing for seamless integration with Click to Pay.

<Info>
  For more information on Secure Fields, please see the [detailed
  guide](/guides/payments/secure-fields/) which covers all the available
  options, events, and theming customizations available.
</Info>

### Install Secure Fields

There are three ways to install **Secure Fields** for use with Click to Pay:
either as a React library, a Node library or straight off the CDN.

<Tabs>
  <Tab title="React">
    ```bash theme={"system"}
    npm install @gr4vy/secure-fields-react --save
    # or: yarn add @gr4vy/secure-fields-react
    ```

    ### Initializing Secure Fields

    With **Secure Fields** installed it's now possible to initialize the connection
    to your instance. It expects the checkout session ID you created earlier.

    ```jsx theme={"system"}
    import { SecureFields } from "@gr4vy/secure-fields-react";

    <SecureFields
      gr4vyId="example"
      environment="sandbox"
      sessionId="8e2adc90-681d-442b-acd4-2d5182e62c72"
      // enable debugging
      debug
    >
      <Form />
    </SecureFields>
    ```

    <Warning>
      When `SecureFields` is loaded without a valid `sessionId` it will error. We recommend only loading
      the component if the session ID is set.

      ```jsx theme={"system"}
      {sessionId && (
        <SecureFields>
          ...
        </SecureFields>
      )}
      ```
    </Warning>

    ### Create a card form

    Next, add any of the 3 individual card fields to the form. Mix
    and match these with custom forms, and add custom labels.

    Let's start by adding the form with 4 fields: the card holder's name,
    the card number, card expiration date, and the security code for the card.

    ```jsx theme={"system"}
    import { 
      CardForm, 
      CardNumber, 
      ExpiryDate, 
      SecurityCode,
      useSecureFields
    } from '@gr4vy/secure-fields-react'

    const secureFields = useSecureFields()

    {/* This card form will automatically hide  */}
    <CardForm
      onVisibilityChange={(visible: boolean) => {
        console.log('Card form visibility changed. Visible', visible)
      }}
    >
      <div id="cc-form" className="max-w-xs">
        {/* You can add your own fields as well as secure fields */}
        <label for="cc-holder-name">Name</label>
        <input id="cc-holder-name" placeholder="Name on the card" />
        
        {/* These are fields that will become secure fields */}
        <label htmlFor="cc-number">Card number</label>
        <CardNumber styles={styles} />

        <label htmlFor="cc-expiry-date">Expiry date</label>
        <ExpiryDate styles={styles} />

        <label htmlFor="cc-security-code">Security code</label>
        <SecurityCode styles={styles} />

        <button onClick={() => secureFields.submit()}>Pay</button>
      </div>
    </CardForm>
    ```

    Each secure field should now be loaded on the page. Please see our more
    extensive guides on how to add [event listeners](/guides/payments/secure-fields/events) and
    custom [styles](/guides/payments/secure-fields/theming) to **Secure Fields**.

    ### Add Click to Pay

    Next, add the Click to Pay components to show and hide their UI on demand.

    ```jsx theme={"system"}
    import { 
      ClickToPay,
      ClickToPaySignIn
    } from '@gr4vy/secure-fields-react'

     {/* The main Click to Pay component */}
    <ClickToPay
      srcDpaId='{SRC_DPA_ID}'
      dpaName='{DPA_NAME}'
      dpaLocale='en_AU'
      cardBrands={['mastercard', 'visa', 'amex']}
      consentCheckbox='#click-to-pay-consent-checkbox'
      learnMoreLink="#click-to-pay-learn-more-link"
      // email='john@example.com' // optional: define a Click to Pay user e-mail instead of capturing it with the sign-in form
      /* mobileNumber={{
        countryCode: "61",
        phoneNumber: "491570159"
      }} */ // optional: define a Click to Pay user phone instead of capturing it with the sign-in form
    />

     {/* An optional sign-in with email or phone for Click to Pay would go here */}
    <ClickToPaySignIn data-testid="sign-in">
      <label>Access your Click to Pay stored cards</label>
      <input type="text" className="email" ref={ref} />
      {/* This shows how to sign in with email. For the mobile number use the `mobileNumber` with a `countryCode` and `number` */}
      <button onClick={() => secureFields.clickToPay.signIn({ email: ref.current.value })}>
        Sign in
      </button>
    </ClickToPaySignIn>

    <CardForm>
      {/* ... */}

      <input type="checkbox" id="click-to-pay-consent-checkbox" />
      <label htmlFor="click-to-pay-consent-checkbox">
        Store my card with Click to Pay <a href="javascript:void(0)" id="click-to-pay-learn-more-link">Learn more</a>
      </label>

      {/* ... */}
    </CardForm>
    ```

    <Note>
      Secure Fields will automatically display and hide the Click to Pay Component, the sign in form, and your card form, based on the
      status of Click to Pay.
    </Note>

    ### Handle form submission

    Once the data has been submitted, use the `onCardVaultSuccess` property
    on the `SecureFields` component to create a transaction.

    ```tsx theme={"system"}
    <SecureFields onCardVaultSuccess={async () => {
        // call your API
      }}
    >...</SecureFields>
    ```

    <Info>
      For more information on Secure Fields, please see our [detailed
      guide](/guides/payments/secure-fields/) which will cover all the available
      options, events, and theming customizations available.
    </Info>
  </Tab>

  <Tab title="Node/CDN">
    <CodeGroup>
      ```bash Node theme={"system"}
      npm install @gr4vy/secure-fields --save
      # or: yarn add @gr4vy/secure-fields
      ```

      ```html CDN theme={"system"}
      <script src="https://cdn.{gr4vyId}.gr4vy.app/secure-fields/latest/secure-fields.js"></script>
      <link
        rel="stylesheet"
        href="https://cdn.{gr4vyId}.gr4vy.app/secure-fields/latest/secure-fields.css"
      />

      <!-- Please replace the `{gr4vyId}` with the name of your instance. -->

      ```
    </CodeGroup>

    <Note>
      When using the CDN the latest version of the library is always pulled straight
      from the server for every request.
    </Note>

    ### Initializing Secure Fields

    With **Secure Fields** installed it's now possible to initialize the connection
    to your instance. It expects the checkout session ID you created earlier.

    ```js theme={"system"}
    import SecureFields from "@gr4vy/secure-fields";
    // set up the environment
    const gr4vyId = "example";
    const environment = "sandbox";
    const sessionId="8e2adc90-681d-442b-acd4-2d5182e62c72"
    // initialize the SDK
    const secureFields = new SecureFields({
      gr4vyId,
      environment,
      sessionId,
    });
    // enable debugging
    secureFields.setDebug(true);
    ```

    ### Create a card form

    Next, add any of the 3 individual card fields to the form. Mix
    and match these with custom forms, and add custom labels.

    Let's start by adding the form with 4 fields: the card holder's name,
    the card number, card expiration date, and the security code for the card.

    ```html theme={"system"}
    <form id="cc-form">
      <!-- You can add your own fields as well as secure fields -->
      <label for="cc-holder-name">Name</label>
      <input id="cc-holder-name" placeholder="Name on the card" />

      <!-- These are fields that will become secure fields -->
      <label for="cc-number">Card Number</label>
      <input id="cc-number" />

      <label for="cc-expiry-date">Expiry date</label>
      <input id="cc-expiry-date" />

      <label for="cc-security-code">Security Code</label>
      <input id="cc-security-code" />

      <input type="submit">Pay</button>
    </form>
    ```

    It is important to add all the card inputs including the number, expiration
    date, and security code. Without each of these fields, a transaction can not be
    processed. Additional inputs can be added to your form but they will not be
    handled by our library.

    Next, initialize each of the inputs as a secure field.

    ```js theme={"system"}
    // Add fields using a querySelector compatible string
    const number = secureFields.addCardNumberField("#cc-number", {
      placeholder: "Enter card number",
    });

    const securityCode = secureFields.addSecurityCodeField("#cc-security-code", {
      placeholder: "Enter CVV",
    });

    // Alternatively an HTML element can be passed directly
    const expiryDate = secureFields.addExpiryDateField(
      document.querySelector("#cc-expiry-date"),
      {
        placeholder: "Enter expiry date",
      }
    );
    ```

    This example replaces each of the `<input>` fields for the card form with a new
    PCI secure field. It's worth noting that we did not attach a secure field for
    the card holder name, instead, this field will remain a regular HTML input

    <Info>
      Every field that Secure Field is attached to needs to be an HTML element. In
      this case, we attached the fields to `<input>` fields. The fields can be
      attached to any element using a `querySelector`-compatible query.
    </Info>

    Each secure field should now be loaded on the page. Please see our more
    extensive guides on how to add [event listeners](/guides/payments/secure-fields/events) and
    custom [styles](/guides/payments/secure-fields/theming) to **Secure Fields**.

    ### Add Click to Pay

    Next, add a placeholder component to your form so we know where to render the
    Click to Pay component. Additionally, add a checkbox to allow a customer not
    already enrolled to determine if they want to share the card data with Click to
    Pay or not. Finally, add the rest of the Click to Pay components to show and hide
    their UI on demand.

    ```html theme={"system"}
    <div id="click-to-pay"></div>

    <!-- Small form to let users sign in with Click to Pay, hidden by default -->
    <div id="click-to-pay-sign-in" style="display: none;">
      <label>Access your Click to Pay stored cards</label>
      <input type="text" id="phoneOrEmail" />
      <button id="signInButton">Continue</button>
    </div>

    <form id="cc-form" style="display: none;">
      <!-- ...Secure fields inputs added previously -->

      <input type="checkbox" id="click-to-pay-consent-checkbox" />
      <label for="click-to-pay-consent-checkbox">
        Store my card with Click to Pay. <a href="javascript:void(0)" id="click-to-pay-learn-more-link">Learn more</a>
      </label>

      <input type="submit">Pay</button>
    </form>

    <script>
      var phoneOrEmail = document.querySelector('#phoneOrEmail')
      var signInButton = document.querySelector('#signInButton')
      signInButton.addEventListener('click', function () {
        clickToPay.signIn({ email: phoneOrEmail.value })
      })
    </script>
    ```

    Next, attach the secure field for Click to Pay to this element. This will require
    an HTML query for the consent checkbox that controls if the card data for a new card
    is shared with Click to Pay or not. Next to the consent label, add a link to let users
    learn more about Click to Pay. References to the card form and sign in HTML containers
    you added previously are also required.

    ```js theme={"system"}
    const clickToPay = secureFields.addClickToPay('#click-to-pay', {
      srcDpaId: '{SRC_DPA_ID}',
      dpaName: '{DPA_NAME}',
      dpaLocale: 'en_AU',
      cardBrands: ['mastercard', 'visa', 'american-express'],
      consentCheckbox: "#click-to-pay-consent-checkbox",
      learnMoreLink: "#click-to-pay-learn-more-link",
      cardForm: "#cc-form",
      signIn: "#click-to-pay-sign-in"
      // email: 'john@example.com', // optional: define a Click to Pay user e-mail instead of capturing it with the sign-in form
      /* mobileNumber: {
        countryCode: "61",
        phoneNumber: "491570159"
      }, */ // optional: define a Click to Pay user phone instead of capturing it with the sign-in form
    })
    ```

    <Note>
      Secure Fields will automatically display and hide the Click to Pay Component, the sign in form, and your card form, based on the
      status of Click to Pay.
    </Note>

    ### Handle form submission

    To handle a form submission, listen to the submission of the `<form>`
    element or a click of the submit button. Then prevent the default
    behavior and submit Secure Fields. This will instruct the fields to post the
    card data (regular, or Click to Pay) to the API.

    ```js theme={"system"}
    document.querySelector('#cc-form').addEventListener(
      "submit",
      (e) => {
        e.preventDefault()
        secureFields.submit()
      }
    )
    ```

    Once the data has been submitted, use the `secureFields` object to
    listen to the card data being successfully, or unsuccessfully vaulted.

    ```js theme={"system"}
    secureFields.addEventListener(
      SecureFields.Events.CARD_VAULT_SUCCESS,
      () => {
        // Make an API call to your server to complete the transaction
      }
    )

    secureFields.addEventListener(
      SecureFields.Events.CARD_VAULT_FAILURE,
      () => {
        // Handle the inability to store the card data
      }
    )
    ```

    <Note>
      In the case of a single-page app, it might be useful to unload any of the event
      listeners when the form is unloaded.
    </Note>
  </Tab>
</Tabs>

## Create a payment

With the card data stored in the vault, create a
transaction on the server-side. To create a transaction, pass the amount,
currency, as well as the payment method, in this case a checkout session.

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
      transactionCreate: new TransactionCreate()
      {
          Amount = 1299,
          Currency = "USD",
          Country = "US",
          PaymentMethod =
              TransactionCreatePaymentMethod.CreateCheckoutSessionWithUrlPaymentMethodCreate(
                  new CheckoutSessionWithUrlPaymentMethodCreate()
                  {
                      Id = checkoutSession.Id,
                  }
              ),
      }
  );
  ```

  ```go Go theme={"system"}
  amount := int64(1299)
  currency := "USD"

  checkoutSessionWithURLPaymentMethodCreate := components.CheckoutSessionWithURLPaymentMethodCreate{
      ID: checkoutSession.ID,
  }
  paymentMethod := components.CreateTransactionCreatePaymentMethodCheckoutSessionWithURLPaymentMethodCreate(checkoutSessionWithURLPaymentMethodCreate)

  transactionCreate := components.TransactionCreate{
      Amount:        amount,
      Currency:      currency,
      PaymentMethod: &paymentMethod,
  }

  transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil)

  // handle response
  ```

  ```java Java theme={"system"}
  CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
      .transactionCreate(TransactionCreate.builder()
          .amount(1299L)
          .currency("USD")
          .paymentMethod(TransactionCreatePaymentMethod.of(CheckoutSessionWithUrlPaymentMethodCreate.builder()
              .id(checkoutSession.id())
              .build()))
          .build())
      .call();

  Transaction transaction = transactionResponse.transaction().orElse(null);

  // handle response
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(amount: 1299, currency: 'USD', paymentMethod: new CheckoutSessionWithUrlPaymentMethodCreate(id: $checkoutSession->id));
  $response = self::$sdk->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction: models.Transaction = client.transactions.create(
      amount=1299,
      currency="USD",
      payment_method={
          "method": "checkout-session",
          "id": checkout_session.id,
      }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
      amount: 1299,
      currency: "USD",
      paymentMethod: {
      method: "checkout-session",
      id: checkoutSession.id
      }
  })
  ```
</CodeGroup>

The returned transaction includes details about the payment method used, and the
status of the transaction.

<CodeGroup>
  ```json Response theme={"system"}
  {
    "type": "transaction",
    "id": "fe26475d-ec3e-4884-9553-f7356683f7f9",
    "status": "authentication_succeeded",
    "amount": 1299,
    "currency": "AUD",
    "payment_method": {
      "type": "payment-method",
      "id": "77a76f7e-d2de-4bbc-ada9-d6a0015e6bd5",
      "method": "card",
      "scheme": "visa",
      "expiration_date": "07/24",
      ...
    },
    ...
  }
  ```
</CodeGroup>

<Warning>
  ### Client-side vs server-side

  A transaction should be created server-side instead of client-side, as
  there are many reasons why a success message may never reach your server, leaving
  you in a state where it's unclear if your transaction has succeeded.
</Warning>

## Error handling

The available error codes for Click to Pay are as follows.
It is recommended to catch and handle Click to Pay errors as required.

* `CODE_INVALID` - The user entered an incorrect OTP. An error message is also displayed
  on the OTP component.
* `INVALID_CARD` - The user entered incorrect card details, or the details of a card that
  is not one of the supported schemes.
* `ACCT_INACCESSIBLE` - The user's account is temporarily not accessible.
* `USER_NOT_RECOGNIZED` - The user is not recognized by Click to Pay (typically when a user
  hasn't signed in yet).
* `UNKNOWN` - An unknown error occurred. These are usually unrecoverable. For example, the
  Click to Pay library was not initialized due to an invalid parameter.
* `RETRIES_EXCEEDED` - The user has exceeded the maximum number of retries filling in
  their one-time password (OTP) and their profile is locked. An error message is also
  displayed in the OTP component. **It is recommended to hide the Click to Pay component
  for the user at this point.**
* `SIGN_OUT_FAILED` - When attempting to sign out via the "Not you?" link, it is possible
  that Click to Pay is not able to sign out the user. **It is recommended to hide
  the Click to Pay component for the user at this point.**

<Tabs>
  <Tab title="React">
    ```js theme={"system"}
    <SecureFields
      ...
      onClickToPayError={({ error }) => {
        if (error.code === 'RETRIES_EXCEEDED' ||
            error.code === 'SIGN_OUT_FAILED') {
          // Hide the Click to Pay component
          setClickToPayVisible(false);
        }
        console.error(error);
      }}
    />
    ```
  </Tab>

  <Tab title="Node/CDN">
    ```js theme={"system"}
    secureFields.addEventListener(
      SecureFields.Events.CLICK_TO_PAY_ERROR,
      ({ error }) => {
        console.error(error);

        if ((error.code === 'RETRIES_EXCEEDED' || 
              error.code === 'SIGN_OUT_FAILED') &&
              clickToPay) {
          // Hide the Click to Pay form
          clickToPay.hide();
        }
      }
    )

    ```
  </Tab>
</Tabs>

## Events

<Tabs>
  <Tab title="React">
    The following props can be used on the `SecureFields` component to listen to specific Click to Pay events.

    | Name                              | Event                                 | Description                                                                                           |
    | --------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------- |
    | `onMethodChange`                  | `METHOD_CHANGE`                       | Triggered when a user switches between the card and the Click to Pay payment methods.                 |
    | `onClickToPayInitialized`         | `CLICK_TO_PAY_INITIALIZED`            | Triggered when Click to Pay is loaded and its `init` method called successfully.                      |
    | `onClickToPayReady`               | `CLICK_TO_PAY_READY`                  | Triggered when a Click to Pay user is identified correctly and can start using Click to Pay.          |
    | `onClickToPaySignOut`             | `CLICK_TO_PAY_SIGN_OUT`               | Triggered when a Click to Pay user signs out using the "Not me" / "Not my cards" functionality.       |
    | `onClickToPayError`               | `CLICK_TO_PAY_ERROR`                  | See [Error Handling](#error-handling)                                                                 |
    | `onClickToPayCancel`              | `CLICK_TO_PAY_CANCEL`                 | Triggered when a Click to Pay user cancels the checkout process from within the UI.                   |
    | `onClickToPayCheckoutWithNewCard` | `CLICK_TO_PAY_CHECKOUT_WITH_NEW_CARD` | Triggered when a Click to Pay user starts the process of checking out with a new (not enrolled) card. |
    | `onClickToPayUnableToLoadDpa`     | `CLICK_TO_PAY_UNABLE_TO_LOAD_DPA`     | Triggered when the provided Click to Pay DPA cannot be loaded.                                        |

    Additionally, you can add the prop `onVisibilityChange` to the `ClickToPay`, `ClickToPaySignIn` and `CardForm`
    components to listen to visibility change events (`CLICK_TO_PAY_VISIBILITY_CHANGE`, `CLICK_TO_PAY_CARD_FORM_VISIBILITY_CHANGE`, `CLICK_TO_PAY_SIGN_IN_VISIBILITY_CHANGE`).

    ```js theme={"system"}
    <CardForm onVisibilityChange={(visible) => console.log('Card form visible', visible)} />
    ```
  </Tab>

  <Tab title="Node/CDN">
    The following Click to Pay events can be listened to by attaching an event handler to the
    `SecureFields` instance using the `addEventListener` method.

    | Name                                       | Description                                                                                           |
    | ------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
    | `METHOD_CHANGE`                            | Triggered when a user switches between the card and the Click to Pay payment methods.                 |
    | `CLICK_TO_PAY_INITIALIZED`                 | Triggered when Click to Pay is loaded and its `init` method called successfully.                      |
    | `CLICK_TO_PAY_READY`                       | Triggered when a Click to Pay user is identified correctly and can start using Click to Pay.          |
    | `CLICK_TO_PAY_SIGN_OUT`                    | Triggered when a Click to Pay user signs out using the "Not me" / "Not my cards" functionality.       |
    | `CLICK_TO_PAY_ERROR`                       | See [Error Handling](#error-handling)                                                                 |
    | `CLICK_TO_PAY_CANCEL`                      | Triggered when a Click to Pay user cancels the checkout process from within the UI.                   |
    | `CLICK_TO_PAY_CHECKOUT_WITH_NEW_CARD`      | Triggered when a Click to Pay user starts the process of checking out with a new (not enrolled) card. |
    | `CLICK_TO_PAY_UNABLE_TO_LOAD_DPA`          | Triggered when the provided Click to Pay DPA cannot be loaded.                                        |
    | `CLICK_TO_PAY_VISIBILITY_CHANGE`           | Triggered when the Click to Pay element is shown or hidden.                                           |
    | `CLICK_TO_PAY_CARD_FORM_VISIBILITY_CHANGE` | Triggered when the card form container is shown or hidden.                                            |
    | `CLICK_TO_PAY_SIGN_IN_VISIBILITY_CHANGE`   | Triggered when the sign in container is shown or hidden.                                              |

    ```js theme={"system"}
    // Listen for the different Click to Pay events
    secureFields.addEventListener(
      SecureFields.Events.METHOD_CHANGE, () => {
        console.log('Method changed');
      }
    )
    ```
  </Tab>
</Tabs>

## Links

<CardGroup cols={1}>
  <Card href="/guides/payments/secure-fields/quick-start/overview">**Quick start:** Secure fields</Card>
  <Card href="/guides/features/vault-forwarding/overview">**Guide:** Vault Forward</Card>
  <Card href="/reference/checkout-sessions/new-checkout-session">**API Reference:** New checkout session</Card>
  <Card href="/reference/transactions/new-transaction">**API Reference:** New transaction</Card>
</CardGroup>
