> ## 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.

# Troubleshooting

> Common Widget SDK issues and fixes

## Widget does not load

**Checklist:**

1. Script URL: `https://payment.paysight.io/widget-sdk.js`
2. `targetId` element exists in the DOM before `createWidget`
3. Page is HTTPS in production
4. Required config: `productId` (number), `sessionId`, `amount`, `environment`

```javascript theme={null}
PaySightSDK.createWidget({
  targetId: 'payment-container',
  config: {
    productId: YOUR_PRODUCT_ID,
    sessionId: 'YOUR_SESSION_ID',
    environment: 'sandbox',
    amount: 29.99,
  },
  onError: (err) => console.error('Init error', err),
});
```

## Wrong charge amount

`amount` is in **decimal major units** (`29.99` = \$29.99), **not cents**.

| Wrong          | Correct         |
| -------------- | --------------- |
| `amount: 2999` | `amount: 29.99` |

When `shopify` is configured, `amount` is ignored — totals come from cart lines.

## `productId` validation errors

`productId` must be a **number**, not a string:

```javascript theme={null}
// Wrong
productId: 'YOUR_PRODUCT_ID'

// Correct
productId: YOUR_PRODUCT_ID
```

## `environment` values

Valid values: `'sandbox'` and `'production'`.

Use `sandbox` for testing, `production` for live payments.

## Payment never starts with external button

When `hidePaymentButton: true`, you must call `submitPayment()` or `submitUpsell()` from the host page after `READY`.

```javascript theme={null}
widget.subscribe((msg) => {
  if (msg.type === 'READY') enablePayButton();
});
```

Calling `submitPayment()` during upsell mode returns `ERROR` with `INVALID_MODE` — use `submitUpsell()`.

## Upsell: "Initial session missing"

Page 2 must include:

```javascript theme={null}
upsell: {
  upsellId: 'your-offer',
  initialPaymentSession: paysightSessionFromPage1,
},
usePreviousPaymentMethod: true,
```

Store `paysightSession` from `PAYMENT_SUCCESS.payload` on page 1 — not your own `sessionId`.

## `DUPLICATE_TRANSACTION`

The upsell was already charged for this `initialPaymentSession`. Redirect to your thank-you page instead of retrying.

## 3DS failures

Listen for `PAYMENT_3DS_ERROR` and `PAYMENT_3DS_FAILURE`. Ensure `threeDSRequired` and related flags are set on both checkout and upsell configs when needed.

Upsell can override with `upsell.threeDSRequired`, `upsell.cancelOnThreeDSFailure`, `upsell.failOnThreeDSChallenge`.

## Wallet-only layout shows card form

`showOnlyWalletMethods` falls back to the full card UI when:

* No wallet is configured or available on the device
* Readiness times out (\~5s)
* A wallet payment fails (not user cancel)

Ensure `applePayEnabled` + `applePayOptions` or `googlePayEnabled` + `googlePayOptions` are fully set.

## Apple Pay / Google Pay button missing

Wallet buttons render on the **host page**, not inside the iframe. Pass `applePayContainerId` / `googlePayContainerId` and ensure those DOM elements exist.

## Iframe height issues

The SDK auto-resizes from `HEIGHT_CHANGE` events. If the iframe is clipped, ensure the container does not have a fixed height smaller than the content.

## Getting help

Log all `onMessage` events during reproduction:

```javascript theme={null}
onMessage: (msg) => console.log('[Widget]', msg.type, msg.payload),
```

Include `sessionId`, `productId`, `environment`, and event sequence when contacting Paysight support.

## Related

* [Error codes](/widget-sdk/reference/error-codes)
* [Configuration reference](/widget-sdk/reference/configuration)
* [API reference](/widget-sdk/reference/api)
