Несколько касс
У бизнеса часто несколько мерчант-аккаунтов у одного провайдера: боевая и sandbox-касса или отдельная касса на каждый бренд. Начиная с 0.5.0 каждый вебхук Django обслуживает их все на одном URL. Старые настройки с одной кассой работают без изменений.
Как вызов находит свою кассу
Перечислите кассы в KASSAS. К какой кассе относится вызов, решают данные
самого провайдера:
| Шлюз | Вызов определяется по |
|---|---|
| Payme | ключу в заголовке Basic auth (PAYME_KEY) |
| Click | service_id в запросе, подписанному SECRET_KEY этой кассы |
| Paynet | serviceId в запросе, иначе по логину (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
- Обновитесь и примените миграции:
pip install "paytechuz[django]>=0.5", затемpython manage.py migrate. - У существующих записей
kassa = ''. Перед переходом наKASSASзапишите вkassaкаждой записи её новое имя, иначе новая касса их не увидит (для возвратов, проверок и выписок). - Переключите настройки и задеплойте.
Откат на 0.4 на Django 5+ не требует обратной миграции: у колонки есть значение по умолчанию в базе, старый код её не замечает.