Skip to Content
Разовые платежиПодпись запросов

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

Подпись подтверждает подлинность запроса. Поддерживаются две версии алгоритма: 3 (по логину) и 4 (с привязкой к телу запроса).

Общие шаги

Внутренний хеш
innerHash = lowercase(hmac_sha256(password, timestamp))
  • password — секретный ключ мерчанта, хранится в настройках проекта на стороне платформы.
  • login — значение заголовка X-Login.
  • timestamp — значение заголовка X-Timestamp.

password — секрет. Он не передаётся в запросе, не логируется и не должен попадать в клиентский код: подпись считается только на сервере мерчанта.

Версия 3 — по логину

signature = lowercase(hmac_sha256(password, login + innerHash))
Пример
password = "password" login = "login" timestamp = "2025-02-10T17:56:37Z" innerHash = lowercase(hmac_sha256("password", "2025-02-10T17:56:37Z")) signature = lowercase(hmac_sha256("password", "login" + innerHash)) → "5f9e4f4a7a805b898cac96a6c3e7a81dd0e06e200c291d51663e6f250b10853f"

Реализация подписи v3

LOGIN=demo_login PASSWORD=demo_password TS=$(date -u +%Y-%m-%dT%H:%M:%SZ) INNER=$(printf '%s' "$TS" \ | openssl dgst -sha256 -hmac "$PASSWORD" | awk '{print $NF}') SIG=$(printf '%s%s' "$LOGIN" "$INNER" \ | openssl dgst -sha256 -hmac "$PASSWORD" | awk '{print $NF}')

Для версии 4 к сообщению добавляется requestPayload — та же функция, но подписывается requestPayload + login + innerHash.

Версия 4 — с привязкой к телу запроса

signature = lowercase(hmac_sha256(password, requestPayload + login + innerHash))

requestPayload — детерминированная конкатенация значимых полей запроса без разделителей:

Метод и путьPayload
POST /invoices{order.merchant_order_id}{customerPayload}{order.price.amount}{order.price.currency}{contract.merchant_contract_id}{client_ip}
POST /invoices/{id}/authorize{invoice_id}{pin_code}{client_ip}
POST /invoices/{id}/cancel{invoice_id}{client_ip}
POST /invoices/{id}/refund{invoice_id}{client_ip}
GET /invoices/{id}{invoice_id}
GET /invoices?merchant_order_id=...{merchant_order_id}
POST /contracts{merchant_contract_id}{customerPayload}{pin_code}{client_ip}
POST /contracts/{id}/authorize{contract_id}{merchant_contract_id}{pin_code}{client_ip}
POST /contracts/{id}/cancel{contract_id}{merchant_contract_id}{client_ip}
POST /billing/check{customerPayload}

customerPayload зависит от customer.type:

ТипPayload
mobile_phone{msisdn}
undefined_bank_card, bank_card{source}{country}{merchant_customer_id}{email}
(иное / нет)(пустая строка)

Любое отсутствующее поле подставляется как пустая строка. ID счёта или контракта берётся из URL пути.