Аутентификация
Аутентификация запросов к Syncra Merchant API V2 с использованием HMAC-SHA256 подписей
Аутентификация запросов
Безопасность является главным приоритетом при взаимодействии с Syncra Merchant API V2. Все запросы к нашему программному интерфейсу должны проходить обязательную аутентификацию и проверку целостности данных. Это позволяет защитить вашу интеграцию от атак типа «человек посередине» (MITM), подделки параметров и повторного воспроизведения запросов (replay attacks).
Syncra V2 использует схему аутентификации на основе секретных токенов и криптографических подписей HMAC-SHA256.
Обязательные HTTP-заголовки
Каждый HTTP-запрос к нашему API должен сопровождаться тремя обязательными заголовками:
| Имя заголовка | Тип значения | Описание |
|---|---|---|
X-Merchant-Token | Строка (64-char hex) | Уникальный публичный токен идентификации мерчанта. Выдается в личном кабинете. |
X-Timestamp | Целое число (Unix Epoch) | Текущее время выполнения запроса на стороне мерчанта (в секундах). |
X-Signature | Строка | Вычисленная криптографическая подпись запроса. Формат: t={timestamp},v1={hmac_sha256_hex}. |
Внимание: В отличие от устаревшей версии API V1, в которой заголовки имели имена MERCHANT и SIGNATURE без девелоперских префиксов, в API V2 используются исключительно заголовки с префиксом X-. Подписи вычисляются по алгоритму SHA256 вместо SHA512.
Алгоритм вычисления подписи
Для вычисления подписи вам потребуется ваш приватный Webhook Secret Key (также называемый секретом подписи), который выдается один раз в панели управления мерчанта.
Чтобы сгенерировать корректную подпись для отправки в заголовке X-Signature, выполните следующие шаги:
- Получите текущую метку времени: Получите текущее время в формате Unix timestamp (в секундах), например:
1783856120. - Подготовьте тело запроса: Используйте в расчетах исходное сырое текстовое тело JSON-запроса (Raw Request Body) в том виде, в котором оно отправляется по сети. Пробелы, переводы строк и порядок полей имеют значение. Для запросов без тела (например, GET) используйте пустую строку
"". - Сформируйте полезную нагрузку (Payload): Объедините метку времени из шага 1 и сырое тело из шага 2 через символ точки (
.). Формула:payload = timestamp + "." + raw_bodyПример:1783856120.{"amount":150000,"currency":"RUB"} - Вычислите HMAC-SHA256: Используя ваш приватный секретный ключ (Webhook Secret Key) в качестве ключа подписи, вычислите HMAC-SHA256 от сформированной полезной нагрузки (Payload) из шага 3.
- Преобразуйте в Hex-строку: Полученный бинарный результат хэширования преобразуйте в шестнадцатеричную строку в нижнем регистре.
- Соберите итоговое значение заголовка: Сформируйте строку в формате:
X-Signature: t={timestamp},v1={hex_signature}
Защита от Replay-атак:
Сервер Syncra проверяет временной интервал между временем, указанным в заголовке X-Timestamp, и серверным системным временем. Если разница составляет более 5 минут (300 секунд), запрос отклоняется с кодом 401 Unauthenticated. Это предотвращает повторный перехват и отправку легитимных запросов злоумышленниками.
Примеры реализации на различных языках программирования
Ниже приведены готовые к копированию фрагменты кода на популярных языках программирования для генерации подписей.
const crypto = require('crypto');
function generateV2Signature(body, webhookSecret) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const payload = `${timestamp}.${body}`;
const signature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
return {
'X-Merchant-Token': 'your_merchant_token_here',
'X-Timestamp': timestamp,
'X-Signature': `t=${timestamp},v1=${signature}`
};
}import time
import hmac
import hashlib
def generate_v2_signature(body_str: str, webhook_secret: str):
timestamp = str(int(time.time()))
payload = f"{timestamp}.{body_str}"
signature = hmac.new(
webhook_secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
return {
'X-Merchant-Token': 'your_merchant_token_here',
'X-Timestamp': timestamp,
'X-Signature': f"t={timestamp},v1={signature}"
}<?php
function generateV2Signature($bodyStr, $webhookSecret) {
$timestamp = (string)time();
$payload = $timestamp . '.' . $bodyStr;
$signature = hash_hmac('sha256', $payload, $webhookSecret);
return [
'X-Merchant-Token' => 'your_merchant_token_here',
'X-Timestamp' => $timestamp,
'X-Signature' => "t={$timestamp},v1={$signature}"
];
}
?>package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
"time"
)
func GenerateV2Signature(body []byte, secret []byte) map[string]string {
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
payload := fmt.Sprintf("%s.%s", timestamp, string(body))
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(payload))
signature := hex.EncodeToString(mac.Sum(nil))
return map[string]string{
"X-Merchant-Token": "your_merchant_token_here",
"X-Timestamp": timestamp,
"X-Signature": fmt.Sprintf("t=%s,v1=%s", timestamp, signature),
}
}Таблица сравнения версий безопасности API
Для разработчиков, мигрирующих с legacy-системы V1, приведена таблица различий:
| Параметр | Устаревшая система V1 | Новая система V2 |
|---|---|---|
| Алгоритм хеширования | HMAC-SHA512 | HMAC-SHA256 |
| Входной формат подписи | Разные строки per endpoint (например, ts;payin_id;salt) | Единый формат timestamp.body для всех запросов |
| Идентификатор мерчанта | MERCHANT header (GUID) | X-Merchant-Token (64-char hex) |
| Передача подписи | SIGNATURE header (raw hex) | X-Signature header (t={ts},v1={hex}) |
| Защита от replay-атак | Нет (или на стороне мерчанта по соли) | Встроена на уровне шлюза (5 минут таймаут) |
| Заголовок времени | Передается внутри формулы подписи | Отдельный заголовок X-Timestamp |