Биллинг¶
К кому идти: @itjune, @art, @dmitriyt Со стороны Биллинга: @halty, @quark, @buxxter
С Биллинговым API (XMLRPC) мы работаем через клиент yandex_directory.common.billing.client.BillingClient
.
Директория обеспечивает сбор и отправку в Биллинг данных по потребленным услугам для всех смежных сервисов.
Платный режим¶
На платный тариф могут перейти как физические, так и юридичекие лица. Физические лица работают только по оферте, а юридические по оферте и договору.
Как выглядит переход на платный режим пошагово, после нажатия пользователем кнопки “перейти на платный режим”:
Создать клиента для организации в Биллинге
Создать плательщика в Биллинге
Создать оферту или договор в биллинге для нашего плательщика
Записать в нашу базу данные о клиенте и плательщике (
OrganizationBillingInfoModel
)
После чего включается платный режим самой организации (Коннекта): subscription_plan: paid
или какие-нибудь платные сервисы.
Клиент в биллинге - это наша организация. Плательщик - набор реквизитов, привязан к клиенту. Представитель клиента - человек, который может платить и смотреть заказы с актами на balance.yandex.ru
(это еще не запущено)
Если пользователь - юр. лицо и хочет договор, то механизм включения платного режима немного отличается.
Оферта принимается сразу, а договор пользователю необходимо подписать. Поэтому мы должны сформировать договор в виде PDF, пользователь его скачает,
подпишет и оправит нам обратно.
После проверки нашим бэкофисом, договор подписывается со стороны Яндекса. Для нас это выглядит так: с самого начала
после создания договора он находится в неактивном статусе. Мы периодически по крону проверяем его (check_inactive_contracts.py
)
и в случае если договор стал активным - включаем платный режим в организации.
Подсчет потребленных продуктов¶
Вкратце, для того чтобы Биллинг начал списывать деньги с наших клиентов (организаций), мы должны сложить в специальные дневные таблицы в YT данные в виде:
client_id |
product_id |
quantity |
---|---|---|
… |
… |
… |
Для этого каждую ночь в таске save_billing_data_to_yt
по крону выполняется подсчет потребленных платными организациями услуг.
По самому коннекту мы считаем сколько активных пользователей было в этот день, а по всем лицензионным сервисам - количество лицензий.
Также, мы считаем все потребленные продукты в момент выключения платного режима в организации.
С лицензиями все немного сложнее. :) Мы каждую ночь складываем в специальную таблицу organizations_license_consumed_info
список всех текущих лицензий по сервисам. При каждом их изменении в таблицу дописываются данные (но не удаляются). Таким образом
в ней у нас хранится полный список пользователей, имевших доступ к этому сервису за любой день.
На следующую ночь из этой таблицы данные перекладываются в organizations_billing_consumed_info
.
При этом продукт для каждого сервиса высчитывается динамически, например с учетом примененного промокода.
Список цен представляет собой словарь, ключи которого - количество пользователей, значения - id продуктов:
{
1: 100,
2: 200,
3: 300
}
product_id выбирается по следующей логике: находим в ключах словаря максимально близкое число к нашему количеству пользователей. Это и будет ключ, значение по которому - наш product_id, его и нужно складывать в биллинг в YT.
После подсчета потребленных продуктов нам нужно сложить их в YT. Складываем мы в два кластера (hahn и banach), на всякий случай, если вдруг один будет лежать. Отправляем мы всё транзакционно, т.е. либо все данные из базы легли в один из кластеров, либо ничего не создалось. Биллинг читает только из одного кластера (hahn), переключается вручную при необходимости.
Оплата¶
Чтобы пользователь мог оплатить, его нужно сначала сделать представителем клиента.
Процесс оплаты (get_url_for_paying
), допустим пользователь хочет положить на счет N рублей:
Проверяем что организация действительно платная
Делаем пользователя представителем клиента
Создаем в биллинге заказ на N продуктов стоимостью в 1 руб.
Получаем ссылку на оплату этого заказа
Пользователь уходит в Биллинг по ссылке и пополняет лицевой счет.
Тестинг¶
В тестинге Биллинг использует продакшеновые uid-ы, а мы - тестовые. Поэтому у нас есть специальный клиент BillingClientWithUidReplacement
,
который умеет подменять uid-ы из под которых мы ходим в биллинг.
Плюс надо помнить, что периодически Биллинг переливает продакшен базу в тестинг, поэтому в тестинге данные могут теряться. Наш QA ходит в продакшен Биллинга.