PAYNEX — быстрый старт интеграции

Одна страница для технарей: как слать депозит/выплату и что придёт в вебхуке. Полный референс — /integration, Swagger /docs и ReDoc с готовыми примерами на разных языках /redoc.

Полный ключ выдаётся только один раз. В ЛК хранится лишь preview/fingerprint; при утрате выполните ротацию в Настройки → API. Старый ключ по умолчанию действует ещё 24 часа, чтобы вы успели переключить сервер, после чего отзывается автоматически.

Задача Метод
Создать Pay-In POST /api/v1/payments
Проверить Pay-In GET /api/v1/payments/{payment_id}
Создать Pay-Out POST /api/v1/payouts
Проверить Pay-Out GET /api/v1/payouts/{payout_id}
Получить комиссионный баланс GET /api/v1/balance
Посмотреть / изменить webhook GET /api/v1/webhook · PUT /api/v1/webhook

Pay-In и Pay-Out проверяются отдельными status-методами, поэтому направление всегда явно видно в коде. Финальный финансовый результат унифицирован статусом операции.


1. Депозит (Pay-In) — POST /api/v1/payments

curl -X POST https://paynex.work/api/v1/payments \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: dep-0001" \
  -d '{
    "amount_kopecks": 500000,
    "currency": "RUB",
    "payment_method": "card",
    "merchant_player_id": "user_42",
    "merchant_payment_id": "deposit_0001",
    "player_full_name": "Иванов Иван Иванович"
  }'

Ответ 201:

{
  "payment_id": "de09a768-...",
  "status": "matching",
  "checkout_url": "https://paynex.top/pay/Qc6CllN0...",
  "amount_kopecks": 500000,
  "expires_at": "...", "created_at": "..."
}

→ Редиректьте игрока на checkout_url (там реквизиты + загрузка чека). Итог придёт вебхуком. Если пара нашлась сразу, начальный статус в ответе уже может быть awaiting_payment.


2. Выплата (Pay-Out) — POST /api/v1/payouts

На карту:

curl -X POST https://paynex.work/api/v1/payouts \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: payout-0001" \
  -d '{
    "amount_kopecks": 500000, "currency": "RUB", "payment_method": "card",
    "merchant_player_id": "user_42",
    "merchant_payment_id": "withdrawal_0001",
    "recipient_card_number": "4276 4400 1234 5678",
    "recipient_card_holder": "IVAN IVANOV"
  }'

По СБП: вместо карты — "payment_method": "sbp", "recipient_sbp_phone": "+7 999 123-45-67", "recipient_sbp_bank_code": "SBER".

Ответ 201 содержит payment_id, status, recipient_last4.

Для обоих endpoint передавайте оба идентификатора: Idempotency-Key защищает повтор того же HTTP-запроса, а merchant_payment_id уникален для бизнес-операции мерчанта сразу между Pay-In и Pay-Out. То же нормализованное тело вернёт существующий платёж; другое тело или другое направление с тем же merchant_payment_id получит 409.


3. Проверить статус Pay-In или Pay-Out

Для Pay-In используйте GET /api/v1/payments/{payment_id}:

curl https://paynex.work/api/v1/payments/deposit_0001 \
  -H "Authorization: Bearer $KEY"

Для Pay-Out — отдельный метод GET /api/v1/payouts/{payout_id}:

curl https://paynex.work/api/v1/payouts/withdrawal_0001 \
  -H "Authorization: Bearer $KEY"

В обоих путях принимается payment_id PAYNEX или собственный merchant_payment_id. Pay-In нельзя запросить через payout-метод и наоборот. Ответ содержит текущий статус, сумму и даты создания/обновления/завершения. Чужая, отсутствующая или относящаяся к другому направлению операция возвращает 404 без раскрытия другого мерчанта.


4. Проверить баланс — GET /api/v1/balance

curl https://paynex.work/api/v1/balance \
  -H "Authorization: Bearer $KEY"

Баланс — комиссионный счёт в центах USDT: начислено минус погашено. PAYNEX не хранит кошелёк доступных средств мерчанта. При неполной исторической оценке денежные итоги возвращаются как null вместе с accounting_complete=false.


5. Установить webhook — PUT /api/v1/webhook

curl -X PUT https://paynex.work/api/v1/webhook \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"webhook_url":"https://merchant.example/webhooks/paynex"}'

Текущую настройку возвращает GET /api/v1/webhook, для отключения передайте {"webhook_url":null}.

На дефолтный webhook_url из ЛК → Настройки шлём POST. Для Pay-In URL можно переопределить полем webhook_url в заявке; Pay-Out сейчас использует только дефолтный URL. Если URL не был настроен к моменту события, такое событие не создаётся и позже не догоняется.

Используйте публичный https:// endpoint на порту 443 без credentials и fragment. Redirect не выполняется, а private/loopback/link-local адреса блокируются.

Заголовки:

X-Paynex-Event-Type: payment.completed
X-Paynex-Timestamp:  1781162244
X-Paynex-Signature:  <hex HMAC-SHA256>
X-Paynex-Event-Id:   <id события>

Тело:

{
  "event_id": "...", "event_type": "payment.completed",
  "payment": { "id": "de09a768-...", "merchant_payment_id": "...",
    "direction": "payin", "status": "completed",
    "amount_kopecks": 500000, "currency": "RUB", "payment_method": "card" }
}

Проверка подписи (обязательно), Sign Key = ваш api_secret:

import hmac, hashlib, time
def verify(sign_key, headers, raw_body: bytes) -> bool:
    ts = headers["X-Paynex-Timestamp"]
    if abs(time.time() - int(ts)) > 300:           # старше 5 мин — отклонить
        return False
    expected = hmac.new(sign_key.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, headers["X-Paynex-Signature"])

Тело берите как пришло, побайтово (не пересериализуйте). Отвечайте 2xx. Обрабатывайте идемпотентно по event_id: по умолчанию возможны до 8 попыток доставки.


6. Статусы

Pay-In: pending → matching → awaiting_payment → awaiting_verification → completed (или failed / expired / cancelled). Pay-Out не входит в awaiting_verification: при частичном N:1-матчинге он может переходить между matching и awaiting_payment, пока не подтверждены все части.

Зачисляйте игроку ТОЛЬКО по completed (придёт вебхуком). awaiting_verification = чек ещё проверяется. cancelled сейчас относится к Pay-In, который клиент отменил на странице оплаты до загрузки чека.


7. Песочница (тесты)

Тестовый мерч в ЛК помечен 🧪 ТЕСТОВЫЙ РЕЖИМ: депозиты сразу получают тестовые реквизиты (встречная выплата создаётся автоматически), а завершить сделку можно кнопкой симуляции — вебхуки при этом настоящие. Тестовый трафик изолирован от боевого. Тестовый Bearer Token сохраните при выдаче; если он утрачен, перевыпустите его в ЛК → Настройки.


Вопросы по интеграции — на этапе подключения подскажем форматы и подпись.