Создание платежа
Пример
Запрос
URL
Заголовки:
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) | Сервис |
desc | string (128) | Описание |
lifetime | int | Время жизни в секундах (900–3600) |
customer_ip * | ip | IP адрес плательщика |
customer_account | string (50) | ID клиента в вашей системе |
customer_email | string (50) | Email адрес |
customer_first_name | string (50) | Имя |
customer_last_name | string (50) | Фамилия |
customer_address | string (50) | Адрес |
customer_phone | string (12) | Телефон |
customer_post_code | int (12) | Почтовый индекс |
customer_state | string (50) | Штат |
customer_city | string (20) | Город |
customer_browser_user_agent * | string (2000) | User Agent браузера |
customer_browser_accept_header | string (2000) | HTTP Accept заголовок |
customer_browser_color_depth | int | screen.colorDepth |
customer_browser_language | string (8) | HTTP Accept-Language |
customer_browser_screen_height | int | screen.height |
customer_browser_screen_width | int | screen.width |
customer_browser_window_height | int | window.innerHeight |
customer_browser_window_width | int | window.innerWidth |
customer_browser_time_different | int | (new Date()).getTimezoneOffset() |
customer_browser_java_enabled | int | 1 — JS включен, 0 — выключен |
success_redirect_id | int | ID редиректа при успехе |
fail_redirect_id | int | ID редиректа при неудаче |
notification_endpoint_id | int | ID уведомления |
success_redirect_url | string (max 255) | URL редиректа после успеха |
fail_redirect_url | string (max 255) | URL редиректа после ошибки |
notification_endpoint_url | string (max 255) | URL для колбека |
project_url | string | URL проекта (для агрегаторов) |
Ответ
Название | Описание |
---|---|
id | ID платежа AliKassa |
uuid | UUID платежа 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);