# onPurchaseFailed

### Purpose

Triggered when a purchase fails due to insufficient funds, out of stock items, or other reasons. Use this hook to play error sounds and show failure messages.

### When It Triggers

* Server rejects the purchase for any reason
* Validation fails (insufficient funds, out of stock, etc.)

### Parameters

| Parameter            | Type   | Description                    |
| -------------------- | ------ | ------------------------------ |
| `data.shopId`        | string | Unique shop identifier         |
| `data.shopName`      | string | Display name of the shop       |
| `data.reason`        | string | Failure reason code            |
| `data.reasonMessage` | string | Human-readable failure message |
| `data.cartTotal`     | number | Attempted purchase total       |
| `data.paymentMethod` | string | Attempted payment method       |

#### Reason Codes

| Code                 | Description                           |
| -------------------- | ------------------------------------- |
| `insufficient_funds` | Player doesn't have enough money      |
| `out_of_stock`       | One or more items are out of stock    |
| `inventory_full`     | Player inventory is full              |
| `restricted_item`    | Player doesn't meet item requirements |
| `shop_closed`        | Shop is closed (opening hours)        |
| `banned`             | Player is banned from this shop       |
| `invalid_coupon`     | Coupon code is invalid/expired        |
| `license_required`   | Player lacks required license         |
| `unknown`            | Unknown error                         |

### Example

```lua
exports['sd-shops']:registerClientHook('onPurchaseFailed', function(data)
    -- Hide loading indicator
    lib.hideTextUI()

    -- Play error sound
    PlaySoundFrontend(-1, 'ERROR', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true)

    -- Show error notification
    lib.notify({
        title = 'Purchase Failed',
        description = data.reasonMessage,
        type = 'error'
    })

    -- Handle specific failure reasons
    if data.reason == 'insufficient_funds' then
        print(('[PURCHASE] Not enough money. Need $%d'):format(data.cartTotal))
    elseif data.reason == 'inventory_full' then
        lib.notify({
            description = 'Clear some inventory space and try again',
            type = 'warning'
        })
    end
end)
```
