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

# Saved payment & upsell

> Two-page checkout using savePaymentMethod and paysightSession

Charge once on page 1, then charge again on page 2 without re-entering card details.

## Flow

```mermaid theme={null}
sequenceDiagram
  participant Host as Host page
  participant Widget as Widget iframe
  participant API as Paysight API

  Note over Host,Widget: Page 1 — checkout
  Host->>Widget: createWidget savePaymentMethod true
  Host->>Widget: submitPayment or wallet
  Widget->>API: initPayment savePaymentMethod
  API-->>Widget: paysightSession
  Widget-->>Host: PAYMENT_SUCCESS paysightSession

  Note over Host,Widget: Page 2 — upsell
  Host->>Widget: createWidget upsell initialPaymentSession
  Host->>Widget: submitUpsell
  Widget->>API: initPayment usePreviousPaymentMethod
  API-->>Widget: charge result
  Widget-->>Host: PAYMENT_SUCCESS mode upsell
```

## Page 1 — checkout

```javascript theme={null}
PaySightSDK.createWidget({
  targetId: 'payment-container',
  config: {
    productId: YOUR_PRODUCT_ID,
    sessionId: 'checkout-' + Date.now(),
    environment: 'sandbox',
    amount: 29.99,
    savePaymentMethod: true,
    customer: { email: 'customer@example.com', country: 'US' },
  },
  onMessage: (msg) => {
    if (msg.type === 'PAYMENT_SUCCESS') {
      const session = msg.payload?.paysightSession;
      sessionStorage.setItem('paysightSession', session);
      window.location.href = '/upsell';
    }
  },
});
```

`savePaymentMethod` applies to card, Apple Pay, and Google Pay.

## Page 2 — upsell

```javascript theme={null}
const paysightSession = sessionStorage.getItem('paysightSession');

PaySightSDK.createWidget({
  targetId: 'upsell-container',
  config: {
    productId: YOUR_PRODUCT_ID,
    sessionId: 'upsell-' + Date.now(),
    environment: 'sandbox',
    amount: 9.99,
    usePreviousPaymentMethod: true,
    upsell: {
      upsellId: 'addon-offer',
      initialPaymentSession: paysightSession,
      upsellButton: { text: 'Add to order' },
    },
    customer: { email: 'customer@example.com' },
  },
  onMessage: (msg) => {
    if (msg.type === 'PAYMENT_SUCCESS' && msg.payload?.mode === 'upsell') {
      redirectToThankYou();
    }
    if (msg.type === 'DUPLICATE_TRANSACTION') redirectToThankYou();
    if (msg.type === 'PAYMENT_ERROR' && msg.payload?.mode === 'upsell') {
      showError(msg.payload);
    }
  },
});
```

Upsell is active when both `upsell.upsellId` and `upsell.initialPaymentSession` are set.

<Callout type="warning">
  `initialPaymentSession` must be the `paysightSession` from page 1 `PAYMENT_SUCCESS` — not your `sessionId`.
</Callout>

## External pay button on upsell

Combine with `hidePaymentButton: true`:

```javascript theme={null}
widget.submitUpsell();
```

See [External payment button](/widget-sdk/guides/external-payment-button).

## 3DS on upsell

Set top-level 3DS flags on page 2, or override per upsell:

```javascript theme={null}
upsell: {
  upsellId: 'addon-offer',
  initialPaymentSession: paysightSession,
  threeDSRequired: true,
  cancelOnThreeDSFailure: true,
  failOnThreeDSChallenge: false,
}
```

## Events

Upsell charges emit the standard payment events. Use `payload.mode` to tell checkout from upsell.

| Event                   | When                                                        |
| ----------------------- | ----------------------------------------------------------- |
| `PAYMENT_SUCCESS`       | Page 1: read `paysightSession`. Page 2: `mode === 'upsell'` |
| `PAYMENT_START`         | Upsell charge started                                       |
| `PAYMENT_ERROR`         | Upsell charge failed (`mode === 'upsell'`)                  |
| `DUPLICATE_TRANSACTION` | Already charged for this session                            |

## Shopify variant

The same handoff works with Shopify cart mode on page 1. See [Shopify cart checkout](/widget-sdk/guides/shopify-cart-checkout).

## Live demo

[Saved payment example](/widget-sdk/examples/saved-payment-upsell) — live demo at `https://payment.paysight.io/demo?preset=upsell` (sandbox).

## Related

* [Core concepts](/widget-sdk/core-concepts)
* [Configuration reference](/widget-sdk/reference/configuration)
* [Events reference](/widget-sdk/reference/events)
