Checkout: Публичная T-Bank ссылка — параметры через Base64
Зачем это нужно
Публичная T-Bank ссылка EasyPay (https://pay.appload.tech/<slug>) по умолчанию работает в ad-hoc режиме: вы шарите один URL, плательщик сам вводит email и телефон, цена фиксирована = default_amount_rub из конфига чекаута. Этого достаточно для простых сценариев — «оплатить курс», «оплатить услугу».
Когда вам нужно больше — pre-fill полей формы, фиксированная цена в коридоре, или передача своего идентификатора заказа для атрибуции — добавьте к URL query-параметр ?d=<base64url(JSON)>. Кодируете payload у себя на стороне, фронтенд pay.appload.tech декодирует и предзаполняет форму. После оплаты ваш order_id возвращается обратно — в поле Payment.Data.ep_order вебхука и строкой Order: в Telegram-уведомлении.
Как это работает
Использование сводится к трём шагам:
Соберите payload с нужными полями (
order_id,email,phone,amount_rub— все опциональны).Закодируйте его в Base64URL (см. примеры ниже).
Подставьте в URL:
https://pay.appload.tech/<slug>?d=<base64>.
После успешной оплаты EasyPay присылает вам уведомление через настроенный канал (Telegram-триггер tbank.transaction_confirmed или webhook). Ваш order_id возвращается ровно в том виде, в котором вы его передали:
webhook — поле
Payment.Data.ep_order(структура тела: «Webhook EasyPay: структура данных платежей T-Bank»);Telegram — строка
Order:в сообщении об оплате (наш внутреннийOrderIDв том же сообщении — это идентификатор попытки на нашей стороне, для сопоставления он не нужен).
URL-контракт
https://pay.appload.tech/<slug>?d=<base64url(JSON)><slug>—product_slugчекаута. Lowercase, регулярка[a-z0-9][a-z0-9-]{1,62}.<base64url(JSON)>— закодированный payload (см. ниже). Опционален — без?d=URL работает в ad-hoc режиме.
Payload
{
"order_id": "u_a1b2c3",
"email": "user@example.com",
"phone": "+79991234567",
"amount_rub": 5990
}Поле | Обязательное | Описание |
|---|---|---|
| Нет | Ваш идентификатор заказа. Регулярка |
| Нет | Pre-fill email на форме. Если задан — должен пройти валидацию ( |
| Нет | Pre-fill телефона. Формат |
| Нет | Точная цена в рублях. Учитывается ТОЛЬКО если задан |
Anti-underpayment. Если передаёте amount_rub без order_id, поле игнорируется и checkout сворачивается в ad-hoc (= default). Это сознательная защита: нестандартная цена должна быть привязана к конкретному заказу, иначе можно случайно дать скидку по битой ссылке.
Поведение при ошибке декодинга. Если ?d= присутствует, но не парсится — фронтенд покажет ошибку «Некорректная ссылка» и не упадёт в ad-hoc. Это защита от молчаливого «проглатывания» битой ссылки с intended discount или order_id.
Кодирование Base64URL
Алгоритм: сериализовать payload в JSON → UTF-8 → стандартный Base64 → URL-safe замены (+ → -, / → _, padding = опционально).
JavaScript / Node:
function encodePayload(payload) {
return Buffer.from(JSON.stringify(payload), "utf8")
.toString("base64")
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
const url = `https://pay.appload.tech/matrixon-colearn?d=${encodePayload({
order_id: "u_a1b2c3",
email: "user@example.com",
amount_rub: 5990
})}`;Python:
import base64, json
def encode_payload(payload):
raw = json.dumps(payload, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
return base64.urlsafe_b64encode(raw).decode().rstrip("=")
url = f"https://pay.appload.tech/matrixon-colearn?d={encode_payload({
'order_id': 'u_a1b2c3',
'email': 'user@example.com',
'amount_rub': 5990,
})}"Как параметры возвращаются обратно
После оплаты вам приходит уведомление на ваш канал. В теле вебхука поле Payment.Data.ep_order — ровно то, что вы положили в order_id внутри ?d=.
На вашей стороне:
Получите свой идентификатор из
Payment.Data.ep_order.Если
order_idвы не передавали, EasyPay сгенерировал свой — такой начинается сauto-:
if (order_id.startsWith("auto-")) {
// идентификатор сгенерировали мы — вашего заказа за ним нет
return null;
}Полный пример
Сценарий. Отправить персональную ссылку по заказу A-1043 клиенту user@example.com по цене 5990 ₽ (default по чекауту — 9990 ₽).
const slug = "my-product";
const payload = { order_id: "A-1043", email: "user@example.com", amount_rub: 5990 };
const dParam = encodePayload(payload);
const url = `https://pay.appload.tech/${slug}?d=${dParam}`;
// Шлёте url клиенту → клиент оплачивает →
// EasyPay присылает вебхук с Payment.Data.ep_order = "A-1043" →
// находите у себя заказ A-1043 и отмечаете его оплаченным.Ограничения
Размер
**order_id**: ≤64 символа, charset[A-Za-z0-9_-]. Если ваш идентификатор длиннее — храните у себя короткий ключ-ссылку на заказ.Schema payload фиксированная — только 4 поля (
order_id,email,phone,amount_rub). Свои ключи в payload игнорируются.Anti-underpayment:
amount_rubбезorder_idвсегда игнорируется. Хотите кастомную цену — обязательно передавайте иorder_id.Anti-corrupt link: битый
?d=(не декодится) → ошибка на странице, не degradation в ad-hoc.Безопасность.
order_idуезжает в T-Bank отдельным параметром платежа (виден в их кабинете), приходит к вам в уведомлении и хранится в БД EasyPay. Не кладите туда секреты — только публичный контекст: ID, источники, флаги. Если нужно прокинуть что-то чувствительное — держите у себя по короткому ключу.Идемпотентность вебхука. У платежей по публичной ссылке
Payment.Data.ep_payment_uuidприходитnull— он существует только у платежей, созданных через API сidempotency_key. Ключ дедупликации повторных доставок здесь —Payment.OrderId.Идемпотентность ссылки. Тот же
order_idс теми же(slug, amount, email, phone)→ replay, вернётся та же T-Bank ссылка. Тот жеorder_idс другими полями →idempotency_conflict. Если планируете retry — держитеorder_idстабильным для одной попытки.
Ошибки
Все ошибки возвращаются с HTTP 200 + success: false.
| Когда |
|---|---|
|
|
|
|
| Email/телефон не прошёл валидацию при submit. |
|
|
|
|
| Параллельный запрос с тем же |
| Прошлая попытка с этим |
| Чекаута с таким slug нет, либо статус не |
Дополнительно фронтенд показывает страницу «Некорректная ссылка» при невалидном slug или нераспарсенном ?d=.