Новичку: если вы пишете свой сайт/бэкенд — берите SDK, а не «голый» HTTP. Так вы не ошибётесь в
подписи запроса (самый частый источник проблем на старте).
Какой SDK выбрать
Все SDK устроены одинаково — одни и те же понятия и почти одинаковые названия методов. Освоив один, вы сразу поймёте остальные.PHP
composer require oblodai/sdkTypeScript / Node.js
npm install @oblodai-npm/sdkPython
pip install oblodaiGo
go get github.com/oblodai/oblodai-goRust
cargo add oblodaiv1.1.0 — текущая версия в реестрах (Packagist · npm · PyPI · Go modules · crates.io).
Ломающее изменение против v1.0.x: идемпотентность переехала с авто-
order_id на заголовок
Idempotency-Key — см. принцип 3 и CHANGELOG вашего SDK. npm-пакет: @oblodai-npm/sdk.Что вам понадобится (для любого SDK)
public_idиsecret— пара ключей вашего мерчанта.public_id— несекретный идентификатор,secret— тайна, которой подписываются запросы. Один ключ на весь функционал (и приём, и выплаты). Ключи берутся в кабинете my.oblodai.com — см. Регистрация и ключи.- Сервер. SDK работает только на сервере (бэкенд). Секрет никогда не должен попадать в браузер или мобильное приложение.
- Публичный URL для вебхуков — адрес на вашем сервере, куда Oblodai будет присылать уведомления
об оплате (например
https://ваш-сайт.ру/oblodai/webhook).
Шесть принципов за минуту
Эти правила одинаковы во всех SDK — понимание их избавит от 90 % ошибок.-
Ключи — из переменных окружения. Не пишите секрет в коде. Задайте
OBLODAI_PUBLIC_IDиOBLODAI_SECRET, и создавайте клиента черезfromEnv()/from_env(). Базовый URL по умолчанию — боевойhttps://api.oblodai.com; переопределить можно переменнойOBLODAI_BASE_URL(необязательно). -
Суммы — строками.
"25.00", не число25.0. Так не теряется точность. -
Повтор безопасен — но защита от дублей устроена по-разному в двух версиях. Это главное отличие
v1.1.0 от v1.0.x.
- Ловушка при обновлении на v1.1.0. Если вы полагались на то, что
order_id«появится сам» в ответе, — теперь его там не будет. Задавайтеorder_idявно (см. следующий раздел). Сама защита от дублей при этом работает и без него — уже заголовком. order_id— это ВАШ бизнес-идентификатор, по которому вы потом находите платёж черезpayments.infoи сопоставляете со своим заказом. Ключом идемпотентности он быть перестал.- Выплаты:
order_idобязателен в обеих версиях — этого требует сам API (без него вернётсяpayout.order_id_required). Задавайте свой уникальный номер выплаты. - Ходите в API напрямую, без SDK? Тогда шлите заголовок
Idempotency-Keyсами (или полагайтесь наorder_id) — иначе повтор задублирует операцию. Подробно — Идемпотентность.
- Ловушка при обновлении на v1.1.0. Если вы полагались на то, что
-
Оплату подтверждает вебхук, а не редирект. Покупателя редиректит на «спасибо», но статус
заказа меняйте только получив вебхук (и перепроверив статус через
payments.info). - Вебхуки надо зарегистрировать. Один раз вызовите «регистрацию вебхука» — получите webhook-секрет и храните его. Именно им проверяются входящие уведомления (это НЕ ваш API-секрет). Без регистрации уведомления не приходят.
-
Валюта цены — это не валюта расчёта. Два разных поля, и их постоянно путают:
currency— валюта ЦЕНЫ. Может быть одной из 23 фиатных валют — USD, EUR, GBP, RUB, UAH, PLN, CZK, TRY, CNY, INR, BRL, CAD, AUD, CHF, AED, ZAR, MXN, IDR, THB, VND, NGN, JPY, KRW — или любой монетой (USDT, BTC, TRX, …). Указать цену в рублях или евро можно, и это надёжно: курс монеты приходит сразу в нужной валюте, ничего не перемножается.to_currency— валюта РАСЧЁТА. Здесь только крипта, фиата не бывает никогда. Баланс, выплаты и возвраты — тоже всегда в крипте: шлюз не хранит фиат.- У JPY и KRW ноль знаков после запятой:
"amount": "10000", а не"10000.00". У остальных — 2. - Тенге (KZT), сом (KGS), сум (UZS) пока не поддерживаются — вернётся
payment.unknown_currency. - Правило, о которое спотыкаются: цена в фиате + задана только
networkбезto_currency→400 payment.to_currency_required. Либо задайтеto_currency, либо не задавайте ни то, ни другое — тогда получится валюто-агностичный счёт и монету выберет сам покупатель.
rates.currencies()— в ответе полеpricing_currencies(монеты + фиат с признаком"fiat": true).
Как связать платёж со своим заказом
Всегда возвращаетсяuuid платежа — по нему платёж ищется через payments.info. Но удобнее искать
по своему order_id, поэтому задавайте его сами и сохраняйте до вызова:
Почему «до вызова». Если
create() бросит исключение (сеть отвалилась после того, как SDK
исчерпал повторы), ответа у вас не будет — и записать uuid будет неоткуда. Дубля при этом не
возникнет (все повторы шли с одним Idempotency-Key), но чтобы потом найти этот платёж, вам
нужен ключ, который вы придумали сами. Поэтому: сначала записали свой order_id, потом отправили.order_id из ответа:
Что нового в v1.1.0
- Массовые операции. До 5000 платежей / возвратов / выплат одним запросом — одна отметка
rate-limit вместо тысячи. Обработка в фоне: постановка возвращает
batch_id, результаты по каждому элементу забираются через «инфо о пачке». Есть режимon_error:continue(по умолчанию) илиstop(остановиться на первой ошибке). См. Массовые операции, Пачка, Инфо о пачке. - Платёжные ссылки (донаты). Переиспользуемая ссылка: по ней платят много людей, каждый платёж — свой инвойс со своим адресом. Сумма фиксированная, свободная или в диапазоне; валюту и сеть можно закрепить или дать выбрать клиенту; ссылка может быть бессрочной. Это единственный способ принимать платежи вообще без бэкенда (Tilda, Wix и т. п.). См. Платёжные ссылки, Ссылка, Публичный доступ к ссылке.
- Сплит-платежи. Доля каждого платежа автоматически уходит партнёру — на внешний адрес (необратимо) или аккаунту на платформе (обратимо: возврат отзовёт долю). См. предупреждение о возвратах ниже, Сплит-платежи, Правило сплита, Настройки сплита.
- Счёт на e-mail — письмо покупателю с кнопкой «Оплатить». Чек об оплате уходит автоматически на
payer_email, если вы задали его при создании платежа. См. Счета на e-mail, Отправка счёта. - Крипто-чеки (payout links) — выплата без адреса получателя: вы резервируете сумму,
получатель открывает
claim_urlи сам вводит свой адрес. Группаpayout_links/payoutLinks/PayoutLinks:create,create_batch(до 500 ссылок),list,info,cancel+ публичныеclaim_info/claim(без подписи). См. Крипто-чеки, Payout-ссылка, Публичный claim. - Резолв недоплаты —
payments.resolve(action=accept|refund): недоплаченный платёж можно принять как есть (accept, глушит авто-возврат) или вернуть плательщику (refund). См. Резолв платежа. - Новые поля платежа:
payer_address(откуда пришли деньги),refunds[]иrefund_status(none|partial|full). addressв возврате больше не обязателен — по умолчанию вернём на адрес плательщика. Для Bitcoin/UTXO, где адрес плательщика неизвестен,addressпо-прежнему нужен.
Сплиты и возвраты — прочитайте, прежде чем включать
Возврат списывается с вашего баланса на всю сумму, что прислал плательщик. Если бы доля партнёра уходила сразу, вам могло бы стать нечем возвращать. Поэтому отправка партнёрам откладывается на окно удержания (refund_hold_hours), и в момент
отправки база пересчитывается как «оплачено − возвращено». Возврат внутри окна сам уменьшает или
отменяет отчисление. Возврат после отправки: долю на внешний адрес вернуть нельзя (придётся
пополнить баланс), а долю партнёра-на-платформе мы отзовём автоматически.
Типичный сценарий приёма платежа
Одинаков во всех языках:Логи (диагностика)
Логирование во всех SDK выключено по умолчанию и включается одинаково — переменной окружения или своим логгером. Секреты (secret, X-Signature, webhook-секрет) и тела запросов не логируются
никогда — только метод, путь, HTTP-статус, время, номер попытки, задержка ретрая и код ошибки.
Самый простой способ — переменная окружения (значения debug · info · warn · error):
- TypeScript —
new OblodaiClient({ ..., logger: (level, msg, fields) => … }) - Python — стандартный
logging: настройте логгерlogging.getLogger("oblodai") - Go —
oblodai.Config{ ..., Logger: slog.Default() } - Rust —
Config::new(...).logger(Arc::new(|level, msg| …)) - PHP —
new Client($publicId, $secret, ['logger' => function (string $level, string $msg) { … }])
Лимиты частоты и повторы (встроено)
Все пять SDK сами переживают временные сбои, и повторы включены по умолчанию — отдельно настраивать ничего не нужно:- Что повторяется:
HTTP 429(лимит частоты) и5xx, а также сетевые сбои/таймауты. Ошибки запроса (4xx, кроме 429) не повторяются. Retry-After: на429шлюз присылаетRetry-After: 60— SDK ждёт именно столько; иначе — экспоненциальный backoff с джиттером.- Дефолты: до 4 попыток, старт 500 мс, потолок задержки 30 с. Настраивается через
RetryConfig/RetryOptions(или отключается) в конфиге клиента. - Лимит самого API — 120 запросов/мин на IP. Подробно — Ограничение частоты.
Go, внимание. Раньше в Go-SDK повторов по умолчанию не было (
Retry: nil означало «не
повторять») — из пяти библиотек ошибалась одна. Это исправлено: теперь nil = повторы включены,
как везде. Отключить их можно осознанно — Retry: oblodai.NoRetry().Куда дальше
Выберите язык из карточек выше и откройте его страницу — там установка, рабочий пример и все методы.Справочник API
Точные поля каждого метода API.
Глоссарий
Незнакомый термин — смотрите здесь.
Модули для CMS
Не пишете код — возьмите готовый модуль.