> For the complete documentation index, see [llms.txt](https://horizon-development.gitbook.io/horizon-development/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://horizon-development.gitbook.io/horizon-development/products/horizon-payment-system.md).

# Horizon Payment System

## **Purchase**

Click [here](https://horizon-development-store.tebex.io/package/6455915) to purchase the script.

## Preview

Click [here](https://youtu.be/FDz17GF-g4g) to watch the preview video.

## Installation

1. [Download](https://forum.cfx.re/uploads/short-url/xGXMVuvOOa36qM1W5IVFBl60RDF.zip) and drop the bzzz\_terminal folder into your server resources folder.
2. Drop the horizon\_paymentsystem folder into your server resources folder.
3. Add these lines to your server.cfg:&#x20;

   start bzzz\_terminal

   start horizon\_paymentsystem
4. Configure the script if needed.
5. Restart your server.

## Requirements

* ESX Legacy/QBCore
* [bzzz\_terminal](https://forum.cfx.re/uploads/short-url/q7snxQTCu0FTUSVga1DNKN673wv.zip)

## Integration into other resources

Horizon Payment System allows easy integration of payment via terminal into other resources such as a shop, car dealership or any other script.

### Export on the client side

<pre class="language-lua" data-full-width="true"><code class="lang-lua">exports["horizon_paymentsystem"]:startPayment(
    "SELLER NAME", -- Seller name (e.g. 24/7 Store, Premium Deluxe Motorsport)
    PAYMENT AMOUNT, -- Total amount of the payment
    { -- List of items that will appear on the receipt (could be nil)
        {item = "ITEM NAME #1", price = TOTAL PRICE, amount = AMOUNT} -- "amount" could be nil
        {item = "ITEM NAME #2", price = TOTAL PRICE, amount = AMOUNT} -- "amount" could be nil
    },
    { -- OnSuccess event, triggered by successful payment
        event = "EVENT_NAME", args = {ARG1 = "ARGUMENT #1", ARG2 = "ARGUMENT #2"}
    },
    { -- OnFail event, triggered by unsuccessful payment
<strong>        event = "EVENT_NAME", args = {ARG1 = "ARGUMENT #1", ARG2 = "ARGUMENT #2"}
</strong>    }
)
</code></pre>

### Export on the server side

<pre class="language-lua" data-full-width="true"><code class="lang-lua">exports["horizon_paymentsystem"]:startPayment(
    PLAYER, -- Player id who receives the payment request
    "SELLER NAME", -- Seller name (e.g. 24/7 Store, Premium Deluxe Motorsport)
    PAYMENT AMOUNT, -- Total amount of the payment
    { -- List of items that will appear on the receipt (could be nil)
        {item = "ITEM NAME #1", price = TOTAL PRICE, amount = AMOUNT} -- "amount" could be nil
        {item = "ITEM NAME #2", price = TOTAL PRICE, amount = AMOUNT} -- "amount" could be nil
    },
    { -- OnSuccess event, triggered by successful payment (could be nil)
        event = "EVENT_NAME", args = {ARG1 = "ARGUMENT #1", ARG2 = "ARGUMENT #2"}
    },
    { -- OnFail event, triggered by unsuccessful payment (could be nil)
<strong>        event = "EVENT_NAME", args = {ARG1 = "ARGUMENT #1", ARG2 = "ARGUMENT #2"}
</strong>    }
)
</code></pre>

### Integration example (qb-vehicleshop)

{% code title="server.lua" fullWidth="true" %}

```lua
RegisterNetEvent('qb-vehicleshop:server:buyShowroomVehicle', function(vehicle)
    local src = source
    vehicle = vehicle.buyVehicle
    local pData = QBCore.Functions.GetPlayer(src)
    local cid = pData.PlayerData.citizenid
    local cash = pData.PlayerData.money['cash']
    local bank = pData.PlayerData.money['bank']
    local vehiclePrice = QBCore.Shared.Vehicles[vehicle]['price']
    local plate = GeneratePlate()
    if cash > tonumber(vehiclePrice) then
        MySQL.insert('INSERT INTO player_vehicles (license, citizenid, vehicle, hash, mods, plate, garage, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
            pData.PlayerData.license,
            cid,
            vehicle,
            GetHashKey(vehicle),
            '{}',
            plate,
            'pillboxgarage',
            0
        })
        TriggerClientEvent('QBCore:Notify', src, Lang:t('success.purchased'), 'success')
        TriggerClientEvent('qb-vehicleshop:client:buyShowroomVehicle', src, vehicle, plate)
        pData.Functions.RemoveMoney('cash', vehiclePrice, 'vehicle-bought-in-showroom')
    elseif bank > tonumber(vehiclePrice) then
        exports["horizon_paymentSystem"]:startPayment(
            src,
            "Premium Deluxe Motorsport",
            tonumber(vehiclePrice),
            {
                {
                    item = string.upper(vehicle).." (Plate: "..plate..")",
                    price = tonumber(vehiclePrice)
                }
            }, 
            {    
                event = "qb-vehicleshop:server:vehiclePurchaseSuccess",
                args = {
                    license = pData.PlayerData.license,
                    cid = cid,
                    vehicle = vehicle,
                    plate = plate
                }
            }
        )
    else
        TriggerClientEvent('QBCore:Notify', src, Lang:t('error.notenoughmoney'), 'error')
    end
end)

RegisterNetEvent("qb-vehicleshop:server:vehiclePurchaseSuccess", function(data)
    local src = source
    MySQL.insert('INSERT INTO player_vehicles (license, citizenid, vehicle, hash, mods, plate, garage, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
        data.license,
        data.cid,
        data.vehicle,
        GetHashKey(data.vehicle),
        '{}',
        data.plate,
        'pillboxgarage',
        0
    })
    TriggerClientEvent('QBCore:Notify', src, Lang:t('success.purchased'), 'success')
    TriggerClientEvent('qb-vehicleshop:client:buyShowroomVehicle', src, data.vehicle, data.plate)
end)
```

{% endcode %}

{% hint style="warning" %}
Horizon Payment System will not calculate the total amount of the payment from the subtotal of each item, nor will it calculate the subtotal of each item based on the number of items. These calculations must be done separately.
{% endhint %}

{% hint style="warning" %}
The specified onSuccess / onFail event will be interpreted as a client-side event if the export is triggered on the client side and as a server-side event if the export is triggered on the server side.

This behaviour can be overridden by specifying the value of "side" in the table containing the onSuccess / onFail event.&#x20;

Example:

{% code fullWidth="false" %}

```lua
{
    event = "EVENT_NAME", args = {}, side = "client"
}
```

{% endcode %}
{% endhint %}

## Changelog

### Update 1.1

* Fixed a bug that prevented players from receiving the requested amount to their personal account after a successful payment on ESX systems
* Fixed a bug that in some cases prevented the society account from receiving the requested amount after a successful payment on ESX systems
* Fixed a bug that in some cases prevented the PIN code of the players from being generated
* Fixed several bugs that caused some functions to fail in some cases
* Fixed a broken link in the README file for the product

### Update 1.2

* Several background processes have been added and modified to enable the use of Horizon Payment System and Horizon Cash Registers together
* A help window has been added to guide users when collecting a receipt
* A new configuration option has been added to allow customization of the currency symbol
* A new configuration option has been added to allow setting the maximum mouse movement speed above which the terminal will not accept the card
* The card acceptance process has been slightly refined
* Fixed a broken link in the README file for the product
* Fixed an issue that caused other players' names to be incorrectly retrieved in some cases
* Fixed an issue that caused an error message to be displayed when running certain background processes

## Common Errors
