Skip to Content
ИнтеграцияСправочник полей подписки

Справочник полей подписки и пользователя

Сводка типичных ошибок интеграции Merchant API и правильное использование полей. Основано на опыте production-интеграций.

Идентификаторы подписки

В ответах API у подписки два разных поля:

ПолеТипНазначение
subscriptionIdstring (sub20260703…)Используйте в APIupdate_submit, cancel, detail и т.д.
idnumberВнутренний числовой id записи в БД; не передавайте как subscriptionId
const { subscription } = await merchant.getSubscriptionUserSubscriptionDetail({ externalUserId: 'myapp-team-42', productId: 0, }) // ✓ правильно const subscriptionId = subscription!.subscriptionId! // ✗ ошибка «sub not found» // await merchant.subscriptionUpdateSubmit({ subscriptionId: String(subscription!.id), ... })

productId и planId

  • planId — id тарифного плана (например, 251 = free, 252 = paid).
  • productId — id продукта в каталоге. Системный продукт по умолчанию: 0.

productId: 0валидное значение. Не путайте с planId.

// ✓ для quota/resolve и user_subscription_detail с дефолтным продуктом await merchant.getQuotaResolve({ productId: 0, planId: 251 }) // ✗ в JS/TS: if (!productId) пропустит 0 if (productId != null) { /* … */ }

returnUrl и cancelUrl

Поля помечены в OpenAPI как optional, но условно обязательны, когда операция создаёт счёт на оплату.

ОперацияКогда нужен returnUrl
subscription/create_submittotalAmount > 0 (платный план)
subscription/update_submitАпгрейд с немедленным эффектом и totalAmount > 0 в preview

Рекомендуемый поток:

  1. Вызовите subscription/update_preview.
  2. Если totalAmount > 0 — передайте returnUrlcancelUrl) в update_submit.
  3. При paid === false перенаправьте пользователя на link из ответа.
  4. После возврата обновите подписку и обработайте вебхуки.

Ответ при необходимости оплаты:

{ "paid": false, "link": "https://payment-gateway.example/…", "subscriptionPendingUpdate": { } }

Если returnUrl не передан при обязательности, API может вернуть общую ошибку Server Error с requestId — сверяйте preview заранее.

В SDK есть проверка до вызова API:

import { assertReturnUrlForPaidOperation } from '@wilix/billbill-client-js' assertReturnUrlForPaidOperation(preview.totalAmount, { returnUrl })

gatewayId при создании подписки

gatewayId обязателен для subscription/create_submit, в том числе для бесплатных (0 ₽) планов. Без него — BaseGateway invalid.

Укажите id активного шлюза из админки (раздел «Платёжные шлюзы») или из merchant.get() / списка gateways.

Email и externalUserId

Один аккаунт на организацию

Типичный B2B/SaaS-паттерн:

  • externalUserId — стабильный ключ (myapp-team-{teamId}) для API и вебхуков.
  • email — контакт для счетов и чеков (email владельца команды или billing-контакт).

BillBill требует уникальный email на учётную запись пользователя.

Смена billing-email

МетодМеняет email в BillBill
userChangeEmailДа — используйте для обновления контакта для счетов
userUpdateНет — не меняет сохранённый email для биллинга
await merchant.userChangeEmail({ externalUserId: 'myapp-team-42', newEmail: 'new-billing@customer.example.com', })

При нескольких командах у одного человека допустимы plus-адреса (owner+team42@example.com).

Матрица сценариев (create / update)

EndpointСценарийКлючевые поля
subscription/create_submitFree (totalAmount = 0)planId, userId или email+externalUserId, gatewayId
subscription/create_submitPaid+ returnUrl, рекомендуется cancelUrl
subscription/update_submitDowngrade / без доплатыsubscriptionId, newPlanId, quantity
subscription/update_submitUpgrade с оплатой+ returnUrl, рекомендуется cancelUrl

Связанные страницы