> For the complete documentation index, see [llms.txt](https://docs.thndr.io/integration/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thndr.io/integration/customisation/payment-errors.md).

# Payment Errors

Payment error handling allows your host application to hook into payment failure events - for example when a user has insufficient balance - and control how the game responds. This feature is **opt-in**. To enable it, notify your THNDR integration contact.

Once enabled, the integration is **required**. When a payment fails, the game emits a `postMessage` and waits for your app to respond with an action before proceeding. If your app does not respond, the game will hang indefinitely.

### The exchange

The flow is a two-step message exchange between the game and your host application.

#### Step 1 - Game notifies your app

When a payment error occurs, the game sends:

```json
{
  "message": "operator_handle_payment_error",
  "data": {
    "error": {}
  }
}
```

The `error` object contains details about what went wrong. Your app should inspect this to decide which action to return.

#### Step 2 - Your app responds with an action

Your host application must reply to the game with `operator_payment_error_handled` and one of four actions:

```json
{
  "message": "operator_payment_error_handled",
  "data": {
    "action": "RETRY"
  }
}
```

| Action           | Behaviour                                                        |
| ---------------- | ---------------------------------------------------------------- |
| `RETRY`          | The game retries the payment automatically                       |
| `GENERIC_ERROR`  | The game displays a standard error screen                        |
| `OPERATOR_ERROR` | The game displays a custom error message defined by you          |
| `IGNORE`         | The game handles the error silently with no user-facing feedback |

If you use `OPERATOR_ERROR`, include a `message` field with the text to display:

```json
{
  "message": "operator_payment_error_handled",
  "data": {
    "action": "OPERATOR_ERROR",
    "message": "Your account has insufficient funds. Please top up to continue."
  }
}
```

### Example listener

```javascript
window.addEventListener("message", (event) => {
  // Validate origin
  if (event.origin !== "https://game.thndr-cdn.com") return;

  let msg;
  try {
    msg = JSON.parse(event.data);
  } catch (e) {
    return;
  }

  if (msg.message.endsWith("operator_handle_payment_error")) {
    const error = msg.data?.error;

    // Inspect the error and decide how to respond
    const response = {
      message: "operator_payment_error_handled",
      data: {
        action: "RETRY", // Replace with your logic
      },
    };

    const iframe = document.getElementById("thndr-iframe");
    iframe.contentWindow.postMessage(
      JSON.stringify(response),
      "https://game.thndr-cdn.com"
    );
  }
});
```
