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

# Paze on web

> Add Paze to a web checkout using the Paze JavaScript SDK and the Gr4vy server SDK.

This guide shows how to add Paze to a web checkout. The shopper completes the Paze flow in the browser with the Paze JavaScript SDK, and your server uses the Gr4vy server SDK to create a Paze session and the resulting transaction.

For background on how Paze works and how Gr4vy fits in, read the [overview](/guides/features/paze/overview).

## Before you begin

Each merchant that wants to use Paze needs to be approved by Early Warning Services (EWS), and Gr4vy then enables Paze on a per-merchant basis. To start onboarding, see [Set up Paze](/connections/digital-wallets/paze#set-up-paze) on the connector page.

A runnable version of this integration is available in the [`sample-standalone-paze`](https://github.com/gr4vy/sample-standalone-paze) repository.

<Warning>
  The server-side examples assume you have already created a Gr4vy client authenticated with your private API key. See [Authentication](/guides/api/authentication) to create the client. Keep your API key and the Gr4vy client on the server — never expose them in browser code.
</Warning>

## Overview of the flow

The integration has server-side and browser-side steps:

1. **Server-side** — create a Paze session with Gr4vy. The session returns the Paze merchant data `id`, merchant `name`, and `profileId` that the Paze JavaScript SDK needs.
2. **Browser-side** — load the Paze JavaScript SDK, initialize it with the session, render the Paze button, and run the checkout.
3. **Server-side** — create a Gr4vy transaction with the opaque token that the Paze checkout returns.

## Step 1: Create a Paze session

On your server, create a Paze session with the domain that hosts the Paze button. Pass the full domain, including any subdomains such as `www.`.

<CodeGroup>
  ```csharp C# theme={"system"}
  var res = await client.DigitalWallets.Sessions.PazeAsync(
      pazeSessionRequest: new PazeSessionRequest()
      {
          DomainName = "www.example.com",
      }
  );

  PazeWebSession? session = null;
  if (res?.Type == ResponseCreatePazeDigitalWalletSessionType.PazeWebSession)
  {
      session = res.PazeWebSession;
  }
  ```

  ```go Go theme={"system"}
  domainName := "www.example.com"

  pazeSessionRequest := components.PazeSessionRequest{
      DomainName: &domainName,
  }

  res, err := client.DigitalWallets.Sessions.Paze(ctx, pazeSessionRequest)
  if err != nil {
      log.Fatal(err)
  }

  var session *components.PazeWebSession
  if res != nil {
      switch res.Type {
      case operations.ResponseCreatePazeDigitalWalletSessionTypePazeWebSession:
          session = res.PazeWebSession
      case operations.ResponseCreatePazeDigitalWalletSessionTypePazeMobileSession:
          // res.PazeMobileSession is populated for mobile sessions
      }
  }
  ```

  ```java Java theme={"system"}
  CreatePazeDigitalWalletSessionResponse res = gr4vyClient.digitalWallets().sessions().paze()
      .pazeSessionRequest(PazeSessionRequest.builder()
          .domainName("www.example.com")
          .build())
      .call();

  PazeWebSession session = null;
  if (res.responseCreatePazeDigitalWalletSession().isPresent()) {
      Object raw = res.responseCreatePazeDigitalWalletSession().get().value();
      if (raw instanceof PazeWebSession) {
          session = (PazeWebSession) raw;
      }
  }
  ```

  ```php PHP theme={"system"}
  $pazeSessionRequest = new PazeSessionRequest(domainName: 'www.example.com');
  $response = $sdk->digitalWallets->sessions->paze(pazeSessionRequest: $pazeSessionRequest);
  $session = $response->responseCreatePazeDigitalWalletSession;
  ```

  ```python Python theme={"system"}
  session = client.digital_wallets.sessions.paze(
      domain_name="www.example.com",
  )
  ```

  ```ts TypeScript theme={"system"}
  const session = await gr4vy.digitalWallets.sessions.paze({
    domainName: "www.example.com",
  });
  ```
</CodeGroup>

The session contains the values that the Paze JavaScript SDK needs. Return it to the browser.

```json Response theme={"system"}
{
  "id": "W8GT9RLCNME754Z7025613H3PDM2T4HF2CSAOi9w2kkP3D4S0",
  "name": "ACME",
  "profileId": "550e8400-e29b-41d4-a716-446655440000"
}
```

## Step 2: Load and initialize the Paze SDK

In the browser, add the Paze JavaScript SDK script for your environment. Use the sandbox script while testing, and the production script when you go live.

<CodeGroup>
  ```html Sandbox theme={"system"}
  <script src="https://checkout.wallet.uat.earlywarning.io/web/resources/js/digitalwallet-sdk.js"></script>
  ```

  ```html Production theme={"system"}
  <script src="https://checkout.paze.com/web/resources/js/digitalwallet-sdk.js"></script>
  ```
</CodeGroup>

Once the script loads, the SDK is available as `window.DIGITAL_WALLET_SDK`. Initialize it with the session from Step 1, then render the Paze button. The initialization is asynchronous, so call it from inside an `async` function.

```js theme={"system"}
const paze = window.DIGITAL_WALLET_SDK;

async function setupPaze(session) {
  await paze.initialize({ client: session });
}
```

```html theme={"system"}
<paze-button id="paze-button" label="Check out with" color="paze-blue" shape="default"></paze-button>
```

## Step 3: Run the checkout

When the shopper clicks the button, call `paze.checkout()` followed by `paze.complete()`. Generate a unique `sessionId` to correlate the two calls. The `complete()` response is the opaque token that your server sends to Gr4vy as `token`, and the `checkout()` response is sent as the optional `checkout_token` (named per your SDK's casing convention).

```js theme={"system"}
const button = document.getElementById("paze-button");

button.addEventListener("click", async () => {
  const sessionId = crypto.randomUUID();

  const { checkoutResponse, result } = await paze.checkout({
    sessionId,
    transactionValue: {
      transactionAmount: "50.21",
      transactionCurrencyCode: "USD",
    },
  });

  if (result === "COMPLETE") {
    const { completeResponse } = await paze.complete({
      sessionId,
      transactionType: "PURCHASE",
      transactionValue: {
        transactionAmount: "50.21",
        transactionCurrencyCode: "USD",
      },
    });
    // Send completeResponse and checkoutResponse to your server.
  }
});
```

<Note>
  The preceding example shows a minimal set of Paze SDK options. See the [`sample-standalone-paze`](https://github.com/gr4vy/sample-standalone-paze) repository for the full option set.
</Note>

## Step 4: Create a transaction

On your server, create the transaction with the token returned by `paze.complete()`. Set the payment method `method` to `paze` and `token` to the `complete()` response.

The `checkout_token` is optional but recommended. Set it to the `checkout()` response to add the card last four digits, card type, expiration, and shipping address to the transaction.

<Warning>
  The Paze JavaScript SDK takes `transactionAmount` as a decimal string in major units (for example `"50.21"`), while Gr4vy's transaction `amount` is an integer in the smallest currency unit (for example `5021` for \$50.21). Convert between the two when bridging the values, and make sure they match for the same purchase.
</Warning>

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
      transactionCreate: new TransactionCreate()
      {
          Amount = 5021,
          Currency = "USD",
          Country = "US",
          PaymentMethod = TransactionCreatePaymentMethod.CreatePazePaymentMethodCreate(
              new PazePaymentMethodCreate()
              {
                  Method = "paze",
                  Token = completeResponse,
                  CheckoutToken = checkoutResponse,
              }
          ),
      }
  );
  ```

  ```go Go theme={"system"}
  pazePaymentMethodCreate := components.PazePaymentMethodCreate{
      Method:        "paze",
      Token:         completeResponse,
      CheckoutToken: &checkoutResponse,
  }
  paymentMethod := components.CreateTransactionCreatePaymentMethodPazePaymentMethodCreate(pazePaymentMethodCreate)

  transactionCreate := components.TransactionCreate{
      Amount:        5021,
      Currency:      "USD",
      Country:       gr4vy.String("US"),
      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(5021L)
          .currency("USD")
          .country("US")
          .paymentMethod(TransactionCreatePaymentMethod.of(PazePaymentMethodCreate.builder()
              .method("paze")
              .token(completeResponse)
              .checkoutToken(checkoutResponse)
              .build()))
          .build())
      .call();

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

  // handle response
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(
      amount: 5021,
      currency: 'USD',
      country: 'US',
      paymentMethod: new PazePaymentMethodCreate(
          method: 'paze',
          token: $completeResponse,
          checkoutToken: $checkoutResponse,
      ),
  );
  $response = $sdk->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction = client.transactions.create(
      amount=5021,
      currency="USD",
      country="US",
      payment_method={
          "method": "paze",
          "token": complete_response,
          "checkout_token": checkout_response,
      },
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
    amount: 5021,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "paze",
      token: completeResponse,
      checkoutToken: checkoutResponse,
    },
  });
  ```
</CodeGroup>

The response is a standard Gr4vy transaction. Handle its `status` as you would for any other payment method.

## Test Paze

To test Paze, load your integration in the browser and complete a checkout with a Paze test wallet. Make sure your environment matches where Paze is configured, so that the browser loads the matching Paze SDK script: the sandbox script for `sandbox`, and the production script for `production`.

<Note>
  Test wallet credentials are issued by Paze, not by Gr4vy. To obtain a test wallet for your merchant, work with Paze directly through your Paze onboarding contact.
</Note>

For general sandbox environment information, see Paze's [Environments guide](https://developer.paze.com/design-sandbox/docs/environments).
