Billing API
Предупреждение
Экспериментальный функционал Личного Кабинета оператора внутри ТВ приложения. Визуальный интерфейс и API может быть изменен.
Изменения в документе
04.03.2025
Обновление модели tariff
:
добавлено обязательное поле
tms_id
добавлено опциональное поле
banner
, если не используется значение должно быть установлено как nullдобавлено опциональное поле
background_color
, если не используется значение должно быть установлено как nullдобавлено опциональное поле
benefits
, если не используется значение должно быть установлено как null или пустой массивудалено неиспользуемое поле
prepaid
из описания модели
Обновление описание модели SingleGroup
:
добавлены ранее используемые, но не документированные поля archiveSubscriptions, futureSubscriptions
Обновление описание модели MultiGroup
:
исправлена ошибка в описании модели (поле subscription исправлено на
subscriptions
)
Описание
Служит для реализации личного кабинета оператора внутри клиентских приложений, позволяет:
Ознакомиться с текущими условиями обслуживания
Изменить пароль доступа к Аккаунту
Переключить тарифный план
Оформить подписку на тарифный план
Отказаться от тарифного плана
На данный момент поддержка Billing API доступна только в мобильных приложениях.

Манипуляции с подписками могут быть ограничены. О том, как ограничиваются действия над тарифными планами, читайте ниже.
Billing API - это описание интерфейса взаимодействия пользовательского приложения с биллингом оператора.
Активация Billing API
Для включения Billing API необходимо:
Добавить
billing: true
в файл /opt/tvip-tms/gateway/gateway-tvip-tms-tvip-api/application-prod.yml;
...
features:
billing: true
...
В Web интерфейсе TMS в настройках Провайдера включить опцию Разрешить Биллинг, добавить Url и токен для доступа к биллингу;
Перезапустить сервис
systemctl restart gateway-tvip-tms-tvip-api
.
Переменные заголовков, доступные при запросе от TMS к биллингу оператора
X-TMS-ACCOUNT-ID
- Идентификатор аккаунта в TMS, запрос которого обрабатывается.
X-TMS-PROVIDER-ID
- Идентификатор провайдера (целое число), запрос которого обрабатывается.
Accept-Language
- Локаль клиентского приложения.
X-AUTH-TOKEN
- Подпись, определенная в настройках провайдера TMS. Формируется следующим образом:
private function createSign(Request $request):string{
$token = $request->getPathInfo();
$token = $token.$_ENV['TMS_TOKEN'];
if($request->headers->has('Content-Length') && $request->headers->get('Content-Length')>0){
$token = $token.$request->headers->get('Content-Length');
}
$md5 = md5($token);
return $md5;
}
Общие правила
Поля, содержащие дату и время, передаются в формате «Y-m-dTH:i:sO», к примеру: 2023-05-03T10:55:11+0000
Ответы на запросы к биллингу должны содержать корректные HTTP коды, к примеру, 200 для успешных запросов, 500 для ошибок на стороне сервиса.
Все запросы передаются TMS, TMS передает их в неизменном виде, добавляя заголовки
X-TMS-ACCOUNT-ID
,X-TMS-PROVIDER-ID
,X-AUTH-TOKEN
Вся бизнес-логика и обработка данных в биллинге и TMS находятся на стороне биллинга, а API выполняет лишь роль интерфейса для управления услугами из клиентского приложения.
Обрабатываемые URL, которые должны быть реализованы биллингом оператора
GET /api/cabinet - личный кабинет пользователя
POST /api/switch - смена тарифного плана
POST /api/subscribe - подписка на новый тарифный план
POST /api/unsubscribe - отказ от подписки
GET /api/tariff/{id} - детальное описание тарифа
POST /api/cabinet/password - смена пароля Аккаунта
GET /api/cabinet
{
"contacts":"string"
"account":{
"id": 1,
"fullname":"John Doe",
"balance": "10 $",
"enabled": true,
"account_credentials": "132379-2014-01-01"
},
"services":[
{
"type": "iptv",
"title": "Interactive TV",
"description" "TV with timeshift and catch-up"
"groups":[
{
"title": "Basic subscription",
"type": "SINGLE",
"offers":[
{
"from": "2023-06-01T00:00:00+0300",
"tariff":{
"id": 2,
"tms_id": 22,
"banner": null,
"name": "Standard channels",
"cost": "2 $",
"period": "monthly",
"description": "",
"channel_count": 150,
"background_color": "#000000",
"benefits": ["TOP 250","Cooking with masters"]
}
}
],
"subscription":{
"id": 19589,
"from": "2022-11-03T00:00:00+0300",
"to": null,
"cancel_date": null,
"tariff":{
"id": 1,
"tms_id": 11,
"banner": "http://example.com/banner.png",
"name": "Basic channels",
"cost": "1 $",
"period": "monthly",
"description": "",
"channel_count": 100,
"background_color": null,
"benefits": null
}
},
"archiveSubscriptions":[],
"futureSubscriptions":[],
},
{
"title": "Premium packages",
"type": "MULTI",
"offers":[],
"subscriptions":[]
}
]
}
]
}
Объект cabinet
содержит следующие поля:
- cabinet.contacts:
Строка, к примеру, там может быть адрес электронной почты службы поддержки или телефон.
- cabinet.account:
Объект аккаунт содержит информацию о абоненте: Имя заключившего контракт, реквизиты контракта, текущий баланс, флаг
enabled
указывает включены ли услуги у абонента.- cabinet.services:
Массив услуг, которыми можно управлять через Личный Кабинет в приложении, на данный момент поддерживается только
type
iptv.- service.groups:
Сервис содержит в себе группы (
groups
), которые, в свою очередь, могут иметьtype
:SINGLE - для тарифных планов, которые могут заменять друг друга и не могут быть включены одновременно, к примеру, «Базовый тариф» и «Расширенный тариф».
MULTI - для тарифных планов, подписки на которые могут быть оформлены одновременно, как правило, это тарифы с фильмовыми или спортивными каналами.
- group.offers:
Общее для обоих типов групп поле, содержит в себе предложения для подписки или перехода (для типа SINGLE) на тарифные планы:
from
- дата с которой предложено оформить подписку (изменить подписку)tariff
- тариф, на который предложено оформить подписку
- group.subscription:
Специфичное поле для типа SINGLE группы, может быть
null
либо отражает текущую подписку:id
- идентификатор подписки, данный идентификатор используется как аргумент в методах отписки и смены подпискиfrom
- дата начала действия подпискиto
- дата окончания действия подписки, null - конечная дата не определенаcancel_date
- дата, с которой возможно окончание подписки (отписка), если установлено null - отменить подписку через ЛК не получится.tariff
- описание тарифного плана, на который оформлена подписка
- group.subscriptions:
Специфичное поле для типа MULTI группы, массив подписок, имеет ту же структуру что и для SINGLE группы
- group.archiveSubscriptions:
Массив прошедших подписок, специфично для SINGLE групп
- group.futureSubscriptions:
Массив запланированных изменений в подписке, позволяет отменить запланированную подписку
- tariff:
Объект тарифа, описывает свойства тарифного плана:
id
- идентификатор тарифа в биллинге, используется при методах подпискиtms_id
- целочисленное поле, идентификатор тарифа в TMSbanner
- баннер для тарифа, необязательное поле, ссылка на картинку размерами 1020px x 640pxname
- название тарифного плана.cost
- стоимость тарифного плана, это простая строка, допустимо использование принятых обозначений для региона предоставления услуг, к примеру «20 EUR» или «$ 20».period
- биллинговый период услуги, используйте формулировки понятные абоненту, к примеру «в день», «в год».description
- описание тарифного плана, опишите особенности или опишите преимущества.channel_count
- целочисленное поле, укажите количество каналов в тарифном плане.background_color
- цвет карточки, если не задан то приложение сгенерирует цвет автоматически.benefits
- массив строк, рекламирующих тарифный план, общая количество символов не более 70, количество символов отдельной строки не более 35 символов. Null или пустой массив трактуется как незаданный параметр
Примечание
Рекомендации оформления
Цвет background_color
:
Допустимо использовать любой цвет, но учитывать, что текст всегда белый.
Избегать слишком ярких или слишком светлых цветов.
Текст benefits
:
Максимальная длина одного бенефита – до 35 символов.
Общее количество символов во всех бенефитах – не более 70 символов.
Описание тарифа:
name
(заголовок тарифа): до 45 символов.description
: до 300 символов.
Оформление banner
Размер баннера: 1020×640 px.
Баннер, размещённый в карточке тарифа, дублируется на страницу с описанием тарифа.
POST /api/switch
Модель запроса к серверу
{
"subscription_id": 19589,
"tariff_id": 2,
"from": "2023-06-01T00:00:00+0300"
}
Метод изменения подписки, используется только для SINGLE групп, приложение формирует запрос, исходя из выбранного offer
:
subscription_id
- идентификатор изменяемой подписки
tariff_id
- идентификатор тарифа в выбранном абонентомoffer
from
- дата изменения тарифного плана в подписке, указанная в выбранном абонентомoffer
Модель ответа от сервера
{
"status": 200,
"message": null,
"subscription": {
"id": 19589,
"from": "2023-06-01T00:00:00+0300",
"to": null,
"cancel_date": null,
"tariff":{
"id": 2,
"tms_id": 22,
"banner": null,
"name": "Standard channels",
"cost": "2 $",
"period": "monthly",
"description": "",
"channel_count": 150,
"background_color": null,
"benefits": null
}
}
}
Поля ответа
status
- код ответа 200 должен быть установлен в случае корректного выполнения запроса, в остальных случаях следует указать 500.
message
- сообщение абоненту, на данный момент не используется.
subscription
- модель сформированной подписки (group.subscription
)
Примечание
На данный момент обрабатывается только HTTP код. HTTP код ответа должен быть 200 в случае, если запрос выполнен без ошибок. HTTP код ответа 500 в случае если запрос не выполнен.
POST /api/subscribe
Модель запроса к серверу
{
"tariff_id": 2,
"from": "2023-06-01T00:00:00+0300"
}
Оформление новой подписки в группе:
tariff_id
- идентификатор тарифа в выбранном абонентомoffer
from
- дата изменения тарифного плана в подписке, указанная в выбранном абонентомoffer
Модель ответа от сервера
{
"status": 200,
"message": null,
"subscription": {
"id": 19589,
"from": "2023-06-01T00:00:00+0300",
"to": null,
"cancel_date": null,
"tariff":{
"id" 2,
"tms_id:" 22,
"banner": null,
"name": "Standard channels",
"cost": "2 $",
"period": "monthly",
"description": "",
"channel_count": 150,
"background_color": null,
"benefits": null
}
}
}
Поля ответа
status
- код ответа 200 должен быть установлен в случае корректного выполнения запроса, в остальных случаях следует указать 500.
message
- сообщение абоненту, на данный момент не используется.
subscription
- модель сформированной подписки (group.subscription
)
Примечание
На данный момент обрабатывается только HTTP код. HTTP код ответа должен быть 200 в случае, если запрос выполнен без ошибок. HTTP код ответа 500 в случае если запрос не выполнен.
POST /api/unsubscribe
Модель запроса к серверу
{
"subscription_id": 100,
"to": "2023-07-01T00:00:00+0300"
}
Отказ от подписки возможен только в случае, если определено поле subscription.cancel_date
, в этом случае клиенту будет доступна кнопка, которая сформирует запрос:
subscription_id
- идентификатор подписки
to
- дата окончания подписки
Модель ответа от сервера
{
"status": 200,
"message": null,
"subscription": {
"id": 100,
"from": "2023-06-01T00:00:00+0300",
"to": "2023-07-01T00:00:00+0300",
"cancel_date": null,
"tariff":{
"id": 2,
"tms_id": 22,
"banner": null,
"name": "Standard channels",
"cost": "2 $",
"period": "monthly",
"description": "",
"channel_count": 150,
"background_color": null,
"benefits": null
}
}
}
Поля ответа:
status
- код ответа 200 должен быть установлен в случае корректного выполнения запроса, в остальных случаях следует указать 500.
message
- сообщение абоненту, на данный момент не используется.
subscription
- модель измененной подписки (group.subscription
)
Примечание
На данный момент обрабатывается только HTTP код. HTTP код ответа должен быть 200 в случае, если запрос выполнен без ошибок. HTTP код ответа 500 в случае если запрос не выполнен.
GET /api/tariff/{id}
Запрос детализации тарифного плана с идентификатором {id}
Модель ответа от сервера
{
"tariff": {
"id": 10,
"tms_id": 22,
"banner": null,
"name": "Amedia Premium",
"cost": "99 $",
"period": "monthly",
"description": "",
"channel_count": 1,
"background_color": null,
"benefits": null
},
"channels": [
{
"name": "Amedia Premium HD",
"logo_url": "https://example.com/logo.png",
"description": "",
"number": 322,
"categories": [
2,
3
]
}
],
"categories": {
"1": "News",
"2": "Movies",
"3": "HD Channels",
}
}
Поля ответа:
tariff
- модель тарифа, описана выше.channels
- массив каналов, входящий в тарифный план.categories
- справочник категорий.
POST /api/cabinet/password
Метод изменения пароля от учетной записи Абонента в TMS
Модель запроса к серверу
{
"old_password": "0512f08120c4fef707bd5e2259c537d0"
"password": "5f4dcc3b5aa765d61d8327deb882cf99"
}
Описание полей:
old_password
- текущий пароль, введенный пользователем.
password
- новый пароль, введенный пользователем.
Ваш бекенд, опираясь на переданные данные, должен поменять пароль или отказать в смене пароля
Модель ответа от сервера
{
"status": 200,
"message": null,
}
Описание полей:
status
- 200 в случае смены пароля, 500 в остальных случаях.
message
- сообщение абоненту, на данный момент не используется.
Примечание
На данный момент обрабатывается только HTTP код. HTTP код ответа должен быть 200 в случае, если запрос выполнен без ошибок. HTTP код ответа 500 в случае если запрос не выполнен.
Описание моделей
Cabinet
Property |
type |
nullable |
---|---|---|
contacts |
string |
no |
account |
Account model |
no |
services |
Service[] |
no |
Account model
Property |
type |
nullable |
---|---|---|
id |
int |
no |
fullname |
String |
no |
balance |
String |
yes |
enabled |
bool |
no |
account_credentials |
String |
yes |
Service model
Property |
type |
nullable |
---|---|---|
type |
String |
no |
title |
String |
no |
description |
String |
yes |
groups |
GroupInterface[] |
no |
GroupInterface
Property |
type |
nullable |
---|---|---|
title |
String |
no |
type |
const: SINGLE |
no |
offers |
Offer[] |
no |
subscription |
Subscription |
yes |
archiveSubscriptions |
Subscription[] |
no, empty or filled array required |
futureSubscriptions |
Subscription[] |
no, empty or filled array required |
Property |
type |
nullable |
---|---|---|
title |
String |
no |
type |
const: MULTI |
no |
offers |
Offer[] |
no |
subscriptions |
Subscription[] |
no, empty or filled array required |
TariffInterface
Property |
type |
nullable |
---|---|---|
id |
int |
no |
tms_id |
int |
no |
banner |
string |
yes |
background_color |
string |
yes |
benefits |
string[] |
yes |
name |
String |
no |
cost |
String |
no |
description |
String |
yes |
channel_count |
int |
no |
Offer
Property |
type |
nullable |
---|---|---|
tariff |
TariffInterface |
no |
from |
String |
no |
Subscription
Property |
type |
nullable |
---|---|---|
id |
int |
no |
from |
String |
no |
to |
String |
yes |
cancel_date |
String |
yes |
tarif |
TariffInterface |
no |