Skip to main content

Несколько касс

У бизнеса часто несколько мерчант-аккаунтов у одного провайдера: боевая и sandbox-касса или отдельная касса на каждый бренд. Начиная с 0.5.0 каждый вебхук Django обслуживает их все на одном URL. Старые настройки с одной кассой работают без изменений.

Как вызов находит свою кассу​

Перечислите кассы в KASSAS. К какой кассе относится вызов, решают данные самого провайдера:

ШлюзВызов определяется по
Paymeключу в заголовке Basic auth (PAYME_KEY)
Clickservice_id в запросе, подписанному SECRET_KEY этой кассы
PaynetserviceId в запросе, иначе по логину (USERNAME)
Uzumлогину Basic auth (USERNAME); запрос обязан указать serviceId этой кассы

Вызов, не подошедший ни к одной кассе, отклоняется как неавторизованный.

Настройки​

PAYTECHUZ = {
'PAYME': {
'KASSAS': {
'shop': {'PAYME_ID': '...', 'PAYME_KEY': '...'},
'gifts': {'PAYME_ID': '...', 'PAYME_KEY': '...'},
},
'KASSA_FIELD': 'kassa', # необязательно, см. ниже
'ACCOUNT_MODEL': 'shop.models.Order',
'ACCOUNT_FIELD': 'id',
'AMOUNT_FIELD': 'amount',
'ONE_TIME_PAYMENT': True,
},
'CLICK': {
'KASSAS': {
'shop': {'SERVICE_ID': '...', 'SECRET_KEY': '...'},
},
# ACCOUNT_MODEL и остальное как выше
},
'PAYNET': {
'KASSAS': {
'live': {'SERVICE_ID': '1001', 'USERNAME': '...', 'PASSWORD': '...'},
'test': {'SERVICE_ID': '1003', 'USERNAME': '...', 'PASSWORD': '...',
'IS_SANDBOX': True},
},
},
'UZUM': {
'KASSAS': {
'shop': {'SERVICE_ID': '...', 'USERNAME': '...', 'PASSWORD': '...',
'ALLOWED_IPS': ['...']},
},
'IP_HEADER': 'HTTP_X_REAL_IP',
'BEHIND_CLOUDFLARE': True,
},
}

View не меняется: тот же наследник BasePaymeWebhookView на том же URL обслуживает все кассы. Внутри хука self.kassa — имя кассы, сделавшей вызов.

Раздельный учёт​

У каждой записи в таблице payments есть kassa, и каждый поиск ограничен кассой, сделавшей вызов. Одна касса не видит, не проводит, не отменяет и не включает в выписку транзакции другой, а один и тот же id транзакции провайдера может быть по одному разу в каждой кассе. У записей до 0.5 kassa = '' — именно это использует настройка с одной кассой.

Какая касса может оплатить заказ​

Укажите в KASSA_FIELD поле модели счёта, где хранится касса, через которую его нужно оплачивать. Вызову из другой кассы отвечают, что счёт не найден. Если значение в счетах отличается от ключа в KASSAS, кассе Paynet можно задать ACCOUNT_KASSA — удобно, когда sandbox- и боевой сервис делят одни счета.

Без KASSA_FIELD любая касса может оплатить любой счёт.

Sandbox-кассы​

Кассы Paynet и Uzum принимают IS_SANDBOX: True. Платежи сохраняются, но вместо successfully_payment вызывается sandbox_payment(params, transaction), то есть ничего не доставляется. Счёт остаётся доступным для оплаты тестером провайдера, а sandbox-записи не попадают в боевые выписки.

Перевод существующей настройки на KASSAS​

  1. Обновитесь и примените миграции: pip install "paytechuz[django]>=0.5", затем python manage.py migrate.
  2. У существующих записей kassa = ''. Перед переходом на KASSAS запишите в kassa каждой записи её новое имя, иначе новая касса их не увидит (для возвратов, проверок и выписок).
  3. Переключите настройки и задеплойте.

Откат на 0.4 на Django 5+ не требует обратной миграции: у колонки есть значение по умолчанию в базе, старый код её не замечает.