Подпись запроса¶
Каждый запрос должен содержать параметр sign. По нему MEGOGO определяет
вашу пару ключей и проверяет, что запрос никто не изменил. Ниже описано,
как вычислить подпись, с рабочим примером и кодом.
Алгоритм¶
- Запишите приватный ключ.
- Допишите
GETзаглавными буквами. - Допишите путь запроса — от
/terminals/до?. Например,/terminals/example_operator/subscription/subscribe. - Отсортируйте query-параметры по названию по возрастанию.
signне включайте. - Допишите каждый параметр в виде
название=значениебез?,&и других разделителей. - Вычислите хеш SHA-256 от полученной строки (UTF-8) и запишите его как 64 шестнадцатеричных символа в нижнем регистре.
- Закодируйте эти 64 символа в Base64.
- Удалите символы
=, а каждый/и+замените на-. - Допишите
_и свой публичный ключ. - Добавьте
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 |
-
Запишите приватный ключ,
GETи путь:Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrSTGET/terminals/example_operator/subscription/subscribe -
Допишите параметры, отсортированные по названию (
phone, затемserviceId):Ex4mpleK3yN0tRealAbCdEfGhIjKlMnOpQrSTGET/terminals/example_operator/subscription/subscribephone=380000000001serviceId=example_svod -
Вычислите хеш SHA-256:
251876030d8bf8d5bdcbd14297ebdd8a6766ac0bdb30fa020856f3d3f036f82a -
Закодируйте текст хеша в Base64:
MjUxODc2MDMwZDhiZjhkNWJkY2JkMTQyOTdlYmRkOGE2NzY2YWMwYmRiMzBmYTAyMDg1NmYzZDNmMDM2ZjgyYQ== -
Удалите
=, замените/и+на-, допишите_и публичный ключ:MjUxODc2MDMwZDhiZjhkNWJkY2JkMTQyOTdlYmRkOGE2NzY2YWMwYmRiMzBmYTAyMDg1NmYzZDNmMDM2ZjgyYQ_example_pub -
Добавьте
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 · Сообщить о проблеме на этой странице