Accepting payments

This section describes the mechanics in which FreedomPay deducts money in favor of the merchant and subsequently transfers it to the appropriate current account.

Acceptance of payments using bank cards and mobile commerce can be carried out in a test mode. Other methods will be available only in production mode.
Payment page

Payment initialization

Payment initialization
Request:
curl --location --request POST 'https://api.freedompay.uz/init_payment.php' \
--form 'pg_order_id=23' \
--form 'pg_merchant_id={{paybox_merchant_id}}' \
--form 'pg_amount=25' \
--form 'pg_description=test' \
--form 'pg_salt=molbulak' \
--form 'pg_sig={{paybox_signature}}'
# Signature example:
'init_payment.php;25;test;{{paybox_merchant_id}};23;molbulak;{{secret_key}}'

Reply:
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_payment_id>4567788</pg_payment_id>
    <pg_redirect_url>https://api.freedompay.uz/pay.html?customer=498333170d6a895148c57c53ffb18287</pg_redirect_url>
    <pg_redirect_url_type>need data</pg_redirect_url_type>
    <pg_salt>bdwLavL9lg6It91b</pg_salt>
    <pg_sig>709633e91387c56ac6fb7cb33d1e07d8</pg_sig>
</response>
Signature Generation
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};

$request = $requestForSignature = [
    'pg_order_id' => '23',
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_amount' => '25',
    'pg_description' => 'test',
    'pg_salt' => 'molbulak',
    'pg_currency' => 'KZT',
    'pg_check_url' => 'http://site.kz/check',
    'pg_result_url' => 'http://site.kz/result',
    'pg_request_method' => 'POST',
    'pg_success_url' => 'http://site.kz/success',
    'pg_failure_url' => 'http://site.kz/failure',
    'pg_success_url_method' => 'GET',
    'pg_failure_url_method' => 'GET',
    'pg_state_url' => 'http://site.kz/state',
    'pg_state_url_method' => 'GET',
    'pg_site_url' => 'http://site.kz/return',
    'pg_payment_system' => 'EPAYWEBKZT',
    'pg_lifetime' => '86400',
    'pg_user_phone' => '77777777777',
    'pg_user_contact_email' => 'mail@customer.kz',
    'pg_user_ip' => '127.0.0.1',
    'pg_postpone_payment' => '0',
    'pg_language' => 'ru',
    'pg_testing_mode' => '1',
    'pg_user_id' => '1',
    'pg_recurring_start' => '1',
    'pg_recurring_lifetime' => '156',
    'pg_receipt_positions' => [
        [
        'count' => '1',
        'name' => 'product name',
        'tax_type' => '3',
        'price' => '900',
        ]
    ],
    'pg_user_id' => '1',
    'pg_param1' => 'additional data',
    'pg_param2' => 'additional data',
    'pg_param3' => 'additional data',
];

/**
 * The function turns a multidimensional array into a flat one
 */
function makeFlatParamsArray($arrParams, $parent_name = '')
{
    $arrFlatParams = [];
    $i = 0;
    foreach ($arrParams as $key => $val) {
        $i++;
        /**
        * Make the name like tag001subtag001
        * So that you can then sort normally and nested nodes do not get confused when sorting
        */
        $name = $parent_name . $key. sprintf('%03d', $i);
        if (is_array($val)) {
            $arrFlatParams = array_merge($arrFlatParams, makeFlatParamsArray($val, $name));
            continue;
        }

        $arrFlatParams += array($name => (string)$val);
    }

    return $arrFlatParams;
}

// Turn the request object into a flat array
$requestForSignature = makeFlatParamsArray($requestForSignature);

// Signature generation
ksort($requestForSignature); // Sort by key
array_unshift($requestForSignature, 'init_payment.php'); // Adding to the beginning of the script name
array_push($requestForSignature, $secret_key); // Adding the private key to the end

$request['pg_sig'] = md5(implode(';', $requestForSignature)); // Received signature
There are two options for using the method:

  • Direct transfer of data from the merchant to FreedomPay
  • Transferring data through the user's browser to FreedomPay
When sending data directly from the merchant to FreedomPay, the merchant must send the data to init_payment.php.

When passing data through the user's browser to FreedomPay, the merchant will send the user with the given data to payment.php.

You can pass arbitrary additional parameters whose names do not start with pg_. All these parameters will be passed to pg_check_url and pg_result_url.

The names of additional merchant parameters must be unique.

After receiving the pg_redirect_url parameter, the user is redirected to the payment page, where the payer completes the payment.

If successful, the user will be redirected to the payment page.

If the merchant did not provide all the parameters necessary to create a payment transaction (payment system, user phone number and parameters required for the selected payment system), they are requested from the user on the freedompay.uz site.

Request URL

POST https://api.freedompay.uz/init_payment.php

Request fields

Response parameters
Request for check_url of the store. Checking the ability to make a payment.

An example of a negative response from a store
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment not allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Payment allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
To use this request, you should contact your manager.
Before accepting money from the buyer on the account, the payment gate can call the merchant script Check URL using the Request Method.

FreedomPay transmits information about the number, order properties and waits for a response. Failure to respond within the specified time is considered as a refusal to pay.

Check URL on the merchant side must be public, without authorization.

The Check URL script is called only if this option was enabled in the merchant settings.

Merchant response to check_url

If Check URL is empty at the time of payment initialization or not specified at the time of payment initialization, and set to empty in the merchant settings, then the payment possibility check step is skipped and it is considered that the merchant agrees to accept the payment.

  • If the store confirms the readiness of the order and the correct amount, it must respond in the form XML with status ok.
  • In case of refusal to pay rejected.
  • error - error in data interpretation.
Request URL

POST {{check_url}}

Request fields

Request for result_url of the store. Payment result
An example of a negative response from a store
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=0' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment cancelled</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Order paid</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
After receiving a payment from a client or if it is impossible to make a payment, FreedomPay calls the Result URL of the store and sends information about the payment result to it using the Request Method method.

Upon receipt of this request, the merchant must take the necessary actions to transfer the goods or services to the buyer, if the payment was successful. If pg_can_reject is equal to 1 and the merchant cannot accept the payment (for example, the ticket reservation has expired), it must respond with a rejected status, and FreedomPay will reject the payment. In this case, the pg_description field from the merchant response is shown to the user as the reason for the refusal.

Result URL on the merchant side must be public, without a authorization.

If the merchant's server is not available at the time the Result URL is called, or if the response from the server was not 200, FreedomPay will make repeated attempts to call it every half an hour for 2 hours, even if the pg_lifetime account expires.

If the first attempt to call Result URL is unsuccessful, then the payment is not canceled, and in subsequent calls Result URL does not allow the merchant to refuse the payment.

The store must be prepared for the Result URL to be called repeatedly for the same payment. Retry responses must match the original response, even if the pg_lifetime transaction has expired.

Merchant response to result_url

The rejected status can be returned by the merchant only if the pg_can_reject parameter equal to 1 was specified in the incoming request from the gate, otherwise, regardless of the merchant's response, the payment will be considered completed. If the merchant refused the payment (rejected answered), the buyer is redirected to Failure URL, otherwise - to Success URL.
  • ok - payment accepted
  • rejected - payment refusal if pg_can_reject is equal to 1
  • error - error in data interpretation
Request URL

POST {{result_url}}

Request fields

Return of the buyer to the merchant's website

After completing the payment in the online payment system, the buyer is redirected to the merchant page Success URL or Failure URL, depending on the result of the payment. Redirection occurs using the Success URL Method or Failure URL Method specified during payment initialization.

If at GET request Success URL or Failure URL already contain parameters in query string, then additional parameters pg_order_id, pg_payment_id and custom variables of the merchant are appended to the end of query string. The merchant must ensure that the names of additional parameters do not match the names of existing parameters.

The difference between Result URL and Success URL must be clearly understood.

Result URL is called directly from the FreedomPay server, while Success URL is called by the user's browser when FreedomPay redirects the user back to the store site. It is wrong to use Success URL as the only way to find out about the completion of the payment, because the user may for various reasons (for example, when the connection is broken) not to reach the Success URL after the payment. The most reliable way to find out about the completion of the payment is to implement a Result URL, which FreedomPay undertakes to call again every half an hour within 2 hours after the payment, if the first attempt for any reason failed.

Request URL

POST {{success_url}} or {{failure_url}}

Request fields

Payment frame

Payment initialization


Payment initialization

Request
curl --location --request POST 'https://api.freedompay.uz/init_payment.php' \
--form 'pg_order_id=23' \
--form 'pg_merchant_id={{paybox_merchant_id}}' \
--form 'pg_amount=25' \
--form 'pg_description=test' \
--form 'pg_payment_route=frame' \
--form 'pg_user_id=12345' \
--form 'pg_salt=molbulak' \
--form 'pg_sig={{paybox_signature}}'
# Signature example:
'init_payment.php;25;test;{{paybox_merchant_id}};23;molbulak;{{secret_key}}'

Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_payment_id>123456789</pg_payment_id>
    <pg_redirect_url>https://api.freedompay.uz/v1/merchant/12345/card/payment?pg_payment_id=12343245dfsdfij123</pg_redirect_url>
    <pg_redirect_url_type>need data</pg_redirect_url_type>
    <pg_salt>some_random_string</pg_salt>
    <pg_sig>your_signature</pg_sig>
</response>
There are two options for using the method:
  • Direct transfer of data from the merchant to FreedomPay
  • Transferring data through the user's browser to FreedomPay
When sending data directly from the merchant to FreedomPay, the merchant must send the data to init_payment.php.

When passing data through the user's browser to FreedomPay, the merchant will send the user with the given data to payment.php.

You can pass arbitrary additional parameters whose names do not start with pg_. All these parameters will be passed to pg_check_url and pg_result_url.

The names of additional merchant parameters must be unique.

After receiving the pg_redirect_url parameter, the user is redirected to the payment page where the payer completes the payment.

If successful, the user will be redirected to the payment page.

If the merchant did not provide all the parameters necessary to create a payment transaction (payment system, user phone number and parameters required for the selected payment system), they are requested from the user on the FreedomPay website.
Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};

$request = $requestForSignature = [
    'pg_order_id' => '23',
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_amount' => '25',
    'pg_description' => 'test',
    'pg_salt' => 'molbulak',
    'pg_payment_route' => 'frame',
    'pg_currency' => 'KZT',
    'pg_check_url' => 'http://site.kz/check',
    'pg_result_url' => 'http://site.kz/result',
    'pg_request_method' => 'POST',
    'pg_success_url' => 'http://site.kz/success',
    'pg_failure_url' => 'http://site.kz/failure',
    'pg_success_url_method' => 'GET',
    'pg_failure_url_method' => 'GET',
    'pg_state_url' => 'http://site.kz/state',
    'pg_state_url_method' => 'GET',
    'pg_site_url' => 'http://site.kz/return',
    'pg_payment_system' => 'EPAYWEBKZT',
    'pg_lifetime' => '86400',
    'pg_user_phone' => '77777777777',
    'pg_user_contact_email' => 'mail@customer.kz',
    'pg_user_ip' => '127.0.0.1',
    'pg_postpone_payment' => '0',
    'pg_language' => 'ru',
    'pg_testing_mode' => '1',
    'pg_user_id' => '1',
    'pg_recurring_start' => '1',
    'pg_recurring_lifetime' => '156',
    'pg_receipt_positions' => [
        [
        'count' => '1',
        'name' => 'product name',
        'tax_type' => '3',
        'price' => '900',
        ]
    ],
    'pg_user_id' => '1',
    'pg_param1' => 'additional data',
    'pg_param2' => 'additional data',
    'pg_param3' => 'additional data',
];

/**
 * The function turns a multidimensional array into a flat one
 */
function makeFlatParamsArray($arrParams, $parent_name = '')
{
    $arrFlatParams = [];
    $i = 0;
    foreach ($arrParams as $key => $val) {
        $i++;
        /**
        * Make the name like tag001subtag001
        * So that you can then sort normally and nested nodes do not get confused when sorting
        */
        $name = $parent_name . $key. sprintf('%03d', $i);
        if (is_array($val)) {
        $arrFlatParams = array_merge($arrFlatParams, makeFlatParamsArray($val, $name));
        continue;
        }
        $arrFlatParams += array($name => (string)$val);
    }

    return $arrFlatParams;
}

// Turn the request object into a flat array
$requestForSignature = makeFlatParamsArray($requestForSignature);

// Signature generation
ksort($requestForSignature); // Sort by key
array_unshift($requestForSignature, 'init_payment.php'); // Adding to the beginning of the script name
array_push($requestForSignature, $secret_key); // Adding the private key to the end

$request['pg_sig'] = md5(implode(';', $requestForSignature)); // Received signature
Request URL

POST https://api.freedompay.uz/init_payment.php

Request fields
Response parameters
Request for check_url of the store. Checking the ability to make a payment

An example of a negative response from a store
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment not allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Запрос
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Payment allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
To use this request, you should contact your manager
Before accepting money from the buyer on the account, the payment gate can call the merchant script Check URL using the Request Method.

Check URL on the merchant side must be public, without authorization.

FreedomPay sends information about the number and properties of the order and waits for a response. Failure to respond within the specified time is considered as a refusal to pay.

The Check URL script is called only if this option was enabled in the merchant settings.
Merchant response to check_url

If Check URL is empty at the moment of payment initialization or is not specified at the moment of payment initialization, and is set to empty in the merchant settings, then the step of checking the ability to make a payment is skipped and it is considered that the merchant agrees to accept the payment.

  • If the merchant confirms the readiness of the order and the correctness of the amount, he must respond in the form of XML with the status ok.
  • In case of refusal to pay rejected.
  • error - error in data interpretation.
Request URL

POST {{check_url}}

Request fields

Request for result_url of the store. Payment result

Example of a positive store response
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Order paid</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
An example of a negative response from a store
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=0' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment cancelled</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
After receiving a payment from a client or if it is impossible to make a payment, FreedomPay calls the Result URL of the store and sends information about the payment result to it using the Request Method method.

Upon receipt of this request, the merchant must take the necessary actions to transfer the goods or services to the buyer, if the payment was successful. If pg_can_reject is equal to 1 and the merchant cannot accept the payment (for example, the ticket reservation has expired), it must respond with a rejected status, and FreedomPay will reject the payment. In this case, the pg_description field from the merchant response is shown to the user as the reason for the refusal.

Result URL on the merchant side must be public, without authorization.

If the merchant's server is not available at the time the Result URL is called, or if the response from the server was not 200, FreedomPay will make repeated attempts to call it every half an hour for 2 hours, even if the pg_lifetime account expires.

If the first attempt to call Result URL is unsuccessful, then the payment is not canceled, and in subsequent calls Result URL does not allow the merchant to refuse the payment.

The store must be prepared for the Result URL to be called repeatedly for the same payment. Retry responses must match the original response, even if the pg_lifetime transaction has expired.

Merchant response to result_url

The rejected status can be returned by the merchant only if the pg_can_reject parameter equal to 1 was specified in the incoming request from the gate, otherwise, regardless of the merchant's response, the payment will be considered completed. If the merchant refused to pay (replied rejected), the buyer is redirected to Failure URL, otherwise to Success URL.

  • ok - payment accepted
  • rejected - payment refusal if pg_can_reject is equal to 1
  • error - error in data interpretation
Request URL

POST {{result_url}}

Request fields
Return of the buyer to the merchant's website

After completing the payment in the online payment system, the buyer is redirected to the merchant page Success URL or Failure URL, depending on the result of the payment. Redirection occurs using the Success URL Method or Failure URL Method specified during payment initialization.

If at GET request Success URL or Failure URL already contain parameters in query string, then additional parameters pg_order_id, pg_payment_id and custom variables of the merchant are appended to the end of query string. The merchant must ensure that the names of additional parameters do not match the names of existing parameters.

The difference between Result URL and Success URL must be clearly understood.

Result URL is called directly from the FreedomPay server, while Success URL is called by the user's browser when FreedomPay.mone redirects the user back to the store site. It is wrong to use Success URL as the only way to find out about the completion of the payment, because the user may for various reasons (for example, when the connection is broken) not to reach the Success URL after the payment. The most reliable way to find out about the completion of the payment is to implement a Result URL, which FreedomPay undertakes to call again every half an hour within 2 hours after the payment, if the first attempt for any reason failed.

Request URL

POST {{success_url}}

Request fields


Payment widget
To use this type of payment creation, you should contact your manager.

Checkout (pop-up payment form) allows you to create a payment on the page of your site using a token that your personal manager can provide you. Payment is made through a pop-up window that is called when the buyer clicks on the button

Payment scenario
  1. The buyer places an order on your website
  2. The buyer clicks on the button to buy the product
  3. Your site initializes the checkout
  4. FreedomPay calls a pop-up window where the payment process takes place
  5. In case of successful payment or error, your site receives a notification
Checkout connection
To use the checkout on their website, the merchant must include the following script:

  <script>
    (function (p, a, y, b, o, x) {
        o = p.createElement(a);
        x = p.getElementsByTagName(a)[0];
        o.async=1;
        o.src = 'https://cdn.freedompay.uz/widget/pbwidget.js?' + 1 * new Date();
        x.parentNode.insertBefore(o, x);
    })(document, 'script');
  </script>
Next, when you click on the payment button, call the payment creation method. Minimum configuration:
 function pay(amount) {
        var data = {
            token: Your token,
            payment: {
                amount: amount
                language: 'ru', // Widget language
                description: 'Order description',
            },
            successCallback: function (payment) {
                console.log(payment) // Payment details
            },
            errorCallback: function (payment) {
                console.log(payment) // Payment details
            }
        }

        var widget = new PayBox(data);
        widget.create();
    }
<button onclick="pay(100)">Pay</button>
Full configuration:
function pay(amount) {
    var data = {
      token: "your token",
      payment: {
        order: "1",
        amount: "200",
        currency: "KZT",
        description: "Description of the order",
        expires_at: "2020-12-12 00:00:00",
        param1: "string",
        param2: "string",
        param3: "string",
        test: 1, // testing mode
        options: {
          callbacks: {
            result_url: "https://my-domain.com/result",
            check_url: "https://my-domain.com/check"
          },
          custom_params: {},
          user: {
            email: "user@test.com",
            phone: "77777777777",
          },
          receipt_positions: [
            {
              count: 2,
              name: "Mouse pad",
              tax_type: 3,
              price: 1000
            },
            {
              count: 2,
              name: "Socket",
              tax_type: 3,
              price: 1000
            }
          ]
        }
      },
      successCallback: function (payment) {
          //...
      },
      errorCallback: function (payment) {
          //...
      }
    }

    var widget = new PayBox(data);
    widget.create();
  }
Get payment status. After the buyer pays, your site receives a notification via callbacks, which are passed in the parameters:
successCallback: function (payment) {
      // upon successful payment
      alert('Order number ' + payment.order + ' paid successfully')
  },
  errorCallback: function (payment) {
      // in case of unsuccessful payment
      alert('An error occurred while trying to pay for order number ' + payment.order)
  }
Request for check_url of the store. Checking the ability to make a payment

An example of a negative response from a store
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment not allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Payment allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
To use this request, you must contact your manager.

Before accepting money from the buyer on the account, the payment gate can call the merchant script Check URL using the Request Method.

FreedomPay transmits information about the number, order properties and waits for a response. Failure to respond within the specified time is considered as a refusal to pay.

The Check URL script is called only if this option was enabled in the merchant settings.
Merchant response to check_url

If Check URL is empty at the time of payment initialization or not specified at the time of payment initialization, and set to empty in the merchant settings, then the payment possibility check step is skipped and it is considered that the merchant agrees to accept the payment.

  • If the store confirms that the order is ready and the amount is correct, it must respond in the form of XML with the status ok.
  • In case of refusal to pay rejected.
  • error - error in data interpretation.
Request URL

POST {{check_url}}

Request fields
Request for result_url of the store. Payment result

Request for result url comes with POST method, with Content-type: application/json header and request body Result URL on the merchant side must be public, without authorization.
{
    "id": 12345,
    status: {
        "code": "success"
    },
    "order": 1234,
    "amount": "100.00",
    "refund_amount": "0.00",
    "currency": "KZT",
    "description": "Order description",
    "payment_system": "EPAYWEBKZT",
    "expires_at": "2022-01-18T05:58:58Z",
    "created_at": "2022-01-17T11:58:58Z",
    "updated_at": "2022-01-17T11:59:07Z",
    "param1": null
    "param2": null
    "param3": null
    "options": {
        "callbacks": {
            "result_url": "",
            "check_url": ""
        },
        "user": {
            "email": "widget@freedompay.uz",
            "phone": "77"
        },
        "receipt_positions": null
    },
    "salt": "EitR7ZYZvhpioeCU",
    "sig": "05e72b0137c52c1e941c627f42cb1f39"
}

The merchant must respond to the request with the following text:
{"status": "ok"}
Any amount method
If you want the payer to enter the payment amount himself, you must use this method.

When making a payment, the payer first gets to the form where he enters the amount of the payment. Then it is redirected to the payment page where the payment takes place.

Payment initialization
Payment initialization
Request
curl --location --request POST 'https://api.freedompay.uz/any_amount.php' \
--form 'pg_order_id=23' \
--form 'pg_merchant_id={{paybox_merchant_id}}' \
--form 'pg_amount=25' \
--form 'pg_description=test' \
--form 'pg_salt=molbulak' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=mobile_commerce'
# Signature example:
'any_amount.php;25;test;{{paybox_merchant_id}};23;KZT;molbulak;{{secret_key}}'

Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_payment_id>4567788</pg_payment_id>
    <pg_redirect_url>https://api.freedompay.uz/any_amount?customer=498333170d6a895148c57c53ffb18287</pg_redirect_url>
    <pg_redirect_url_type>need data</pg_redirect_url_type>
    <pg_salt>bdwLavL9lg6It91b</pg_salt>
    <pg_sig>709633e91387c56ac6fb7cb33d1e07d8</pg_sig>
</response>
When sending data directly from the merchant to FreedomPay, the merchant must send data to any_amount.php.

You can pass arbitrary additional parameters whose names do not start with pg_. All these parameters will be passed to pg_check_url and pg_result_url.

The names of additional merchant parameters must be unique.

After receiving the pg_redirect_url parameter, the user is redirected to the payment page where the payer completes the payment.

If successful, the user will be redirected to the payment page.

If the merchant did not provide all the parameters necessary to create a payment transaction (payment system, user phone number and parameters required for the selected payment system),
they are requested from the user on the freedompay.uz site.

Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};

$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_amount' => 10,
    'pg_salt' => 'some random string',
    'pg_order_id'=> '00102',
    'pg_description' => 'Ticket',
    'pg_result_url' => 'http://site.kz/result'
];

// $request['pg_testing_mode'] = 1; //add this parameter to request for testing payments

//if you pass any of your parameters, which you want to get back after the payment, then add them. For example:
// $request['client_name'] = 'My Name';
// $request['client_address'] = 'Earth Planet';

//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'any_amount.php');
array_push($request, $secret_key);

$request['pg_sig'] = md5(implode(';', $request)); // signature

unset($request[0], $request[1]);
Request URL

POST https://api.freedompay.uz/any_amount.php

Request fields
Response parameters
Request for check_url of the store. Checking the ability to make a payment.

An example of a negative response from a store
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment not allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Payment allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
To use this request, you should contact your manager.

Before accepting money from the buyer on the account, the payment gate can call the merchant script Check URL using the Request Method.

FreedomPay transmits information about the number, order properties and waits for a response.
Failure to respond within the specified time is considered as a refusal to pay.

Check URL on the merchant side must be public, without authorization.

The Check URL script is called only if this option was enabled in the merchant settings.

Merchant response to check_url

If Check URL is empty at the time of payment initialization or not specified at the time of payment initialization, and set to empty in the merchant settings, then the payment possibility check step is skipped and it is considered that the merchant agrees to accept the payment.

  • If the store confirms the readiness of the order and the correct amount, it must respond in the form XML with status ok.
  • In case of refusal to pay rejected.
  • error - error in data interpretation.
Request URL

POST {{check_url}}

Request fields
Request for result_url of the store. Payment result
An example of a negative response from a store
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=0' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment cancelled</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Order paid</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
After receiving a payment from a client or if it is impossible to make a payment, FreedomPay calls the Result URL of the store and sends information about the payment result to it using the Request Method method.

Upon receipt of this request, the merchant must take the necessary actions to transfer the goods or services to the buyer, if the payment was successful. If pg_can_reject is equal to 1 and the merchant cannot accept the payment (for example, the ticket reservation has expired), it must respond with a rejected status, and FreedomPay will reject the payment. In this case, the pg_description field from the merchant response is shown to the user as the reason for the refusal.

Result URL on the merchant side must be public, without a authorization.

If the merchant's server is not available at the time the Result URL is called, or if the response from the server was not 200, FreedomPay will make repeated attempts to call it every half an hour for 2 hours, even if the pg_lifetime account expires.

If the first attempt to call Result URL is unsuccessful, then the payment is not canceled, and in subsequent calls Result URL does not allow the merchant to refuse the payment.

The store must be prepared for the Result URL to be called repeatedly for the same payment. Retry responses must match the original response, even if the pg_lifetime transaction has expired.
Merchant response to result_url

The rejected status can be returned by the merchant only if the pg_can_reject parameter equal to 1 was specified in the incoming request from the gate, otherwise, regardless of the merchant's response, the payment will be considered completed. If the merchant refused the payment (rejected answered), the buyer is redirected to Failure URL, otherwise - to Success URL.

  • ok - payment accepted
  • rejected - payment refusal if pg_can_reject is equal to 1
  • error - error in data interpretation
Request URL
POST {{result_url}}
Request fields

Return of the buyer to the merchant's website

After completing the payment in the online payment system, the buyer is redirected to the merchant page Success URL or Failure URL, depending on the result of the payment. Redirection occurs using the Success URL Method or Failure URL Method specified during payment initialization.

If at GET request Success URL or Failure URL already contain parameters in query string, then additional parameters pg_order_id, pg_payment_id and custom variables of the merchant are appended to the end of query string. The merchant must ensure that the names of additional parameters do not match the names of existing parameters.

The difference between Result URL and Success URL must be clearly understood.

Result URL is called directly from the FreedomPay server, while Success URL is called by the user's browser when FreedomPay redirects the user back to the store site. It is wrong to use Success URL as the only way to find out about the completion of the payment, because the user may for various reasons (for example, when the connection is broken) not to reach the Success URL after the payment. The most reliable way to find out about the completion of the payment is to implement a Result URL, which FreedomPay undertakes to call again every half an hour within 2 hours after the payment, if the first attempt for any reason failed.

Request URL

POST {{success_url}} or {{failure_url}}

Request fields
Saved card with cvc input

To use this request, contact your manager

This scenario involves the participation of the user in the payment process. User is redirected to FreedomPay to enter cvc and pass 3ds validation

In the case when the card on which the payment is made is confirmed, the cvc is not requested from the user

Approved cards are marked with the approved status

Card payment initialization
Payment with a saved card takes place in two stages:
  • Payment initialization
  • Carrying out payment
The following request is used to initialize the payment:

Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};
$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_amount' => 100,
    'pg_order_id' => 12345,
    'pg_user_id' => 1234,
    'pg_card_token' => 'ef741cfc-f85e-41a0-84e6-2ba964912182',
    'pg_description' => 'Payment description',
    'pg_salt' => 'some random string',
];
//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'init');
array_push($request, $secret_key);
$request['pg_sig'] = md5(implode(';', $request)); // signature
unset($request[0], $request[1]);

Request URL

POST https://api.freedompay.uz/v1/merchant/{{paybox_merchant_id}}/card/init

Request fields
Response parameters
Making a payment

To make a payment, you need to redirect the user to FreedomPay with a POST request

Redirecting the user with a POST request:
<html>
    <body>
        <form action="https://api.freedompay.uz/v1/merchant/{{paybox_merchant_id}}/card/pay" method="post" id="redirect-form">
            <input type="hidden" name="pg_merchant_id" value="{{paybox_merchant_id}}" />
            <input type="hidden" name="pg_payment_id" value="12345" />
            <input type="hidden" name="pg_salt" value="some random string" />
            <input type="hidden" name="pg_sig" value="{{paybox_signature}}" />
        </form>

        <script type="text/javascript">
            document.getElementById('redirect-form').submit();
        </script>
    </body>
</html>

Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};
$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_payment_id' => 12345,
    'pg_salt' => 'some random string',
];
//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'pay');
array_push($request, $secret_key);
$request['pg_sig'] = md5(implode(';', $request)); // signature
unset($request[0], $request[1]);

Request URL

POST https://api.freedompay.uz/v1/merchant/{{paybox_merchant_id}}/card/pay

Request fields
Request for result_url of the store. Payment result

An example of a negative response from a store
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=0' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment cancelled</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Order paid</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
After receiving payment from the client or if it is impossible to make a payment, FreedomPay calls the Result URL of the merchant and sends information about the payment result to it using the Request Method method.

Upon receipt of this request, the merchant must take the necessary actions to transfer the goods or services to the buyer, if the payment was successful. If pg_can_reject is equal to 1 and the merchant cannot accept the payment (for example, the ticket reservation has expired), it must respond with a rejected status, and FreedomPay will reject the payment. In this case, the pg_description field from the merchant response is shown to the user as the reason for the refusal.

Result URL on the merchant side must be public, without authorization.

If the merchant's server is unavailable at the time the Result URL is called, or if the response from the server was 500, FreedomPay will make repeated attempts to call it every half an hour for 2 hours, even if the pg_lifetime account expires.

If the first attempt to call Result URL is not successful, then the payment is not canceled, and in subsequent calls Result URL does not allow the merchant to refuse the payment.

The merchant must be prepared for the fact that the Result URL will be called repeatedly for the same payment. Retry responses must match the original response, even if the pg_lifetime transaction has expired.

Merchant response to result_url

The rejected status can be returned by the merchant only if the pg_can_reject parameter equal to 1 was specified in the incoming request from the gate, otherwise, regardless of the merchant's response, the payment will be considered completed. If the merchant refused the payment (rejected answered), the buyer is redirected to Failure URL, otherwise - to Success URL.

  • ok - payment accepted
  • rejected - payment refusal if pg_can_reject is equal to 1
  • error - error in data interpretation
Request URL

POST {{result_url}}

Request fields
Non-acceptance payments
To use this request, contact your manager

Card payment initialization

Payment with a saved card takes place in two stages:
  • Payment initialization
  • Carrying out payment
The following request is used to initialize the payment:
Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};
$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_amount' => 100,
    'pg_order_id' => 12345,
    'pg_user_id' => 1234,
    'pg_card_token' => 'ef741cfc-f85e-41a0-84e6-2ba964912182',
    'pg_description' => 'Payment description',
    'pg_salt' => 'some random string',
];
//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'init');
array_push($request, $secret_key);
$request['pg_sig'] = md5(implode(';', $request)); // signature
unset($request[0], $request[1]);

Request URL

POST https://api.freedompay.uz/v1/merchant/{{paybox_merchant_id}}/card/init

Request fields
Response parameters
Making a payment
Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};
$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_payment_id' => 12345,
    'pg_salt' => 'some random string',
];
//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'direct');
array_push($request, $secret_key);
$request['pg_sig'] = md5(implode(';', $request)); // signature
unset($request[0], $request[1]);

Request URL

POST https://api.freedompay.uz/v1/merchant/{{paybox_merchant_id}}/card/direct

Request fields
Response parameters
Request for result_url of the store. Payment result

An example of a negative response from a store
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=0' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment cancelled</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
Example of a positive store response
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=500' \
--form 'pg_currency=KZT' \
--form 'pg_net_amount=482.5' \
--form 'pg_ps_amount=500' \
--form 'pg_ps_full_amount=500' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Order paid</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
After receiving payment from the client or if it is impossible to make a payment, FreedomPay calls the Result URL of the merchant and sends information about the payment result to it using the Request Method method.

Upon receipt of this request, the merchant must take the necessary actions to transfer the goods or services to the buyer, if the payment was successful. If pg_can_reject is equal to 1 and the merchant cannot accept the payment (for example, the ticket reservation has expired), it must respond with a rejected status, and FreedomPay will reject the payment. In this case, the pg_description field from the merchant response is shown to the user as the reason for the refusal.

Result URL on the merchant side must be public, without authorization.

If the merchant's server is unavailable at the time the Result URL is called, or if the response from the server was 500, FreedomPay will make repeated attempts to call it every half an hour for 2 hours, even if the pg_lifetime account expires.

If the first attempt to call Result URL is not successful, then the payment is not canceled, and in subsequent calls Result URL does not allow the merchant to refuse the payment.

The merchant must be prepared for the fact that the Result URL will be called repeatedly for the same payment. Retry responses must match the original response, even if the pg_lifetime transaction has expired.

Merchant response to result_url

The rejected status can be returned by the merchant only if the pg_can_reject parameter equal to 1 was specified in the incoming request from the gate, otherwise, regardless of the merchant's response, the payment will be considered completed. If the merchant refused the payment (rejected answered), the buyer is redirected to Failure URL, otherwise - to Success URL.

  • ok - payment accepted
  • rejected - payment refusal if pg_can_reject is equal to 1
  • error - error in data interpretation
Request URL

POST {{result_url}}

Request fields
Mobile balance
FreedomPay offers the possibility to pay for an order/service from the mobile phone balance, if the payer's mobile operator supports this possibility tenderness. Available mobile operators:

Tele2
Altel
Beeline
Activ
Kcell

To make test payments, we recommend that you familiarize yourself with [test phone numbers] (#testovye_nomera_telefonov)

Payment initialization
Payment initialization
Request
curl --location --request POST 'https://api.freedompay.uz/init_payment.php' \
--form 'pg_order_id=23' \
--form 'pg_merchant_id={{paybox_merchant_id}}' \
--form 'pg_amount=25' \
--form 'pg_description=test' \
--form 'pg_salt=molbulak' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=mobile_commerce'
# Signature example:
'init_payment.php;25;test;{{paybox_merchant_id}};23;KZT;molbulak;{{secret_key}}'

Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_payment_id>4567788</pg_payment_id>
    <pg_redirect_url>https://api.freedompay.uz/pay.html?customer=498333170d6a895148c57c53ffb18287</pg_redirect_url>
    <pg_redirect_url_type>need data</pg_redirect_url_type>
    <pg_salt>bdwLavL9lg6It91b</pg_salt>
    <pg_sig>709633e91387c56ac6fb7cb33d1e07d8</pg_sig>
</response>
When sending data directly from the merchant to FreedomPay, the merchant must send data to init_payment.php.

You can pass arbitrary additional parameters whose names do not start with pg_. All these parameters will be passed to pg_check_url and pg_result_url.

The names of additional merchant parameters must be unique.

After receiving the pg_redirect_url parameter, the user is redirected to the payment page where the payer completes the payment.

If successful, the user will be redirected to the payment page.

If the merchant did not provide all the parameters necessary to create a payment transaction (payment system, user phone number and parameters required for the selected payment system), they are requested from the user on the freedompay.uz site.

Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};

$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_amount' => 10,
    'pg_salt' => 'some random string',
    'pg_order_id'=> '00102',
    'pg_description' => 'Ticket',
    'pg_result_url' => 'http://site.kz/result'
];

// $request['pg_testing_mode'] = 1; //add this parameter to request for testing payments

//if you pass any of your parameters, which you want to get back after the payment, then add them. For example:
// $request['client_name'] = 'My Name';
// $request['client_address'] = 'Earth Planet';

//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'init_payment.php');
array_push($request, $secret_key);

$request['pg_sig'] = md5(implode(';', $request)); // signature

unset($request[0], $request[1]);
Request URL

POST https://api.freedompay.uz/init_payment.php

Request fields
Response parameters
Mobile payment

Payment in most cases passes OTP verification. Those. confirmation is required to make a payment. But by special agreement, it is possible to disable OTP verification.
Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};
$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_payment_id' => 12345,
    'pg_subscriber_phone' => 77077777777,
    'pg_payment_system_code' => 'ALTELKZT',
    'pg_salt' => 'some random string',
];
//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'pay');
array_push($request, $secret_key);
$request['pg_sig'] = md5(implode(';', $request)); // signature
unset($request[0], $request[1]);

If in response pg_status equals need_approve FreedomPay will send an SMS message to the number specified in pg_abonent_phone with an OTP code. To continue, the merchant needs to request this code from the payer.

Request URL

POST https://api.freedompay.uz/mfs/pay

Request fields

Response parameters
Payment confirmation

To confirm the payment, the following request is sent:

Signature generation:

$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};
$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_payment_id' => 12345,
    'pg_approval_code' => '077587',
    'pg_salt' => 'some random string',
];
//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'approve');
array_push($request, $secret_key);
$request['pg_sig'] = md5(implode(';', $request)); // signature
unset($request[0], $request[1]);

Request URL
POST https://api.freedompay.uz/mfs/approve

Response parameters
Request to resend SMS code

Merchant can once again request to resend the SMS code.
Signature generation:
$pg_merchant_id = {{paybox_merchant_id}};
$secret_key = {{paybox_merchant_secret}};

$request = [
    'pg_merchant_id'=> $pg_merchant_id,
    'pg_payment_id' => 12345,
    'pg_subscriber_phone' => 77077777777,
    'pg_salt' => 'some random string',
];

//generate a signature and add it to the array
ksort($request); // sort alphabetically
array_unshift($request, 'resend_otp');
array_push($request, $secret_key);

$request['pg_sig'] = md5(implode(';', $request)); // signature

unset($request[0], $request[1]);
Request URL

POST https://api.freedompay.uz/mfs/resend_otp

Request fields
Request for check_url of the store. Checking the ability to make a payment.

Example of a positive store response
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Payment allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
An example of a negative response from a store
Request
curl --location --request POST '{{check_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_amount=10' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_ps_amount=5' \
--form 'pg_ps_full_amount=5' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment not allowed</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
To use this request, you should contact your manager

Before accepting money from the buyer on the account, the payment gate can call the merchant script Check URL using the Request Method.

Check URL on the merchant side must be public, without authorization.

FreedomPay sends information about the number and properties of the order and waits for a response. Failure to respond within the specified time is considered as a refusal to pay.

The Check URL script is called only if this option was enabled in the merchant settings.

Merchant response to check_url

If Check URL is empty at the moment of payment initialization or not specified at the moment of payment initialization, and is set to empty in the merchant settings, then the step of checking the ability to make a payment is skipped and it is considered that the merchant agrees to accept the payment.

  • If the merchant confirms the readiness of the order and the correctness of the amount, he must respond in the form of XML with the status ok.
  • In case of refusal to pay rejected.
  • error - error in data interpretation.
Request URL

POST {{check_url}}

Request fields
Request for result_url of the store. Payment result

Example of a positive store response
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>ok</pg_status>
    <pg_description>Order paid</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
An example of a negative response from a store
Request
curl --location --request POST '{{result_url}}' \
--form 'pg_order_id=123456789' \
--form 'pg_payment_id=12345' \
--form 'pg_currency=KZT' \
--form 'pg_ps_currency=KZT' \
--form 'pg_description=Purchase in the online store Site.kz' \
--form 'pg_result=1' \
--form 'pg_payment_date=2019-01-01 12:00:00' \
--form 'pg_can_reject=1' \
--form 'pg_user_phone=7077777777777' \
--form 'pg_user_contact_email=mail@customer.kz' \
--form 'pg_need_email_notification=1' \
--form 'pg_testing_mode=1' \
--form 'pg_captured=0' \
--form 'pg_card_pan=5483-18XX-XXXX-0293' \
--form 'Merchant parameters=' \
--form 'pg_salt=some random string' \
--form 'pg_sig={{paybox_signature}}' \
--form 'pg_payment_method=bankcard'
Reply
<?xml version="1.0" encoding="utf-8"?>
<response>
    <pg_status>rejected</pg_status>
    <pg_description>Payment cancelled</pg_description>
    <pg_salt>random string</pg_salt>
    <pg_sig>ksdjrimzjedkljsujjemnjsuj</pg_sig>
</response>
After receiving a payment from a client or if it is impossible to make a payment, FreedomPay calls the Result URL of the store and sends information about the payment result to it using the Request Method method.

Upon receipt of this request, the merchant must take the necessary actions to transfer the goods or services to the buyer, if the payment was successful. If pg_can_reject is equal to 1 and the merchant cannot accept the payment (for example, the ticket reservation has expired), it must respond with a rejected status, and FreedomPay will reject the payment. In this case, the pg_description field from the merchant response is shown to the user as the reason for the refusal.

Result URL on the merchant side must be public, without authorization.

If the merchant's server is not available at the time the Result URL is called, or if the response from the server was not 200, FreedomPay will make repeated attempts to call it every half an hour for 2 hours, even if the pg_lifetime account expires.

If the first attempt to call Result URL is unsuccessful, then the payment is not canceled, and in subsequent calls Result URL does not allow the merchant to refuse the payment.

The store must be prepared for the Result URL to be called repeatedly for the same payment. Retry responses must match the original response, even if the pg_lifetime transaction has expired.

Merchant response to result_url

The rejected status can be returned by the merchant only if the pg_can_reject parameter equal to 1 was specified in the incoming request from the gate, otherwise, regardless of the merchant's response, the payment will be considered completed. If the merchant refused the payment (rejected answered), the buyer is redirected to Failure URL, otherwise - to Success URL.

  • ok - payment accepted
  • rejected - payment refusal if pg_can_reject is 1
  • error - error in data interpretation
Request URL
POST {{result_url}}
Request fields