Introduction
Business API - a solution specifically designed for internet businesses in need of multicurrency payment processing. We support all major currencies and multiple payment methods.
Credentials
The credentials contain:
- merchant_private_key
- api_url
- api_status_url
- api_balance_url
We also provide a username, password and url for your private office.
Environments
There are two environments available for integration:
- Sandbox environment
- Production environment
The base API URL for the environments is provided along with the credentials (api_url).
Sandbox Environment
Sandbox provides full functionality but it only emulates processing, no actual bank transactions are made. You can use the following PAN for tests:
- APPROVED: ANY VALID CARD NUMBER
- DECLINED: 4626233193837898
- PENDING: 2222420000001113
You can use any cardholder name, expiry date and CVV2/CVC2 with these PANs. 3-D Secure is also emulated with a page that doesn’t require any password but only shows you 2 buttons. One button is for successful authentication, another is for failed authentication. Note, that when you chose to fail authentication, order is always declined, no matter what PAN was used.
Production Environment
Once you complete integration with Sandbox environment you will be provided with Production credentials. These are completely different credentials, not related with the ones on Sandbox. Production always makes real bank transactions, cards from Sandbox are not supported on this environment.
Authentication example
curl "[api_url]/api/v1/init/pay" \
-H "Authorization: Bearer merchant_private_key"
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_HTTPHEADER => array(
"authorization: Bearer merchant_private_key",
),
));
import http.client
conn = http.client.HTTPSConnection("...")
headers = {
'authorization': "Bearer merchant_private_key",
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("[api_url]/api/v1/payouts")
...
.addHeader("content-type", "application/json")
.addHeader("authorization", "Bearer merchant_private_key")
.build();
Response response = client.newCall(request).execute();
Authenticate your account when using the API by including your API secret key that was provided with the credentials. Your API keys carry importance and privileges, be sure to store them securely. Please do not share your secret API keys in publicly accessible areas such GitHub and client-side code areas.
Authentication to the API is performed via bearer auth keys (for cross-origin requests), use -H “Authorization: Bearer merchant_private_key”.
All API requests must be made through HTTPS. Calls made through plain HTTP will fail. API requests without authentication will also fail.
Total flow
- 1. Initialization, see create
- 2. Use the response received in the first step.
- If you need host to host integration, then make a POST request without parameters from host_to_host_url to the method you need, for example, in method_1_url.
- If you want to give the payer a choice of payment method on the payment page, redirect to payment_page_url -> total, for example payment_page_total_url. You can also place this link in a frame on your site.
- If you need the payment page of the method you need, then redirect to payment_page_url -> methods, for example method_1_url.
- 3. Final, only host to host
5XX Errors
This is the category of server errors. It includes error 502 bad gateway, 504 gateway time-out and error 508, as well as error 500.
Attention!!!
Don't send repeated requests to create payments or payouts, causing several transactions with the same request parameters may be created. Therefore, contact the support service and check if the transaction was created according to your previous request? If not, then try again.
Timeout Error
Attention!!!
If our server does not respond for a long time or the connection is broken, you need to wait for a callback or poll the status of the transaction, if either did not work, then contact the support.
Please, don't send repeated requests to create payments or payouts, causing several transactions with the same request parameters may be created. Also don't assign statuses to transactions until you have received these statuses from our server or from our technical support.
Payments
Payment processing REST API.
Create
curl "[api_url]/api/v1/payments" \
-X POST \
-H "Authorization: Bearer merchant_private_key" \
-H "Content-Type: application/json" -d '{
"product" : "Your Product",
"amount" : "1000",
"currency" : "CNY",
"redirectSuccessUrl" : "https://your-site.com/success",
"redirectFailUrl" : "https://your-site.com/fail",
"extraReturnParam" : "your order id or other info",
"orderNumber" : "your order number",
"locale": "zh"
}'
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "[api_url]/api/v1/payments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{ \"product\" : \"Your Product\", \"amount\" : "10000", \"currency\" : \"CNY\", \"redirectSuccessUrl\" : \"https://your-site.com/success\", \"redirectFailUrl\" : \"https://your-site.com/fail\", \"extraReturnParam\" : \"your order id or other info\", \"orderNumber\" : \"your order number\", \"locale\" : \"zh\"\n}",
CURLOPT_HTTPHEADER => array(
"authorization: Bearer merchant_private_key",
"content-type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
from django.http import HttpResponseRedirect, HttpResponse
import requests
import json
def pay(request) :
MERCHANT_PRIVATE_KEY = 'merchant_private_key'
SANDBOX_URL = '[api_url]'
payload = {
"product" : request.POST['product_name'],
"amount" : request.POST['order_amount'],
"currency" : "CNY",
"redirectSuccessUrl": request.POST['notify_url'],
"redirectFailUrl" : request.POST['return_url'],
"extraReturnParam" : request.POST['order_no'],
"orderNumber" : request.POST['order_number'],
"locale" : request.POST['locale']
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer %s' % (MERCHANT_PRIVATE_KEY)
}
resp = requests.post('%s/api/v1/payments' % (SANDBOX_URL), json=payload, headers=headers)
if resp.status_code == 200:
resp_payload = json.loads(resp.text)
return HttpResponseRedirect(resp_payload['processingUrl'])
else:
return HttpResponse('<html><body><span>Something gone wrong: %s</span></body></html>' % (resp.status_code))
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("product", "Example Payment");
params.put("amount", "1000");
params.put("currency", "EUR");
params.put("redirectSuccessUrl", "[sucess redirect url]");
params.put("redirectFailUrl", "[fail redirect url]");
params.put("orderNumber", "[merchat system order number]");
params.put("extraReturnParam", "[some additional params]");
params.put("locale", "[user locale]");
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("[api_url]/api/v1/payments")
.post(RequestBody.create(JSON, new Gson().toJson(params)))
.addHeader("content-type", "application/json")
.addHeader("authorization", "Bearer merchant_private_key")
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("response ", "onFailure(): " + e.getMessage() );
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String resp = response.body().string();
Log.e("response ", "onResponse(): " + resp );
}
});
Return status 200 and JSON:
Response
{
"success": true,
"token": "[token]",
"host_to_host_url": {
"method_1": "[method_1_url]",
"method_2": "[method_2_url]",
"method_3": "[method_3_url]",
},
"payment_page_url": {
"total": "[payment_page_total_url]",
"methods": {
"method_1": "[method_1_url]",
"method_2": "[method_2_url]",
"method_3": "[method_3_url]",
}
}
}
Initialize payments - to begin receiving payments, you must first call using the following script. This will enable you to obtain a payment token and required URLs, which will be required later to complete API integration.
HTTP Request via SSL
POST '/api/v1/init/pay'
Query Parameters
| Parameter | Mandatory | Description | Validation |
|---|---|---|---|
| product | yes | Product name (Service description) (example: 'iPhone'). | minLength: 5, maxLength: 255 |
| amount | yes | Payment amount in cents (10020), except JPY and VND | minLength: 1, maxLength: 32 |
| currency | yes | Currency code (CNY, EUR, USD, JPY). | minLength: 3, maxLength: 3 |
| callbackUrl | yes | The server URL a merchant will be notified about a payment finalisation | Valid URI format |
| redirectSuccessUrl | yes | The URL a customer will be redirected to in the case of successfull payment | Valid URI format |
| redirectFailUrl | yes | The URL a customer will be redirected to in the case of payment error or failure | Valid URI format |
| extraReturnParam | no | Any additional merchant parameters that will return with the callback | minLength: 1, maxLength: 1024 |
| orderNumber | no | The current order number from a company system. | minLength: 3, maxLength: 255 (string) |
| locale | no | The locale is used on a payment page by default. Currently supported locales: en, zh and jp from ISO 639-1. | minLength: 2, maxLength: 5 (string) |
| card | no | Card object for Host2Host payments. | |
| customer | no | Customer object for Host2Host payments. |
Card Object Parameters
| Parameter | Mandatory | Description | Validation |
|---|---|---|---|
| pan | yes | Customer’s card number (PAN). Any valid card number, may contain spaces | Valid card number (16-19 digits) |
| expires | yes | Customer’s card expiration date. Format: mm/yyyy | mm/yyyy format |
| holder | yes | Customer’s cardholder name. Any valid cardholder name | minLength: 5, maxLength: 50 |
| cvv | yes | Customer’s CVV2 / CVC2 / CAV2 | minLength: 3, maxLength: 3 Only digits (\d+) |
Customer Object Parameters (optional)
| Parameter | Mandatory | Description | Validation |
|---|---|---|---|
| yes | Customer’s email, is mandatory if Customer object posted on a request | Valid email format | |
| address | no | Customer's billing address | minLength: 5, maxLength: 55 |
| ip | no | Customer IP address | Valid IP address format (XX.XX.XX.XX) |
Host to host confirmation
Use the response received in the first step
Make a POST request without parameters from host_to_host_url to the method you need, for example, in method_1_url
POST [method_1_url]
curl [method_1_url] \
-H Authorization: Bearer [merchant_private_key]
Return status 200 and JSON:
Response_h2h
{
"success": true,
"token": "token",
"processingUrl": "processing_url",
"payment": {
"amount": 3000,
"gateway_amount": 3000,
"status": "pending",
"currency": "RUB"
},
"redirect_request": {
"type": "post",
"url": "url",
"params": {
"PaReq": "TEST_PAREQ_SUCCESS",
"TermUrl": "TermUrl",
"MD": "MD"
}
}
}
Host to host final
Use the response received in the second step
Redirect to processing_url
Payment page
Use the response received in the first step.
Frame
If you want to give the payer a choice of payment method on the payment page, redirect to payment_page_url -> total, for example payment_page_total_url. You can also place this link in a frame on your site.
Payment page for method
If you need the payment page of the method you need, then redirect to payment_page_url -> methods, for example method_1_url.
Get
curl "[api_status_url]/api/v2/merchant/payment/[payment_token]" \
-H "Authorization: Bearer merchant_private_key"
Return status 200 and JSON:
{
"success": true | false,
"errors": [],
"status": 200,
"payment": {
"id": 2599,
"status": "pending | approved | declined",
"token": "[payment token]",
"currency": "[payment currency]",
"product": "[product description]",
"callback_url": "[callback/notification url]",
"redirect_success_url": "success redirection url",
"redirect_fail_url": "fail redirection url",
"amount": 0,
"created_at": "[creation date]",
"updated_at": "[last status update date]",
"extra_return_param": "[extra params, can be use to payment identification in merchat system]",
"operation_type": "pay | payout",
"order_number": "[merchant's order number]"
}
}
Payment Get - this is the method used to retrieve information about single payment. Use it to clarify the status.
HTTP Request via SSL
GET '/api/v2/merchant/payment/[payment_token]'
api_status_url from credentials
Payouts
Transferring money from a business account to a client account.
Initialization payout
curl "[api_url]/api/v1/init/payout" \
-X POST \
-H "Authorization: Bearer merchant_private_key" \
-H "Content-Type: application/json" -d '{
"amount" : 1000,
"currency" : "CNY",
"orderNumber": "10001",
"callbackUrl": "[callback/notification url]",
"bankAccount": {
"accountHolder" : "John Snow",
"accountNumber" : "11111111111111111",
"bankCode" : "BOC"
},
"billing": {
"state" : "11",
"countryCode" : "CHN",
"city" : "1000"
}
}'
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "[api_url]/api/v1/init/payout",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{ \"amount\" : 1000, \"currency\" : \"CNY\", \"callbackUrl\": \"[callback/notification url]\", \"walletToken\": \"478230471238470\", \"billing\": { \"state\" : \"11\", \"countryCode\" : \"CHN\", \"city\" : \"1000\" }, \"bankAccount\": { \"accountHolder\" : \"John Snow\", \"accountNumber\" : \"11111111111111111\", \"bankCode\" : \"BOC\"}, \"orderNumber\" : \"10001\"\n}",
CURLOPT_HTTPHEADER => array(
"authorization: Bearer edf526c5374796cdcec5dce731405cee",
"content-type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound
from django.views.decorators.csrf import csrf_exempt
import requests
import json
def payout(request) :
MERCHANT_PRIVATE_KEY = 'your-merchant-private-key'
SANDBOX_URL = '[api_url]'
payload = {
"amount" : 10000,
"currency" : "EUR",
"orderNumber": "10001",
"callbackUrl": "[callback/notification url]",
"walletToken": "[client wallet token]",
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer %s' % (MERCHANT_PRIVATE_KEY)
}
resp = requests.post('%s/api/v1/payouts' % (SANDBOX_URL), json=payload, headers=headers)
if resp.status_code == 200:
resp_o = json.loads(resp.text)
return HttpResponseRedirect(resp_o['status'])
else:
return HttpResponse('<html><body><span>Something gone wrong: %s</span> : %s</body></html>' % (resp.status_code, resp.text))
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("amount", 1000);
params.put("currency", "EUR");
params.put("callbackUrl", "[callback/notification url]");
params.put("orderNumber", "[merchat system order number]");
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("[api_url]/api/v1/payouts")
.post(RequestBody.create(JSON, new Gson().toJson(params)))
.addHeader("content-type", "application/json")
.addHeader("authorization", "Bearer merchant_private_key")
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("response ", "onFailure(): " + e.getMessage() );
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String resp = response.body().string();
Log.e("response ", "onResponse(): " + resp );
}
});
Return status 200 and JSON:
Response_payout
{
"success": true,
"token": "[token]",
"host_to_host_url": {
"method_1": "[method_1_url]",
"method_2": "[method_2_url]",
"method_3": "[method_3_url]",
},
"payment_page_url": {
"total": "[payment_page_total_url]",
"methods": {
"method_1": "[method_1_url]",
"method_2": "[method_2_url]",
"method_3": "[method_3_url]",
}
}
}
Only host to host integration. Create a payout operation.
HTTP Request via SSL
POST 'api/v1/init/payout'
Query Parameters
| Parameter | Mandatory | Description |
|---|---|---|
| amount | yes | Payment amount in minimal values as of; USD and EUR / Cents, for JPY and VND / Yen, for CNY / Fen. |
| currency | yes | Currency code (CNY, EUR, USD, JPY) |
| orderNumber | yes | Client inner order number |
| callbackUrl | yes | The server URL a merchant will be notified about a payment finalisation |
| bankAccount | no | customer’s bank account information |
| billing | no | customer’s billing address information |
| card | no | Card object for Host2Host payouts. |
| customer | no | Customer object for Host2Host payouts. |
Query Parameters bankAccount attributes
| Parameter | Description |
|---|---|
| accountHolder | Customer’s account owner name |
| accountNumber | Customer’s account number |
| bankCode | Bank code from the dictionary |
Query Parameters billing attributes
| Parameter | Mandatory | Description |
|---|---|---|
| state | yes | Billing state or province code from the directory |
| countryCode | yes | ISO 3166-1 code of delivery country: 2 or 3 latin letters or numeric code |
| city | yes | Billing city code from the directory |
| zip | no | Billing postal code |
| street | no | Billing street address |
| phone | no | Valid customer phone number 20) |
Card Payout Object Parameters
| Parameter | Mandatory | Description |
|---|---|---|
| pan | yes | Customer’s card number (PAN). Any valid card number, may contain spaces |
| expires | yes | Customer’s card expiration date. Format: mm/yyyy |
Customer Object Parameters (optional)
| Parameter | Mandatory | Description |
|---|---|---|
| yes | Customer’s email, is mandatory if Customer object posted on a request | |
| address | no | Customer's billing address |
| ip | no | Customer IP address |
Confirmation
Use the response received in the first step
Make a POST request without parameters from host_to_host_url to the method you need, for example, in method_1_url
POST [method_1_url]
curl [method_1_url] \
-H Authorization: Bearer [merchant_private_key]
Return status 200 and JSON:
json { "success": true, "token": "token", "payment": { "amount": 3000, "gateway_amount": 3000, "status": "pending", "currency": "RUB" } }
Reports
Forming reports for your transactions history
Authorization
Authorization: Bearer [merchant_private_key]
Headers
Content-Type: application/json
Form report
Create report with specified parameters. Report will be generated in CSV format and will be available for download up to 5 mins (depends on size of a report). Response will contain [report_id], which can be used to check report status and download report file in get report method.
POST [api_url]/api/transactions/export
Body parameters
| Parameter | Mandatory | Description | Validation |
|---|---|---|---|
| from_date | yes | Start date of the report | Date format: YYYY-MM-DD |
| to_date | no | End date of the report | Date format: YYYY-MM-DD |
| status | no | Transaction status | Possible values: created, accepted, declined, returned, refunded |
| currency | no | Transaction currency | Possible values: USD, EUR etc. |
| order_number | no | Merchant's order number | String |
| token | no | Transaction token | String |
| type | no | Transaction type | Possible values: payin, payout, refund, chargeback |
| uid | no | Feed UUID | String |
| card_masked_number | no | Masked card number | String |
| sub_account | no | Sub account | String |
| decline_reason | no | Any words or symbols from decline reason text |
String |
Params
{
"from_date": "datetime",
"to_date": "datetime",
"status": "string",
"currency": "string",
"order_number": "string",
"token": "string",
"type": "string",
"uid": "string",
"card_masked_number": "string",
"sub_account": "string",
"decline_reason": "string"
}
Responses
Return status 202 and JSON:
{
"success": true,
"status": "pending",
"code": 202,
"report_id": "string"
}
Errors
Return status 422 and JSON:
{
"error_code": 422,
"success": false,
"message": "Date range should be less than 1 year"
}
Return status 429 and JSON:
{
"error_code": 429,
"success": false,
"message": "Too Many Requests. Try again in 1 minute"
}
Return status 415 and JSON:
{
"error_code": 415,
"success": false,
"message": "Unsupported Media Type, only `Content-Type: application/json` is supported"
}
Return status 500 and JSON:
{
"error_code": 500,
"success": false,
"message": "Server error"
}
Get report
Get formed report as link to zipped csv file.
get_report
GET [api_url]/api/transactions/export/[report_id]
Responses
Return status 200 and JSON:
{
"success": true,
"status": "success",
"code": 200,
"report_download_url": "url_string"
}
Return status 200 and JSON:
{
"success": true,
"status": "empty",
"code": 200,
"report_download_url": null
}
Return status 200 and JSON:
{
"success": true,
"status": "pending",
"code": 200,
"report_download_url": null
}
Errors
Return status 404 and JSON:
{
"error_code": 404,
"success": false,
"message": "Not Found"
}
Return status 415 and JSON:
{
"error_code": 415,
"success": false,
"message": "Unsupported Media Type, only `Content-Type: application/json` is supported"
}
Return status 500 and JSON:
{
"error_code": 500,
"success": false,
"message": "Server error"
}
Balance
Request current balance.
Receive Balance
curl "[api_balance_url]/api/v1/balance?currency=USD" \
-X GET \
-H "Authorization: Bearer merchant_private_key" \
-H "Content-Type: application/json"
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "[api_balance_url]/api/v1/balance?currency=USD",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"authorization: Bearer merchant_private_key",
"content-type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound
from django.views.decorators.csrf import csrf_exempt
import requests
import json
def balance(request) :
MERCHANT_PRIVATE_KEY = 'merchant_private_key'
SANDBOX_URL = '[api_url]'
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer %s' % (MERCHANT_PRIVATE_KEY)
}
resp = requests.get('%s/api/v1/balance' % (SANDBOX_URL), params = {'currency':'USD'}, headers=headers)
if resp.success:
resp_o = json.loads(resp.text)
return HttpResponse('<html><body><span>Your balance %s</body></html>' % (resp_o['wallet']['available']))
else:
return HttpResponse('<html><body><span>Something gone wrong: %s</span> : %s</body></html>' % (resp.status_code, resp.text))
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("[api_url]/api/v1/balance?currency=USD")
.get()
.addHeader("content-type", "application/json")
.addHeader("authorization", "Bearer merchant_private_key")
.build();
Response response = client.newCall(request).execute();
Return status 200 and JSON:
{
"success": true | false,
"errors": [],
"wallet": {
"available": 0,
"hold": 0,
"currency": "USD"
}
}
Receiving the balance for a business account.
Balance is returned as an object displaying available and pending amounts.
Balances shown may be not be released and/or processed.
HTTP Balance request via SSL
GET '/api/v1/balance'
Balance Query Parameters
| Parameter | Description |
|---|---|
| currency | Currency code (USD) |
The api_balance_url for the environments is provided along with the credentials.
Notifications
Callbacks
Notifications with the payment or payout status is sent to your callback URL using POST methods. Should payment or payout status change (pending/approved/declined) - notifications are sent accordingly.
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound
@csrf_exempt
def notifyme(request) :
req_o = json.loads(request.read());
return HttpResponse('Status is:%s' % (req_o['status']))
Params:
{
"token": "payment token",
"type": "payment type: pay | payout",
"status" : "payment status: pending | approved | declined ",
"extraReturnParam" : "extra params",
"orderNumber" : "merchant order number",
"sanitizedMask": "payer's sanitized card, if it was provided",
"amount": "payment amount in cents",
"currency": "payment currency",
"gatewayAmount": "exchanged amount in cents",
"gatewayCurrency": "exchanged currency"
}
Signature verification
$json = \json_decode((string) $request->getContent(), true, 512, JSON_THROW_ON_ERROR);
$actualSignature = $json['signature'];
unset($json['signature']);
$expected = json_encode($json, JSON_FORCE_OBJECT);
$expected = \str_replace('u003C', 'u003c', $expected);
$expected = \str_replace('u003E', 'u003e', $expected);
$expectedSignature = \hash_hmac('sha512', $expected, $config->getAuthKey(), false);
#the parameters look something like this (part of the data is changed or superfluous, so the signature
#in the example will not converge, just for an example of generation)
{:token=>"some_token", :type=>"pay", :status=>"declined", :extraReturnParam=>"_blank_", :orderNumber=>"Paycos01UZS161131499946", :walletDisplayName=>"", :amount=>5555500, :currency=>"UZS",
:gatewayAmount=>5555500, :gatewayCurrency=>"UZS", :gatewayDetails=>{"amount"=>"5555500", "product"=>"1 / 46", "currency"=>"UZS", "customer"=>{"ip"=>"172.0.0.1", "email"=>"wgreenholt@romaguera.net", "address"=>"27
63 Andrew Terrace Apt. 200\nNew Kayliberg, NY 46441", "zip_code"=>"77457-8346", "customer_name"=>"Bailey Powlowski", "identification_number"=>nil}, "platform"=>"web", "callback_url"=>"http://f09f0545ddbd.ngrok.io/
app_dev.php/pay/callback/", "order_number"=>"Paycos01UZS161131499946", "redirect_fail_url"=>"http://f09f0545ddbd.ngrok.io/app_dev.php/pay/fail/5dcd0b8e1d1a16866cd8983a94ab73e8530146560b229a7e731467901d1cd3f1/", "e
xtra_return_param"=>"_blank_", "redirect_success_url"=>"http://f09f0545ddbd.ngrok.io/app_dev.php/pay/success/5dcd0b8e1d1a16866cd8983a94ab73e8530146560b229a7e731467901d1cd3f1/"}, :declinationReason=>"gateway respon
se error: SomeDeclinationReason", :walletToken=>"some_token", :customer_ip=>"141.101.77.88"}
#convert them to json with the replacement of "\\u0026" by "&"
params.to_json.gsub("\\u0026", "&")
#we get a json string of this format:
"{\"token\":\"some_token\",\"type\":\"pay\",\"status\":\"declined\",\"extraReturnParam\":\"_blank_\",\"orderNumber\":\"Paycos01UZS161131499946\",\"walletDisplayName\":\"\",\"amount\":55555
00,\"currency\":\"UZS\",\"gatewayAmount\":5555500,\"gatewayCurrency\":\"UZS\",\"gatewayDetails\":{\"amount\":\"5555500\",\"product\":\"1 / 46\",\"currency\":\"UZS\",\"customer\":{\"ip\":\"172.0.0.1\",\"email\":\"w
greenholt@romaguera.net\",\"address\":\"2763 Andrew Terrace Apt. 200\\nNew Kayliberg, NY 46441\",\"zip_code\":\"77457-8346\",\"customer_name\":\"Bailey Powlowski\",\"identification_number\":null},\"platform\":\"we
b\",\"callback_url\":\"http://f09f0545ddbd.ngrok.io/app_dev.php/pay/callback/\",\"order_number\":\"Paycos01UZS161131499946\",\"redirect_fail_url\":\"http://f09f0545ddbd.ngrok.io/app_dev.php/pay/fail/5dcd0b8e1d1a16
866cd8983a94ab73e8530146560b229a7e731467901d1cd3f1/\",\"extra_return_param\":\"_blank_\",\"redirect_success_url\":\"http://f09f0545ddbd.ngrok.io/app_dev.php/pay/success/5dcd0b8e1d1a16866cd8983a94ab73e8530146560b22
9a7e731467901d1cd3f1/\"},\"declinationReason\":\"gateway response error: SomeDeclinationReason\",\"walletToken\":\"some_token\",\"customer_ip\":\"141.101.77.88\"}"
#next, we generate a signature from the string using the private key and this string
OpenSSL::HMAC.hexdigest('SHA512', payment.merchant_private_key, data)
#at the output we get 1 more line
"63dec72410d92aa0e8994904cf81706663886013fe1fd69a21fcb70bbd92de92639393343b38d8d5af9eb15c5fbcccf4ad51d61cf05e91146a6b5182224a47f9"
Dictionaries
Payment states
| State | Final | Description |
|---|---|---|
| init | no | Request to API will initiate payments. |
| pending | no | User redirected to the Checkout facility during payment processing period. |
| approved | yes | Successfully completed payment. |
| declined | yes | Unsuccessful payment. |
Kinds of errors
| Kind | Description |
|---|---|
| api_error | Indicate rare occasions such as an API server technicality. |
| authentication_error | Authentication request failure. |
| invalid_request_error | Invalid parameters which produce invalid requests. |
| processing_error | Processing the payment generated an error. |
Codes of errors
| Code | Description |
|---|---|
| incorrect_private_key | The current private key cannot identify the user. |
| incorrect_address_info | Absent or incorrect address information. |
| incorrect_bank_card_info | Absent or incorrect bank card information. |
| order_number_already_exists | Repeating an order of already identified order number. |
| amount_less_than_balance | Payout cannot be completed due to insufficient funds. |
| incorrect_amount | Absent or incorrect amount value. |
| incorrect_currency | Absent or incorrect currency value. |
| incorrect_order_number | Absent or incorrect order value. |
| amount_less_than_minimum | Minimum payout amount has not been requested. |
