API Documentation

API документация — это ваш быстрый вход в интеграцию с нашим платёжным шлюзом. Ниже вы найдёте правила формирования ссылок на платёжную страницу, подписи запросов, формат вебхуков и готовые примеры кода для Node.js и Python, чтобы запустить приём платежей за считанные минуты.

Редирект пользователя на платёжное окно

Сформируйте подпись и соберите URL

  • Создайте проект, и получите ключи
  • Посчитайте подпись (sha256 → base64)
  • Сделайте редирект на https://payment.twizzygate.tech/

Базовый URL и параметры

Базовый URL:
Copied!
https://payment.twizzygate.tech/
ПараметрТипОбязат.ПримерОписание
orderNumstringДа456ID заказа на стороне мерчанта
amountnumberДа100.00Сумма (с двумя знаками или целое)
currencystringДаRUBВалюта
clientstringДаpub_123Публичный ключ клиента
signstringДаBase64Подпись (см. ниже)
Важно! Из набора для подписи исключите client и sign. Сортируйте ключи, склейте key=value через & и добавьте в конец secret без имени.

Подпись запроса

  • Исключите client и sign из запроса.
  • Отсортируйте ключи по алфавиту (ASCII).
  • Соберите строку: k1=v1&k2=v2&...&secret .
  • Вычислите sha256 → base64.
Copied!
// ⚠️ Считайте подпись на сервере. Секрет не уходит на фронт.
import crypto from "node:crypto";

type Params = Record<string, string | number | undefined>; 

function makeSign(params: Params, secret: string): string {
  const entries = Object.entries(params)
    .filter(([k, v]) => k !== 'client' && k !== 'sign' && v !== undefined)
    .sort(([a], [b]) => a.localeCompare(b));

  const base = entries.map(([k, v]) => `${k}=${v}`).join('&') + `&${secret}`;
  const digest = crypto.createHash('sha256').update(base, 'utf8').digest();
  return Buffer.from(digest).toString("base64");
}

const params = { orderNum: "456", amount: "100.00", currency: "RUB", client: "pub_123" };
const secret = "my_secret";
const sign = makeSign(params, secret);
console.log(sign);
Тест-векторы
params: {amount: "100.00", currency: "RUB", orderNum: "456"}, secret: my_secret
base: amount=100.00&currency=RUB&orderNum=456&my_secret
sign: KhizMnxNLB/XuSSoLhLZJz/+oq4nwLr3UVTeOYNOWlo=
params: { amount: "1200.50", currency: "RUB", orderNum: "ORD-1001" }, secret: sec_abc
base: amount=1200.50&currency=RUB&orderNum=ORD-1001&sec_abc
sign: xrgISoNmltwflMXLOvLIgqK6omiLIY9F2I6aXASo0MI=
Советы: используйте стабильный формат суммы (например 100.00), не включайте пустые поля в подпись, храните секрет только на бекенде.

Примеры

Готовый URL
Copied!
https://payment.twizzygate.tech/?orderNum=456&amount=100.00&currency=RUB&client=pub_123&sign=KhizMnxNLB%2FXuSSoLhLZJz%2F%2Boq4nwLr3UVTeOYNOWlo%3D
cURL
Copied!
curl -L
  "https://payment.twizzygate.tech/?orderNum=456&amount=100.00&currency=RUB&client=pub_123&sign=KhizMnxNLB%2FXuSSoLhLZJz%2F%2Boq4nwLr3UVTeOYNOWlo%3D"

Ошибки

При некорректной подписи пользователь увидит ошибку.

Коллбек с результатом операции (Webhook)

После обработки платежа мы отправим POST-запрос на ваш бекенд с результатом операции. URL для коллбека вы настраиваете в панели управления проекта.

Метод
POST
URL

Указывается вами в настройках проекта (например: https://merchant.com/payment/callback).

Заголовки
НазваниеОписание
X-Client-KeyПубличный ключ клиента
X-Signature Подпись запроса (см. раздел ниже). Используется для проверки, что запрос исходит от нас.
Тело запроса (application/json)
{
  "orderNum": "456",
  "status": "success",
  "details": {}
}
  • orderNum — ID заказа на вашей стороне.
  • status — статус операции: "success", "fail" или "cancel".
  • details — объект с дополнительной информацией (зарезервировано, может быть пустым).

Подпись коллбека (X-Signature)

Для защиты от подмены запросов каждый коллбек подписывается. Вам необходимо на своей стороне пересчитать подпись и сравнить с заголовком X-Signature.

  1. Используйте поля orderNum и status из тела запроса.
  2. Отсортируйте их по алфавиту ключей.
  3. Соберите строку в формате key=value через & и добавьте в конец ваш секретный ключ (без имени).
  4. Посчитайте SHA-256 от строки и закодируйте результат в Base64.
  5. Сравните полученное значение с заголовком X-Signature .
Пример строки для подписи (если orderNum=456 , status=success , секрет sec_abc ):
orderNum=456&status=success&sec_abc
Node.js пример проверки
import crypto from "node:crypto";

function makeSignature(body, secret) {
  const params = {
    orderNum: body.orderNum,
    status: body.status,
  };

  const entries = Object.entries(params)
    .filter(([, v]) => v !== undefined && v !== null)
    .sort(([a], [b]) => a.localeCompare(b));

  const base = entries.map(([k, v]) => `${k}=${v}`).join("&") + `&${secret}`;
  const digest = crypto.createHash("sha256").update(base, "utf8").digest();
  return Buffer.from(digest).toString("base64");
}

function isValidCallback(reqBody, headers, secret) {
  const expected = makeSignature(reqBody, secret);
  const received = String(headers["x-signature"] || "");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
}
Python пример проверки
import hmac, hashlib, base64

def make_signature(body: dict, secret: str) -> str:
    params = {
        "orderNum": body.get("orderNum"),
        "status": body.get("status"),
    }
    items = sorted((k, v) for k, v in params.items() if v is not None)
    base = "&".join(f"{k}={v}" for k, v in items) + f"&{secret}"
    digest = hashlib.sha256(base.encode("utf-8")).digest()
    return base64.b64encode(digest).decode("ascii")

def is_valid_callback(body: dict, headers: dict, secret: str) -> bool:
    expected = make_signature(body, secret)
    received = headers.get("X-Signature", "")
    return hmac.compare_digest(expected, received)
Важно:
  • Секретный ключ храните только на сервере.
  • Проверяйте X-Client-Key и соответствие вашему проекту.
  • Используйте timing safe сравнение строк при проверке подписи.