Перейти к основному содержимому

Создание платежа

Пример

Запрос

URL

POSThttps://api-merchant.alikassa.com/v1/payment📋

Заголовки:

  • Content-Type: application/json
  • Account: UUID вашего счета (доступен по адресу: Счета проекта)
  • Sign: Подпись запроса

Перейдите в Настройки API сертификатов и сгенерируйте «API сертификат на оплаты». Сохраните и распакуйте архив:

  • password.txt
  • private.pem
  • public.pem

Мы сохраняем только public.pem для проверки подписи.

Оберните все POST-данные в JSON (в том же порядке) и подпишите:

$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('Ошибка сертификата.');
}

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('SHA256');
signer.update(dataStr);
signer.end();
const signature = signer.sign(
{ key: privateKeyPem, passphrase: passphrase },
'base64'
);
import json
import base64
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

data_bytes = json.dumps(data).encode('utf-8')
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.SHA256()
)
sign = base64.b64encode(signature).decode('utf-8')
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.security.Signature;
import java.util.Base64;
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;

ObjectMapper mapper = new ObjectMapper();
String dataStr = mapper.writeValueAsString(data);
char[] pass = new String(java.nio.file.Files.readAllBytes(
java.nio.file.Paths.get("password.txt")
)).toCharArray();
PEMParser parser = new PEMParser(new FileReader("private.pem"));
PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) parser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PrivateKey privateKey = converter.getKeyPair(
ckp.decryptKeyPair(
new JcePEMDecryptorProviderBuilder().build(pass)
)
).getPrivate();
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(privateKey);
sig.update(dataStr.getBytes(StandardCharsets.UTF_8));
String sign = Base64.getEncoder().encodeToString(sig.sign());
package main

import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"io/ioutil"
)

func main() {
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 := sha256.Sum256(dataBytes)
sigBytes, _ := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hash[:])
sign := base64.StdEncoding.EncodeToString(sigBytes)
_ = sign
}

Полученную подпись $sign передайте в заголовке Sign.


Обязательные поля

НазваниеТипОписание
amount*decimal (11.2)Сумма
order_id*string (128)Ваш уникальный ID
service*string (100)Сервис
descstring (128)Описание
lifetimeintВремя жизни в секундах (900–3600)
customer_ip*ipIP адрес плательщика
customer_accountstring (50)ID клиента в вашей системе
customer_emailstring (50)Email адрес
customer_first_namestring (50)Имя
customer_last_namestring (50)Фамилия
customer_addressstring (50)Адрес
customer_phonestring (12)Телефон
customer_post_codeint (12)Почтовый индекс
customer_statestring (50)Штат
customer_citystring (20)Город
customer_browser_user_agent*string (2000)User Agent браузера
customer_browser_accept_headerstring (2000)HTTP Accept заголовок
customer_browser_color_depthintscreen.colorDepth
customer_browser_languagestring (8)HTTP Accept-Language
customer_browser_screen_heightintscreen.height
customer_browser_screen_widthintscreen.width
customer_browser_window_heightintwindow.innerHeight
customer_browser_window_widthintwindow.innerWidth
customer_browser_time_differentint(new Date()).getTimezoneOffset()
customer_browser_java_enabledint1 — JS включен, 0 — выключен
success_redirect_idintID редиректа при успехе
fail_redirect_idintID редиректа при неудаче
notification_endpoint_idintID уведомления
success_redirect_urlstring (max 255)URL редиректа после успеха
fail_redirect_urlstring (max 255)URL редиректа после ошибки
notification_endpoint_urlstring (max 255)URL для колбека
project_urlstringURL проекта (для агрегаторов)

Ответ

НазваниеОписание
idID платежа AliKassa
uuidUUID платежа AliKassa
urlСсылка на оплату
payment_statusСтатус платежа

Изначально payment_status всегда wait. Проверяйте статус через API или ожидайте уведомления.

Пример успешного ответа (HTTP 200):

{
"url": "https://pay-merchant.alikassa.com/bd291fe1-5c19-4113-ae62-a2d3c4d01d20",
"payment_status": "wait",
"id": 100001524,
"uuid": "h12a5a34-7e21-3789-bf53-96fe96131601"
}

Пример ошибки (HTTP 400):

{
"message": "The given data was invalid.",
"errors": {
...
}
}

После получения URL переадресуйте клиента по ссылке на оплату.

Проверка статуса платежа

При создании всегда ждите, проверяйте статус платежа через API или ждите получение уведомления!


Уведомления

Настройка уведомлений

Если вы передали notification_endpoint_id, то вы получите уведомление о смене статуса оплаты


Пример кода

Скачанный архив распакуйте в папку «путь до скрипта/cert/payment/»

function requestPayment(string $method, string $account, array $data)
{
$data = json_encode($data);

$privateKey = openssl_pkey_get_private(
file_get_contents(__DIR__ . '/cert/payment/private.pem'),
file_get_contents(__DIR__ . '/cert/payment/password.txt')
);

if ($privateKey === false) {
throw new \Exception('Ошибка сертификата.');
}

openssl_sign($data, $sign, $privateKey);
$sign = base64_encode($sign);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api-merchant.alikassa.com/' . $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);
}

$payment = requestPayment('v1/payment', '93d5df06-996c-48c3-9847-348d6b580b80', [
'order_id' => (string)time(),
'amount' => 500,
'customer_browser_user_agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0',
'customer_ip' => '18.191.80.10',
'success_redirect_id' => 1,
'fail_redirect_id' => 1,
'notification_endpoint_id' => 5,
'service' => 'payment_card_rub_hpp',
]);

var_dump($payment);