Перейти к содержанию

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

Каждый запрос должен содержать параметр sign. По нему MEGOGO определяет вашу пару ключей и проверяет, что запрос никто не изменил. Ниже описано, как вычислить подпись, с рабочим примером и кодом.

Алгоритм

  1. Запишите приватный ключ.
  2. Допишите GET заглавными буквами.
  3. Допишите путь запроса — от /terminals/ до ?. Например, /terminals/example_operator/subscription/subscribe.
  4. Отсортируйте query-параметры по названию по возрастанию. sign не включайте.
  5. Допишите каждый параметр в виде название=значение без ?, & и других разделителей.
  6. Вычислите хеш SHA-256 от полученной строки (UTF-8) и запишите его как 64 шестнадцатеричных символа в нижнем регистре.
  7. Закодируйте эти 64 символа в Base64.
  8. Удалите символы =, а каждый / и + замените на -.
  9. Допишите _ и свой публичный ключ.
  10. Добавьте sign к URL.
text = private_key + "GET" + path + "name1=value1name2=value2" (sorted by name)
sign = base64(sha256_hex(text)) without "=", "/" and "+" → "-", + "_" + public_key

ОСТОРОЖНО

В Base64 кодируется шестнадцатеричный текст хеша, а не двоичный хеш. Результат до _ содержит 86 символов.

Значения параметров

  • Подписывайте значения до URL-кодирования: +380000000001, а не %2B380000000001.
  • Кодируйте значения только в URL. Символ + кодируйте как %2B: в URL + означает пробел.
  • Включайте в подпись все параметры, которые отправляете. Параметр, который есть в URL, но отсутствует в подписи, дает HTTP 401.

Рабочий пример

В примере используются вымышленные значения:

Значение Пример
ID партнера example_operator
Публичный ключ example_pub
Приватный ключ Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrST
Номер телефона 380000000001
ID услуги example_svod
Запрос GET /terminals/example_operator/subscription/subscribe?phone=380000000001&serviceId=example_svod
  1. Запишите приватный ключ, GET и путь:

    Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrSTGET/terminals/example_operator/subscription/subscribe
    
  2. Допишите параметры, отсортированные по названию (phone, затем serviceId):

    Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrSTGET/terminals/example_operator/subscription/subscribephone=380000000001serviceId=example_svod
    
  3. Вычислите хеш SHA-256:

    251876030d8bf8d5bdcbd14297ebdd8a6766ac0bdb30fa020856f3d3f036f82a
    
  4. Закодируйте текст хеша в Base64:

    MjUxODc2MDMwZDhiZjhkNWJkY2JkMTQyOTdlYmRkOGE2NzY2YWMwYmRiMzBmYTAyMDg1NmYzZDNmMDM2ZjgyYQ==
    
  5. Удалите =, замените / и + на -, допишите _ и публичный ключ:

    MjUxODc2MDMwZDhiZjhkNWJkY2JkMTQyOTdlYmRkOGE2NzY2YWMwYmRiMzBmYTAyMDg1NmYzZDNmMDM2ZjgyYQ_example_pub
    
  6. Добавьте sign к URL:

    https://billing.megogo.net/terminals/example_operator/subscription/subscribe?phone=380000000001&serviceId=example_svod&sign=MjUxODc2MDMwZDhiZjhkNWJkY2JkMTQyOTdlYmRkOGE2NzY2YWMwYmRiMzBmYTAyMDg1NmYzZDNmMDM2ZjgyYQ_example_pub
    

Другие примеры с теми же ключами:

Запрос Строка перед хешированием sign
subscriptions …GET/terminals/example_operator/subscriptions NjAwOGFmZDkyYzc1OTAyNzQ1NzEzZWRkNWIwZTY5NGRjMDgwZWNkN2UwZjc5ZmM0ZTQ2YmEwNWRlMTg3NzEyYg_example_pub
user/phone, phone=380000000001 …GET/terminals/example_operator/user/phonephone=380000000001 MjdhZTU2NzQ4YjAxMTI1NmQ0NGU5OWFkN2Y1OGRhNGM5ZDk2MDljODY4N2MwMzE4MzI3YTlkZGM2ZTE5YmFhMw_example_pub
user/phone, phone=+380000000001 …GET/terminals/example_operator/user/phonephone=+380000000001 YWU1MjYwZDcxNTA4NDg5MzM4ZjkwNjhjNWIyMTBhZWNhYTVkZjY2N2FlMzE2MjY4Nzk1OWEzMmJlZmVjN2QxZA_example_pub
subscriptions, phone=380000000001 …GET/terminals/example_operator/subscriptionsphone=380000000001 OWU1MGI2YjdjNDBlYTEyNTdlYmRjZWU4OWVjYmJkZDVhNTkwNDVhNmU3MDg1YzRiYmIxZGFkZDYxMzkzMGI3NQ_example_pub

… — это приватный ключ. Проверяйте свой код на этих примерах.

Код

Функции получают путь и параметры и сами сортируют параметры.

import base64
import hashlib
from urllib.parse import urlencode

def terminals_sign(path, params, private_key, public_key):
    text = private_key + "GET" + path
    text += "".join(f"{name}={params[name]}" for name in sorted(params))
    digest = hashlib.sha256(text.encode("utf-8")).hexdigest()
    sign = base64.b64encode(digest.encode("ascii")).decode("ascii")
    sign = sign.replace("=", "").replace("/", "-").replace("+", "-")
    return sign + "_" + public_key

def signed_url(path, params, private_key, public_key):
    query = dict(params, sign=terminals_sign(path, params, private_key, public_key))
    return "https://billing.megogo.net" + path + "?" + urlencode(query)

print(signed_url("/terminals/example_operator/subscription/subscribe",
                 {"phone": "380000000001", "serviceId": "example_svod"},
                 "Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrST", "example_pub"))
const crypto = require("crypto");

function terminalsSign(path, params, privateKey, publicKey) {
  const names = Object.keys(params).sort();
  const text = privateKey + "GET" + path + names.map((n) => `${n}=${params[n]}`).join("");
  const digest = crypto.createHash("sha256").update(text, "utf8").digest("hex");
  const sign = Buffer.from(digest, "ascii").toString("base64")
    .replace(/=/g, "").replace(/[/+]/g, "-");
  return sign + "_" + publicKey;
}

function signedUrl(path, params, privateKey, publicKey) {
  const query = new URLSearchParams({ ...params, sign: terminalsSign(path, params, privateKey, publicKey) });
  return "https://billing.megogo.net" + path + "?" + query;
}

console.log(signedUrl("/terminals/example_operator/subscription/subscribe",
  { phone: "380000000001", serviceId: "example_svod" },
  "Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrST", "example_pub"));
<?php
function terminals_sign(string $path, array $params, string $privateKey, string $publicKey): string {
    ksort($params, SORT_STRING);
    $text = $privateKey . 'GET' . $path;
    foreach ($params as $name => $value) {
        $text .= $name . '=' . $value;
    }
    $sign = base64_encode(hash('sha256', $text));
    $sign = str_replace(['=', '/', '+'], ['', '-', '-'], $sign);
    return $sign . '_' . $publicKey;
}

function terminals_signed_url(string $path, array $params, string $privateKey, string $publicKey): string {
    $params['sign'] = terminals_sign($path, $params, $privateKey, $publicKey);
    return 'https://billing.megogo.net' . $path . '?' . http_build_query($params, '', '&', PHP_QUERY_RFC3986);
}

echo terminals_signed_url('/terminals/example_operator/subscription/subscribe',
    ['phone' => '380000000001', 'serviceId' => 'example_svod'],
    'Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrST', 'example_pub'), "\n";

Все три примера дают URL из шага 6 рабочего примера.

ПРИМЕЧАНИЕ

В PHP hash('sha256', $text) возвращает шестнадцатеричный текст. Не устанавливайте третий параметр (binary) в true.

Ошибки

Ответ Причина Что делать
HTTP 401, "message": "Not Authorized" Подпись неправильная или отсутствует. Или ID партнера или публичный ключ неизвестны. Или IP-адреса вашего сервера нет в списке Проверьте свой код на рабочем примере. Убедитесь, что запрос приходит с сервера из списка. См. Учетные данные
HTTP 400, "message": "Invalid request format" Обязательного параметра нет в запросе, или он пустой См. Справочник API

Версия руководства 1.0.0, 2026-11-02 · Сообщить о проблеме на этой странице