Checking payout status
Endpoint
Headers
| Header | Value |
|---|---|
| Content-Type | application/json |
| Account | Your account uuid, you can find in Accounts |
| Sign | Request signature |
Certificate Setup
To generate API certificate for payouts, visit: https://merchant.alikassa.io/cabinet/form/setting-api-certs
Save the archive and unpack to get:
password.txtprivate.pempublic.pem
We keep only public.pem for signature verification.
Signature Generation
Wrap all POST data in JSON (in the same order) and sign:
$data = json_encode($data);
$privateKey = openssl_pkey_get_private(
file_get_contents('private.pem'),
file_get_contents('password.txt')
);
if ($privateKey === false) {
throw new \Exception('Error cert.');
}
openssl_sign($data, $sign, $privateKey);
$sign = base64_encode($sign);
import { readFileSync } from 'fs';
import { createSign } from 'crypto';
const dataStr = JSON.stringify(data);
const privateKeyPem = readFileSync('private.pem', 'utf8');
const passphrase = readFileSync('password.txt', 'utf8').trim();
const signer = createSign('SHA1');
signer.update(dataStr);
signer.end();
const sign = signer.sign({ key: privateKeyPem, passphrase }, 'base64');
import json, base64
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
data_bytes = json.dumps(data).encode()
with open('password.txt','rb') as f:
password = f.read().strip()
with open('private.pem','rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=password)
signature = private_key.sign(data_bytes, padding.PKCS1v15(), hashes.SHA1())
sign = base64.b64encode(signature).decode()
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Signature;
import java.util.Base64;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
byte[] dataBytes = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsBytes(data);
char[] pass = Files.readString(Paths.get("password.txt")).toCharArray();
PEMParser parser = new PEMParser(Files.newBufferedReader(Paths.get("private.pem")));
PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) parser.readObject();
var privateKey = new JcaPEMKeyConverter()
.getKeyPair(ckp.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(pass)))
.getPrivate();
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(privateKey);
sig.update(dataBytes);
String sign = Base64.getEncoder().encodeToString(sig.sign());
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"io/ioutil"
)
dataBytes, _ := json.Marshal(data)
pemBytes, _ := ioutil.ReadFile("private.pem")
passBytes, _ := ioutil.ReadFile("password.txt")
block, _ := pem.Decode(pemBytes)
der, _ := x509.DecryptPEMBlock(block, passBytes)
priv, _ := x509.ParsePKCS1PrivateKey(der)
hash := sha1.Sum(dataBytes)
sigBytes, _ := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA1, hash[:])
sign := base64.StdEncoding.EncodeToString(sigBytes)
Pass the received $sign in the Sign header.
Request Parameters
| Name | Type | Description |
|---|---|---|
| order_id | string (128) | Your id specified during creation |
| id | string (128) | AliKassa payment id |
You must pass order_id or id.
Response
| Name | Description |
|---|---|
| order_id | Your id specified during creation |
| id | AliKassa payment id |
| payment_status | Payment status wait — in the process of payment paid — successfully paid (final status) cancel — canceled (final status) fail — error (final status) |
| card_mask | Card mask when paying by card |
| card_brand | Card brand (for example, VISA, MasterCard, MIR, etc.) |
| amount | Amount |
| payment_amount | Payment amount |
| is_partial_payment | Is the payment partial? |
| account_payment_amount | Amount credited to the account |
| commission_amount | Commission |
| service_code | Service |
| error_message | Error text/details in case of failed processing. Filled when payment_status = fail or cancel, absent for paid/wait. |
| RRN | RRN |
| account_old_balance | Balance before making a request |
| account_new_balance | Balance after request processing |
Response Example
*Successful Response (HTTP CODE 200)*
{
"payment_status": "paid",
"id": 100000536,
"order_id": "6422494",
"amount": "300.00",
"payment_amount": "300.00",
"is_partial_payment": false,
"account_payment_amount": "290",
"commission_amount": "10",
"service_code": "payment_card_rub",
"card_brand": "VISA",
"rrn": "11111111111",
"account_old_balance": "1290",
"account_new_balance": "1000"
}
*Failed response (HTTP CODE 200, with error)*
{
"payment_status": "fail",
"id": 100000537,
"order_id": "6422495",
"amount": "300.00",
"payment_amount": "0.00",
"is_partial_payment": false,
"account_payment_amount": "0",
"commission_amount": "0",
"service_code": "payment_card_rub",
"card_brand": "VISA",
"error_message": "Payment declined by issuer",
"rrn": null,
"account_old_balance": "1290",
"account_new_balance": "1290"
}
Error Response (HTTP 400):
*The payout with the specified ID/order_id was not found in the system. Please contact support and provide the request and response logs from the payment creation to investigate the issue. Do not assign a final status to this operation on your side until you receive guidance from support.*
{
"message": "Incorrect request. For information, contact support",
}
500 Server Error — Unexpected server-side error.
An internal error occurred while processing the request. In such a situation, the payment cannot be considered completed, cancelled, or unsuccessful on your side. The payout may be in one of the intermediate states, or it may have already been created, but is temporarily unavailable for verification. The payout status cannot be determined. If you receive such an error, you should contact support by attaching the request and response logs to clarify the reason and payment status.
{
"message": "Internal server error"
}
Example Implementation
Unpack the downloaded archive into the folder "path to script/cert/payout/"
function requestPayment(string $method, string $account, array $data)
{
$data = json_encode($data);
$privateKey = openssl_pkey_get_private(
file_get_contents(__DIR__ . '/cert/payout/private.pem'),
file_get_contents(__DIR__ . '/cert/payout/password.txt')
);
if ($privateKey === false) {
throw new \Exception('Error cert.');
}
openssl_sign($data, $sign, $privateKey);
$sign = base64_encode($sign);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api-merchant.alikassa.io/' . $method);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Account: ' . $account,
'Sign: ' . $sign,
]);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'AliKassa2.0 API');
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
return json_decode($response, true);
}
$payout = requestPayment('v1/payout/status', '93d5df06-996c-48c3-9847-348d6b580b80', [
'id' => '100000536',
]);
var_dump($payout);
import { readFileSync } from 'fs';
import { createSign } from 'crypto';
import https from 'https';
async function requestPayment(method, account, data) {
const dataStr = JSON.stringify(data);
const privateKeyPem = readFileSync('cert/payout/private.pem', 'utf8');
const passphrase = readFileSync('cert/payout/password.txt', 'utf8').trim();
const signer = createSign('SHA1');
signer.update(dataStr);
signer.end();
const sign = signer.sign({ key: privateKeyPem, passphrase }, 'base64');
const options = {
hostname: 'api-merchant.alikassa.io',
path: `/${method}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
Account: account,
Sign: sign,
'User-Agent': 'AliKassa2.0 API',
},
timeout: 30000,
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
let body = '';
res.on('data', (chunk) => (body += chunk));
res.on('end', () => resolve(JSON.parse(body)));
});
req.on('error', reject);
req.write(dataStr);
req.end();
});
}
(async () => {
const payout = await requestPayment(
'v1/payout/status',
'93d5df06-996c-48c3-9847-348d6b580b80',
{
id: '100000536',
}
);
console.log(payout);
})();
import json
import base64
import requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
def request_payment(method: str, account: str, data: dict):
data_bytes = json.dumps(data).encode('utf-8')
with open('cert/payout/password.txt', 'rb') as f:
password = f.read().strip()
with open('cert/payout/private.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=password)
signature = private_key.sign(data_bytes, padding.PKCS1v15(), hashes.SHA1())
sign = base64.b64encode(signature).decode('utf-8')
headers = {
'Content-Type': 'application/json',
'Account': account,
'Sign': sign,
'User-Agent': 'AliKassa2.0 API',
}
resp = requests.post(f'https://api-merchant.alikassa.io/{method}', json=data, headers=headers, timeout=30)
return resp.json()
payout = request_payment('v1/payout/status', '93d5df06-996c-48c3-9847-348d6b580b80', {
'id': '100000536',
})
print(payout)
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Signature;
import java.util.Base64;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
public class Example {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Map<String,String> data = Map.of("id", "100000536");
String dataStr = mapper.writeValueAsString(data);
char[] pass = Files.readString(Paths.get("cert/payout/password.txt")).toCharArray();
PEMParser parser = new PEMParser(Files.newBufferedReader(Paths.get("cert/payout/private.pem")));
PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) parser.readObject();
var kp = new JcaPEMKeyConverter().getKeyPair(
ckp.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(pass))
);
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(kp.getPrivate());
sig.update(dataStr.getBytes(StandardCharsets.UTF_8));
String sign = Base64.getEncoder().encodeToString(sig.sign());
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create("https://api-merchant.alikassa.io/v1/payout/status"))
.header("Content-Type", "application/json")
.header("Account", "93d5df06-996c-48c3-9847-348d6b580b80")
.header("Sign", sign)
.header("User-Agent", "AliKassa2.0 API")
.POST(HttpRequest.BodyPublishers.ofString(dataStr))
.build();
var client = HttpClient.newHttpClient();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(mapper.readValue(response.body(), Object.class));
}
}
package main
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"io/ioutil"
"net/http"
"time"
"fmt"
)
func signData(data interface{}) string {
dataBytes, _ := json.Marshal(data)
pemBytes, _ := ioutil.ReadFile("cert/payout/private.pem")
passBytes, _ := ioutil.ReadFile("cert/payout/password.txt")
block, _ := pem.Decode(pemBytes)
der, _ := x509.DecryptPEMBlock(block, passBytes)
priv, _ := x509.ParsePKCS1PrivateKey(der)
hash := sha1.Sum(dataBytes)
sigBytes, _ := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA1, hash[:])
return base64.StdEncoding.EncodeToString(sigBytes)
}
func requestPayment(method, account string, data interface{}) (map[string]interface{}, error) {
sign := signData(data)
body, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", "https://api-merchant.alikassa.io/"+method, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Account", account)
req.Header.Set("Sign", sign)
req.Header.Set("User-Agent", "AliKassa2.0 API")
client := &http.Client{Timeout: 30 * time.Second}
resp, _ := client.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
return result, nil
}
func main() {
payout, _ := requestPayment("v1/payout/status", "93d5df06-996c-48c3-9847-348d6b580b80", map[string]interface{}{
"id": "100000536",
})
fmt.Println(payout)
}