[DEV: PHP] Writing code to replenish balances in games and services
Tags: php, bitcoin, payments, apirone
Published: 2023-02-20 09:07:26

Let's say you have a gaming platform or service where you plan to accept cryptocurrency to top up users' balances. 

The Apirone [payment gate has wallets](https://apirone.com/docs/wallet/#create-wallet) for separate cryptocurrencies and [accounts] (https://apirone.com/docs/account/#create-account) that combine crypto wallets. Accounts and wallets can be created with an API request, which is very convenient when scaling and deploying ready-made projects. You can also do this on the page [https://apirone.com/dashboard/create](https://apirone.com/dashboard/create) Requests are completely anonymous, and you can create as many wallets and accounts as you like, without restrictions on the number. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zqj50clanyg7jddbe8v.png)

The main thing is to keep the wallet data in a safe place. 

Test wallet: tbtc-bde1cfc70297e4ff7068334b25986819
Transfer key: hyl1aQkd5vwdzT1uExgUCOXOcekUg4Yc

To replenish the balance for any amount, customers just need to see the [current rate](https://apirone.com/docs/rate/#ticker), payment address and [QR code](https://developers.google.com/chart/infographics/docs/qr_codes?hl=en). When paying in cryptocurrency, there is no payment purpose or exact amount, so the address is used as a payment identifier (for example, let's take the bitcoin blockchain). 
For each user, we create a separate bitcoin address with a [POST request](https://apirone.com/docs/wallet/#generate-address) with the parameters of the user id, email, or login. 
Also, you can add a secret key to increase the security of your platform. 

```
<?php 
$json_data = array ( "callback" => array( 'url'=> 'http://example.com/callback', 'data' => array ( 'user_id' => "1234", 'secret' => "7j0ap91o99cxj8k9"))); 
$wallet = "tbtc-bde1cfc70297e4ff7068334b25986819"; 
$api_base = "https://apirone.com/api/v2/wallets/". $wallet ."/addresses"; 
$curl = curl_init($api_base); 
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($curl, CURLOPT_POST, 1); 
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data)); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
$http_status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE); 
$response = curl_exec($curl); curl_close($curl); 
$decoded = json_decode($response, true); 
echo "Please send the payment to the following bitcoin address: " . $decoded["address"];
?>
```

In 'url'=> 'http://example.com/callback' change the example link to the page address for the callback on our website. This page will receive all information about incoming payments.

 'user_id' is some identifier of your client. 

'secret' is a secret code you have created, for additional security when receiving data from the payment service. 

$wallet -is an identifier of the wallet we are working with. 
In this example, we use the bitcoin testnet for debugging, in production change it to your wallet. 

You can create an unlimited number of addresses, and besides, they are eternal. This means that we always monitor them, and when a payment is received, we notify the specified url with all the saved parameters. 

On the balance replenishment page, it will be convenient for the client if the payment automatically appears on the screen. To do this, you can periodically request the database and check whether the payment is made. 

## Callback processing 

The callback page is used to receive transaction data and follow the business logic when paying. Apirone sends an address, amount, transaction hash, number of confirmations, and the data that we specified (user_id and secret) to this page. The data is sent with a POST request in JSON format, which is more convenient and safer. 

```
<?php
$secret = "7j0ap91o99cxj8k9";

//receive JSON data
$data = file_get_contents('php://input');

if ($data) {
    $params = json_decode($data, true);

    // Checking the secret code
    if ($params["data"]["secret"] !== $secret) die();

    $input_address = $params["input_address"];
    $value_in_satoshi = $params["value"];

    // If the number of confirmations = zero, then we write data into the database but do not pay 

    if ($params["confirmations"] == 0) {
    
        // Writing data about the transaction and 
        note the invoice status - waiting for payment confirmation
        
    }
    
    if ($params["confirmations"] >= 1) {
        
        // the transaction is confirmed in the network, we answer *ok* to the payment service and replenish the client balance        
        echo "*ok*";
    }
}
?>
```

P.S.:
> We strongly recommend charging payments after at least one confirmation in the network, and if amounts are significantly large, then after 3 confirmations. 
> We recommend storing integer satoshi amounts in the database because floating point values can lead to calculation errors. 
> The endpoint is the same for all wallets, change the $wallet parameter to Litecoin, Bitcoin Cash, Dogecoin, etc. New cryptocurrencies, stablecoins, and tokens will appear in the future.