---
title: Bir nechta kassa
description: PayTechUZ 0.5 bilan bitta Django webhook URL'da bir nechta Payme, Click, Paynet yoki Uzum kassasini ishlatish — alohida hisob, sandbox kassalar va kassa tekshiruvi.
source: https://pay-tech.uz/docs/integrations/multiple-kassas
---

# Bir nechta kassa

Biznesda ko'pincha bitta provayderda bir nechta merchant hisobi bo'ladi: jonli
va sandbox kassa yoki har brend uchun alohida kassa. **0.5.0** dan boshlab har
bir Django webhook ularning hammasini bitta URL'da qabul qiladi. Bitta kassali
eski sozlamalar o'zgarishsiz ishlayveradi.

## Murojaat o'z kassasini qanday topadi

Kassalarni `KASSAS` ichida sanab chiqing. Murojaat qaysi kassaga tegishli
ekanini provayderning o'z ma'lumotlari hal qiladi:

| Gateway | Murojaat nimaga qarab tanlanadi |
| --- | --- |
| Payme | Basic auth sarlavhasidagi kalit (`PAYME_KEY`) |
| Click | so'rovdagi `service_id`, shu kassaning `SECRET_KEY` bilan imzolangan |
| Paynet | so'rovdagi `serviceId`, bo'lmasa login (`USERNAME`) |
| Uzum | Basic auth login (`USERNAME`); so'rov shu kassaning `serviceId` sini ko'rsatishi shart |

Hech bir kassaga mos kelmagan murojaat avtorizatsiyadan o'tmagan deb rad
etiladi.

## Sozlamalar

```python
PAYTECHUZ = {
    'PAYME': {
        'KASSAS': {
            'shop':  {'PAYME_ID': '...', 'PAYME_KEY': '...'},
            'gifts': {'PAYME_ID': '...', 'PAYME_KEY': '...'},
        },
        'KASSA_FIELD': 'kassa',          # ixtiyoriy, quyida
        'ACCOUNT_MODEL': 'shop.models.Order',
        'ACCOUNT_FIELD': 'id',
        'AMOUNT_FIELD': 'amount',
        'ONE_TIME_PAYMENT': True,
    },
    'CLICK': {
        'KASSAS': {
            'shop': {'SERVICE_ID': '...', 'SECRET_KEY': '...'},
        },
        # ACCOUNT_MODEL va boshqalar yuqoridagidek
    },
    '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 o'zgarmaydi: bitta URL'dagi o'sha `BasePaymeWebhookView` vorisi hamma
kassaga xizmat qiladi. Hook ichida `self.kassa` — murojaat qilgan kassaning
nomi.

## Alohida hisob

`payments` jadvalidagi har qatorda `kassa` bor va har bir qidiruv murojaat
qilgan kassa bilan cheklanadi. Bir kassa boshqasining tranzaksiyalarini
ko'rmaydi, o'tkazmaydi, bekor qilmaydi va hisobotiga qo'shmaydi; provayderning
bitta tranzaksiya id si har kassada bir martadan bo'lishi mumkin. 0.5 dan
oldingi qatorlarda `kassa = ''` — bitta kassali sozlama aynan shuni ishlatadi.

## Buyurtmani qaysi kassa to'lashi mumkin

`KASSA_FIELD` ga account modelingizdagi, hisob qaysi kassa orqali to'lanishi
kerakligini saqlaydigan maydon nomini bering. Boshqa kassadan kelgan murojaatga
hisob topilmadi deb javob beriladi. Agar hisoblardagi qiymat `KASSAS`
dagi kalitdan farq qilsa, Paynet kassasiga `ACCOUNT_KASSA` berish mumkin —
sandbox va jonli servis bitta hisoblarni ishlatganda qulay.

`KASSA_FIELD` bo'lmasa, istalgan kassa istalgan hisobni to'lay oladi.

## Sandbox kassalar

Paynet va Uzum kassalari `IS_SANDBOX: True` ni qabul qiladi. To'lovlar
yoziladi, lekin `successfully_payment` o'rniga
`sandbox_payment(params, transaction)` chaqiriladi, ya'ni hech narsa
yetkazilmaydi. Hisob provayder testeri uchun to'lanadigan holatda qoladi,
sandbox qatorlari jonli hisobotlarga kirmaydi.

## Mavjud sozlamani `KASSAS` ga o'tkazish

1. Yangilang va migratsiya qiling: `pip install "paytechuz[django]>=0.5"`,
   so'ng `python manage.py migrate`.
2. Mavjud qatorlarda `kassa = ''`. `KASSAS` ga o'tishdan oldin har qatorning
   `kassa` siga uning yangi nomini yozing, aks holda yangi kassa ularni
   (qaytarish, tekshirish va hisobot uchun) ko'rmaydi.
3. Sozlamalarni almashtiring va deploy qiling.

Django 5+ da 0.4 ga qaytish uchun teskari migratsiya kerak emas: ustunning
bazaviy default qiymati bor, eski kod uni e'tiborsiz qoldiradi.
