Документация

Типы доставки: что именно получает покупатель

У каждого товара есть deliveryType. Он отвечает на один вопрос — что вернётся, когда заказ выполнится, — и определяет, что вы обязаны собрать с покупателя до оформления. Ошибётесь — либо спросите данные, которые никому не нужны, либо пообещаете ключ, которого не будет.

Пять значений

deliveryTypeЧто получает покупательЧто передаёте вы
id_onlyОтдавать нечего — пополнение приходит на аккаунт.Игровой ID игрока (иногда ещё сервер).
gift_cardКлюч или код, который мы вернём при завершении.Обычно ничего.
login_requiredМы пополняем через указанный вами аккаунт.Данные аккаунта, которые требует схема.
serviceУслуга, выполняемая вручную.То, что требует схема.
otherТип ещё не определён — читайте схему товара.То, что требует схема.

Колонка nullable. Неклассифицированный SKU приходит с deliveryType: null, а не с other, и, поскольку каталожный фильтр сравнивает на точное равенство, ?deliveryType=other его не найдёт. Ваш собственный тип этого поля обязан допускать null, а полная синхронизация должна делать хотя бы один проход без фильтра.

Каким бы ни был тип, deliveryDataобязательный ключ в теле заказа. Если товару поля не нужны, передавайте пустой объект: отсутствие ключа — это ошибка валидации схемы, а не «пустой, но валидный» запрос.

Что нужно каждому типу

id_only

Игровой идентификатор покупателя — и ничего больше. Ключ не возвращается: у завершённой позиции id_only приходит cdKeys: [], и это финальный, правильный ответ. Это самая большая часть каталога — UC в PUBG Mobile, алмазы в Mobile Legends и Free Fire, кристаллы в Genshin Impact, — и та, где неверный ID стоит реальных денег: мы проверяем формат идентификатора, но никогда не проверяем, что такой аккаунт существует.

Всё про этот сценарий — id полей по играм, форматные правила, как выглядит выполненный заказ без ключей — на странице Прямое пополнение по API. Её стоит прочитать до того, как вы начнёте строить чекаут пополнений.

gift_card

Код, который покупатель активирует сам: подарочная карта платформы, карта игровой валюты, пополнение баланса магазина. Обычно у такого товара полей доставки нет вовсе, поэтому вы передаёте "deliveryData": {}.

Результат приходит в поле cdKeys у позиции заказа. Про этот массив важны две вещи:

  • Он заполняется только тогда, когда позиция в статусе completed. В любом другом статусе придёт [] — пустой массив означает «ещё нет», а не «ключей не будет».
  • В теле вебхука cdKeys есть только у товаров с ключом, поэтому получатель обязан одинаково трактовать отсутствующее поле и пустой массив.

Храните код зашифрованным, показывайте один раз и логируйте, кто его раскрыл. Это инструмент на предъявителя: кто прочитал — тот и активировал, из-за чего тикет поддержки с кодом внутри превращается в вечное обязательство.

login_required

Пополнение выполняется входом в аккаунт покупателя, поэтому схема просит учётные данные — логин, пароль, иногда регион или контрольный ответ.

Не ждите, что type поля подскажет, где секрет. В живом каталоге пароль приходит обычным текстовым полем, а называют его id и label{ "id": "password", "label": "Пароль", "required": true, "type": "text" }: один поставщик объявляет только text, number и select, второй сводит к text всё, что не select и не image. Решайте, что поле чувствительное, по его id и label, а не по type — ровно так же поступает и наш собственный классификатор, когда вообще помечает товар как login_required.

Считайте такие данные токсичными. Собирайте по TLS, не пускайте в логи приложения и в трекер ошибок, не храните после того, как заказ дошёл до терминального статуса, и попросите покупателя сменить пароль. Второй раз на нашей стороне они не понадобятся.

service

Позиция, выполняемая вручную: работу делает оператор, а не машина. Для вашего кода отсюда два следствия — это дольше, и статус позиции может проходить через состояния, которых автоматический SKU не показывает: awaiting_code или awaiting_screenshot. Код, который ждёт только completed или failed, зависнет на них навсегда, поэтому любой незнакомый статус трактуйте как «ещё в работе». Полный список статусов — на странице Заказы.

other и null

other — честная корзина «ни одно из перечисленного». null означает «ещё не классифицирован»: с вашей стороны ситуация та же, но значение другое, и в фильтре они невзаимозаменяемы.

Для обоих авторитет — deliveryDataSchema товара. Просит поля — собирайте; пустая — передавайте {}. Не стройте поведение на названии типа.

Читайте схему, а не эту страницу

deliveryDataSchema — это контракт на уровне товара. Ключи, которые вы передаёте, — это id каждого поля, а не его label; и любое значение должно быть строкой JSON: число без кавычек отбивается валидацией тела ещё до нашей собственной обработки ошибок.

type поляЧто означает
textСвободный текст. Форматные правила семейства игр всё равно могут применяться.
numberЧисловое; может объявлять диапазон.
selectЗначение должно точно совпадать с одним из объявленных вариантов.
imageЗагрузка файла — в этом API не поддерживается.
passwordПонимается, если поставщик когда-нибудь его пришлёт, но в живом каталоге его сегодня не отдаёт никто. Не ищите секрет по наличию этого типа.

Товары, объявляющие поле image, полностью исключены из B2B-каталога, а заказ по такому товару отбивается с 400. Если SKU, который виден в рознице, отсутствует в вашем фиде, причина обычно эта.

Раз type секрет не размечает, применяйте правило из login_required везде: считайте чувствительным любое поле, чьи id или label говорят об учётных данных — password, pass, pwd, пароль, — независимо от его type, и держите его вне логов, отчётов об ошибках и аналитики. На проводе секрет — обычная строка JSON; разница только в вашем обращении с ней.

Как строить форму у себя

Стройте форму из схемы в момент запроса, а не из таблицы, которую вы ведёте руками:

  1. Читайте deliveryDataSchema для того самого товара, который выбрал покупатель, — не для игры и не из вчерашнего кэша. У одного тайтла id полей могут отличаться между регионами и номиналами.
  2. Отрисуйте каждую запись, подставив label дословно на языке покупателя, и пометьте обязательные.
  3. Заставьте покупателя подтвердить всё, что идентифицирует аккаунт, до оплаты — и прямо скажите, что ошибка не возвращается.
  4. Отправьте собранные значения строками, с ключами по id.

Этот цикл одинаков для всех пяти типов — в этом и смысл: один рендерер, никакого ветвления по играм, и новая игра, которую поставщик добавит завтра, заработает без релиза с вашей стороны.

Нужен ключ API?

Напишите, какие игры и регионы вы продаёте, — выдадим ключ и пройдём интеграцию вместе с вами. На вопросы по интеграции отвечают те же люди, которые ведут API.