# How it works

Learn about PXP's Paze component for iOS.

## Overview

Paze is a US digital wallet that lets shoppers pay with cards stored in their Paze wallet. On iOS, the Paze component renders a native Paze-branded button, opens the Paze web checkout in an in-app browser session (`ASWebAuthenticationSession`), and orchestrates checkout completion, token decryption, and transaction submission through PXP.

With the Paze component, you can benefit from:

* **Secure checkout:** Payments use network tokens and cryptograms from the Paze wallet rather than raw card numbers.
* **Reduced friction:** Shoppers authenticate with Paze instead of entering card details manually.
* **Merchant approval gates:** Approve or reject checkout data, decryption, and authorisation at `onCheckoutComplete`, `onPreDecryption`, and `onPreAuthorisation`.
* **Flexible decryption:** Let the SDK decrypt tokens automatically, or handle decryption on your backend.
* **Fraud controls:** Integrate AVS and Kount risk screening through component configuration and callbacks.
* **Brand customisation:** Configure official Paze button colours, shapes, and labels to match your checkout.


Paze currently supports `USD` transactions only. The SDK validates currency during presentment and throws `SDK1213` if another currency is used.

Your backend session must include `allowedFundingTypes.wallets.paze` with `clientId` (presentment) and `merchantCategoryCode` (complete step on iOS). `merchantCategoryCode` is read from `CheckoutConfig.session`, not from `PazeButtonComponentConfig`:

```swift
// Required on CheckoutConfig.session — not on PazeButtonComponentConfig
session.allowedFundingTypes?.wallets?.paze?.merchantCategoryCode
```

Example session shape:

```swift
AllowedFundingType(
    wallets: Wallets(
        paze: Paze(
            clientId: "your-paze-client-id",
            merchantCategoryCode: "5812"
        )
    )
)
```

Without `merchantCategoryCode`, checkout can succeed but the complete step fails with `PazeMerchantCategoryCodeRequiredException` (`SDK1202A`).

## Presentment

On iOS, the Paze button uses static presentment: it appears after SDK validation without calling Paze `canCheckout()`. When the component view appears, the SDK:

1. Validates configuration from the correct sources:
  - `CheckoutConfig`: `clientName` (max 50 characters), `siteName` (max 50 characters)
  - Session data: `session.allowedFundingTypes?.wallets?.paze?.clientId`
  - `PazeButtonComponentConfig`: `paymentDescription` (max 25 characters), when set
2. Validates the optional shopper identity (`emailAddress`, `phoneNumber`) on `PazeButtonComponentConfig` when provided.
3. Confirms that `CheckoutConfig.transactionData.currency` is `USD`.
4. Calls `onInit`, shows the Paze button, and calls `onPresentmentResolved(true)`.


If validation fails, the button stays hidden and `onPresentmentResolved(false)` is called followed by `onError`.

```swift
// CheckoutConfig (passed to PxpCheckout.initialize(config:))
checkoutConfig.clientName
checkoutConfig.siteName

// Session data from your backend
session.allowedFundingTypes?.wallets?.paze?.clientId

// PazeButtonComponentConfig
pazeConfig.paymentDescription
```

Optional `emailAddress` and `phoneNumber` are passed to Paze during session creation when provided. Each field is validated independently at presentment and again at checkout time.

Set `transactionData.entryType` to `.ecom` when initialising the SDK. Paze expects an e-commerce entry type on the authorisation request, but the button component doesn't validate `entryType` at presentment.

## Payment flow

The Paze payment flow has five steps.

### Step 1: Presentment

The component validates configuration and renders the native Paze button in your SwiftUI view via `buildContent()`.

### Step 2: Checkout

When the shopper taps the button:

1. `onPazeButtonClicked` runs before checkout starts.
2. The SDK validates checkout configuration (amount, identity, billing preference, shipping countries, cobrand).
3. The SDK calls the PXP `create-session` API and receives a Paze checkout URL.
4. `ASWebAuthenticationSession` opens the Paze web checkout.
5. The shopper completes or abandons checkout. The session returns to your app via your registered URL scheme (default `pxpcheckout://paze`).


### Step 3: Merchant validation

If checkout returns `COMPLETE`, `onCheckoutComplete` is called with checkout details including masked card and consumer data. Return `false` to reject the checkout. The SDK treats it as incomplete and calls `onCheckoutIncomplete`.

### Step 4: Completion and decryption

If you approve checkout, the SDK calls the Paze complete API with `transactionType: "PURCHASE"` and receives a `securedPayload`. The complete request requires `session.allowedFundingTypes?.wallets?.paze?.merchantCategoryCode` — if it's missing, the SDK throws `SDK1202A` (`PazeMerchantCategoryCodeRequiredException`) even when checkout returned `COMPLETE`. `onComplete` fires with the decoded response before decryption. By default, the SDK decrypts through the PXP `decrypt-token` API. Return `false` from `onPreDecryption` to handle decryption on your backend instead.

The Paze complete step always uses `transactionType: "PURCHASE"`. Your session card intent (`.authorisation` or `.purchase`) applies to the Unity authorisation request after decryption, not to the complete call. See [Transaction intents](#transaction-intents).

### Step 5: Authorisation

After decryption, the SDK builds a scheme-token card transaction and submits it to PXP (calling `onGetShopper` when configured). Use `onPreAuthorisation` to provide risk screening data or abort the flow. `onPostAuthorisation` receives transaction identifiers when the SDK gets a `MerchantSubmitResult`. Verify the outcome on your backend. Authorisation failures surface through `onSubmitError`.

```mermaid
sequenceDiagram
    participant App as Your iOS app
    participant SDK as PXP SDK
    participant Browser as ASWebAuthenticationSession
    participant Paze as Paze checkout
    participant PXP as PXP API

    App->>SDK: Display component (buildContent)
    SDK-->>App: onInit / onPresentmentResolved
    App->>SDK: Shopper taps button
    SDK-->>App: onPazeButtonClicked
    SDK->>PXP: create-session
    PXP-->>SDK: pazeCheckoutUrl
    SDK->>Browser: Open checkout URL
    Browser->>Paze: Shopper completes checkout
    Paze-->>Browser: Redirect to pxpcheckout://paze
    Browser-->>SDK: Callback URL
    SDK-->>App: onCheckoutComplete
    alt merchant approves
        SDK->>PXP: complete
        SDK-->>App: onComplete
        SDK->>PXP: decrypt-token (unless manual)
        SDK-->>App: onPostDecryption
        SDK-->>App: onPreAuthorisation
        SDK->>PXP: authorise transaction
        alt authorisation succeeds
            SDK-->>App: onPostAuthorisation
        else authorisation fails
            SDK-->>App: onSubmitError
        end
    else merchant rejects or shopper cancels
        SDK-->>App: onCheckoutIncomplete
    end
```

## Supported card networks

Paze supports:

- Visa
- Mastercard
- Discover


Configure accepted networks with `acceptedPaymentCardNetworks` on `PazeButtonComponentConfig`. When all three networks are selected or the property is `nil`, no network filter is sent to Paze.

## Button customisation

The component renders native Paze button artwork. Configure appearance with `PazeButtonStyleConfig` on `PazeButtonComponentConfig`. When `style` isn't set, the SDK uses defaults (auto colour, rounded shape, checkout-with label). See [Configuration](/guides/checkout/components/ios/paze/configuration#styling) for the full reference.

| Colour | Description |
|  --- | --- |
| `.auto` (default) | Adapts to light/dark mode (Paze blue in light mode, white in dark mode). |
| `.pazeBlue` | Paze brand blue background with white label. |
| `.white` | White background with Paze blue label. |
| `.whiteWithOutline` | White background with outline border. |
| `.midnightBlack` | Midnight black background with white label. |


| Shape | Description |
|  --- | --- |
| `.rounded` (default) | Rounded corners (4pt radius). |
| `.rectangle` | Square corners (0pt radius). |
| `.pill` | Fully rounded pill shape. |


| Label | Description |
|  --- | --- |
| `.checkoutWith` (default) | "Check out with Paze" label artwork. |
| `.checkout` | "Paze checkout" label artwork. |
| `.pazeCheckout` | "Paze checkout" alternate artwork. |
| `.donateWith` | "Donate with Paze" label artwork. |


Set `disableMaxHeight` to `true` to remove the default 48pt height cap so the button can expand vertically within its container.

## Decryption options

The component supports two decryption approaches:

* **SDK-managed decryption (default):** The SDK calls the PXP `decrypt-token` endpoint after `onComplete`. Implement `onPostDecryption` to inspect the decrypted token before authorisation.
* **Manual decryption:** Return `false` from `onPreDecryption` to skip SDK decryption. Use `onComplete` to receive the `securedPayload` and decrypt from your backend. See [Implementation](/guides/checkout/components/ios/paze/implementation#backend-decryption).


## Transaction intents

Paze transactions are submitted as scheme-token card payments. Configure `transactionData.entryType` as `.ecom` and set the card intent when you initialise the SDK:

| Intent | Description |
|  --- | --- |
| `.authorisation` | Authorise and hold funds for later capture. |
| `.purchase` | Capture payment immediately. |


Card intent controls the Unity authorisation request the SDK submits after decryption. It doesn't change the Paze complete step: the SDK always sends `transactionType: "PURCHASE"` when calling the Paze complete API after checkout, regardless of whether you configured `.authorisation` or `.purchase` on `transactionData.intent.card`.

## Fraud and address verification

* **AVS:** Set `performAVS` to `true` on `PazeButtonComponentConfig` when a billing address is returned from decryption. Set `billingPreference` to `.all` so Paze collects billing data during checkout. If you use manual backend decryption, apply AVS on your own transaction request instead.
* **Kount:** Return `PazePreAuthorisationResult.transactionInitData(...)` from `onPreAuthorisation` with `riskScreeningData`. Set `kountDisabled: true` on `CheckoutConfig` when calling `PxpCheckout.initialize(config:)` to disable Kount device fingerprinting.


## What's next?

- [Implementation](/guides/checkout/components/ios/paze/implementation): Install the SDK, register your URL scheme, and integrate the Paze button.
- [Configuration](/guides/checkout/components/ios/paze/configuration): Explore component properties and callbacks.
- [Events](/guides/checkout/components/ios/paze/events): Reference all Paze callbacks and payload types.