---
title: Django integratsiyasi
description: Django loyihasiga Payme, Click, Uzum, Paynet va Octo to'lov tizimlarini PayTechUZ orqali ulash: sozlamalar, modellar, webhook va callback.
source: https://pay-tech.uz/docs/integrations/django
---

# Django Integratsiyasi

Django ilovalariga PayTechUZ ni integratsiya qilish bo'yicha to'liq qo'llanma.

:::tip Tayyor misol loyihalar

Tayyor Django loyihalari kerakmi? Bizda turli to'lov stsenariylari uchun keng qamrovli misollar mavjud:

- **🛒 [Shop misoli](https://github.com/PayTechUz/Shop)** - **Buyurtmalar asosidagi to'lovlar** bilan to'liq elektron tijorat integratsiyasi (Payme, Click). Onlayn do'konlar va bozorlar uchun ideal.

- **🚕 [Taxi misoli](https://github.com/PayTechUz/Taxi)** - Payme, Click, Uzum, va Paynet yordamida **hamyon balansini to'ldirish**ning to'liq implementatsiyasi. Xizmat ilovalar, taksi xizmatlari va balansga asoslangan tizimlar uchun mos.

Ikkala misol ham to'liq Django sozlamasi, webhook handlerlari va ishlab chiqarish uchun tayyor kod bilan birga keladi!
:::

## O'rnatish

PayTechUZ ni Django qo'llab-quvvatlashi bilan o'rnating:

```bash
pip install paytechuz[django]
```

## Django Sozlamalari

Django sozlamalariga PayTechUZ konfiguratsiyasini qo'shing:

:::note
Sizga kerak bo'lmagan to'lov provayderlarining konfiguratsiyasini o'chirib yuborishingiz mumkin. Faqat loyihangizda foydalanmoqchi bo'lgan provayderlarni sozlang.
:::

```python
# settings.py

INSTALLED_APPS = [
    # ...
    'paytechuz.integrations.django',
]

PAYTECHUZ = {
    'PAYME': {
        'PAYME_ID': 'your_payme_id',
        'PAYME_KEY': 'your_payme_key',
        'ACCOUNT_MODEL': 'payment.models.Invoice',  #  Your invoice model
        'ACCOUNT_FIELD': 'id',
        'AMOUNT_FIELD': 'amount',
        'ONE_TIME_PAYMENT': True,
        'IS_TEST_MODE': True,  # Set to False in production
    },
    'CLICK': {
        'SERVICE_ID': 'your_service_id',
        'MERCHANT_ID': 'your_merchant_id',
        'MERCHANT_USER_ID': 'your_merchant_user_id',
        'SECRET_KEY': 'your_secret_key',
        'ACCOUNT_MODEL': 'payment.models.Invoice',
        'ACCOUNT_FIELD': 'id',
        'COMMISSION_PERCENT': 0.0,
        'ONE_TIME_PAYMENT': True,
        'IS_TEST_MODE': True,  # Set to False in production
    },
    'UZUM': {
        'SERVICE_ID': 'your_service_id',  # Biller URL uchun Uzum Service ID
        'USERNAME': 'your_uzum_username',  # Webhook Basic Auth uchun
        'PASSWORD': 'your_uzum_password',  # Webhook Basic Auth uchun
        'ACCOUNT_MODEL': 'payment.models.Invoice',
        'ACCOUNT_FIELD': 'id',  # yoki 'order_id'
        'AMOUNT_FIELD': 'amount',
        'ONE_TIME_PAYMENT': True, # Set to False if you want to allow multiple payments for the same invoice
        'IS_TEST_MODE': True,  # Production da False qilib belgilang
    },
    'PAYNET': {
        'SERVICE_ID': 'your_paynet_service_id',
        'USERNAME': 'your_paynet_username',
        'PASSWORD': 'your_paynet_password',
        'ACCOUNT_MODEL': 'payment.models.Invoice',
        'ACCOUNT_FIELD': 'id',
        'AMOUNT_FIELD': 'amount',
        'ONE_TIME_PAYMENT': True,
        'IS_TEST_MODE': True,
    },
    'OCTO_BANK': {
        'OCTO_SHOP_ID': 42125,  # Octo Shop ID
        'OCTO_SECRET': 'your_octo_secret',  # Octo Secret Key
        'OCTO_UNIQUE_KEY': 'your_octo_unique_key',  # Required in production
        'NOTIFY_URL': 'https://example.com/webhooks/octo/',  # Callback URL
        'ACCOUNT_MODEL': 'payment.models.Invoice',
        'ACCOUNT_FIELD': 'id',
        'AMOUNT_FIELD': 'amount',
        'ONE_TIME_PAYMENT': True,
        'TEST_MODE': True,
    }
}
```

:::warning Octo imzo tekshiruvi
`TEST_MODE: True` callback imzosini tekshirishni o'chiradi. Productionga
chiqishdan oldin uni `False` qiling va Octo jamoasi bergan `OCTO_UNIQUE_KEY`
ni kiriting — usiz webhook umuman ishga tushmaydi.
:::

Buyurtmalar va to'lovlarni boshqarish uchun modellar yarating:

```python
# shop/models.py
from django.db import models
from django.contrib.auth.models import User

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product_name = models.CharField(max_length=255)
    total_amount = models.DecimalField(max_digits=12, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Order {self.id} - {self.product_name}"

# payment/models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from shop.models import Order  # Import Order from shop app

class Invoice(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('paid', 'Paid'),
        ('cancelled', 'Cancelled'),
    )

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    created_at = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return f"Invoice {self.id} for Order {self.order.id}"
```

## Ko'rinishlar (Views)

To'lovlarni boshqarish uchun ko'rinishlar yarating:

:::note
Faqat foydalanayotgan to'lov provayderlaringiz uchun webhook ko'rinishlarini yaratishingiz kerak. Kerak bo'lmagan provayderlar uchun importlar va klasslarni o'chirib tashlang.
:::

```python
# payment/views.py
from paytechuz.integrations.django.views import (
    BasePaymeWebhookView,
    BaseClickWebhookView,
    BaseUzumWebhookView,
    BasePaynetWebhookView,
    BaseOctoWebhookView,
)

from payment.models import Invoice
from shop.models import Order

class PaymeWebhookView(BasePaymeWebhookView):
    def successfully_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'paid'
        invoice.save()

    def cancelled_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'cancelled'
        invoice.save()

    def get_check_data(self, params, account): # optional
        """
        Return additional data for CheckPerformTransaction (fiscal receipt)

        You can override this method to return additional data for fiscal receipt
        """
        return {
            "additional": {"first_name": account.user.first_name}, # optional
            "detail": { # optional
                "receipt_type": 0,
                "shipping": {"title": "Yetkazib berish", "price": 10000},
                "items": [
                    {
                        "discount": 0,
                        "title": account.product_name,
                        "price": account.amount,
                        "count": 1,
                        "code": "00001",
                        "units": 1,
                        "vat_percent": 0,
                        "package_code": "123456"
                    }
                ]
            }
        }

class ClickWebhookView(BaseClickWebhookView):
    def successfully_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'paid'
        invoice.save()

    def cancelled_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'cancelled'
        invoice.save()

    def successfully_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'paid'
        invoice.save()

    def cancelled_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'cancelled'
        invoice.save()

class UzumWebhookView(BaseUzumWebhookView):
    def successfully_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'paid'
        invoice.save()

    def cancelled_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'cancelled'
        invoice.save()

class PaynetWebhookView(BasePaynetWebhookView):
    def successfully_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'paid'
        invoice.save()

    def cancelled_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'cancelled'
        invoice.save()

    def get_check_data(self, params, account):  # ixtiyoriy
        # GetInformation uchun qo'shimcha ma'lumotlarni qaytarish
        # Istalgan kalit-qiymat juftliklaridan foydalanishingiz mumkin
        return {
            "fields": {
                "first_name": account.user.first_name,
                "balance": 0  # account.user.balance
            }
        }
class OctoWebhookView(BaseOctoWebhookView):
    def successfully_payment(self, params, transaction):
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'paid'
        invoice.save()

    def cancelled_payment(self, params, transaction):
        # Refund ham shu yerga tushadi: to'langan tranzaksiya cancelled bo'ladi
        invoice = Invoice.objects.get(id=transaction.account_id)
        invoice.status = 'cancelled'
        invoice.save()
```

## URL Yo'nalishlari

URL yo'nalishlarini sozlang:

:::note
Faqat foydalanayotgan to'lov provayderlaringiz uchun URL yo'nalishlarini qo'shing. Kerak bo'lmagan provayderlar uchun importlar va pathlarni o'chirib tashlang.
:::

```python
# urls.py
from django.urls import path
from payment.views import PaymeWebhookView, ClickWebhookView, UzumWebhookView, PaynetWebhookView, OctoWebhookView
from shop.views import OrderCreateView

urlpatterns = [
    # ...
    path('webhooks/payme/', PaymeWebhookView.as_view(), name='payme_webhook'),
    path('webhooks/click/', ClickWebhookView.as_view(), name='click_webhook'),
    path('webhooks/uzum/<str:action>/', UzumWebhookView.as_view(), name='uzum_webhook'),
    path('webhooks/paynet/', PaynetWebhookView.as_view(), name='paynet_webhook'),
    path('webhooks/octo/', OctoWebhookView.as_view(), name='octo_webhook'),
    
    # Order creation endpoint
    path('order/create/', OrderCreateView.as_view(), name='order_create'),
]
```


## To'lov Havolalarini Yaratish

Quyida **Django Rest Framework (DRF)** ko'rinishi misoli keltirilgan, u buyurtma yaratishni boshqaradi va tanlangan to'lov provayderi asosida to'lov havolasini generatsiya qiladi (serializerlardan foydalanmasdan):

:::note
Mantiqni faqat siz qo'llab-quvvatlamoqchi bo'lgan to'lov tizimlarini o'z ichiga oladigan qilib o'zgartiring. Foydalanilmayotgan tizimlar uchun importlar va `elif` bloklarini olib tashlang.
:::

```python
# shop/views.py
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from paytechuz.gateways.payme import PaymeGateway
from paytechuz.gateways.click import ClickGateway
from paytechuz.gateways.octo import OctoGateway
from payment.models import Invoice

class OrderCreateView(APIView):
    def post(self, request):
        data = request.data
        product_name = data.get('product_name')
        amount = data.get('amount')
        payment_type = data.get('payment_type')  # 'payme', 'click', 'uzum', 'paynet'

        if not all([product_name, amount, payment_type]):
            return Response(
                {'error': 'product_name, amount, and payment_type are required.'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 1. Create Order
        order = Order.objects.create(
            user=request.user,
            product_name=product_name,
            total_amount=amount
        )

        # 2. Create Invoice linked to the Order
        invoice = Invoice.objects.create(
            user=request.user,
            order=order,
            amount=amount,
            status='pending'
        )

        payment_url = None

        # 3. Generate Payment Link based on payment_type
        if payment_type == 'payme':
            gateway = PaymeGateway(
                payme_id=settings.PAYTECHUZ['PAYME']['PAYME_ID'],
                payme_key=settings.PAYTECHUZ['PAYME']['PAYME_KEY'],
                is_test_mode=settings.PAYTECHUZ['PAYME']['IS_TEST_MODE']
            )
            payment_url = gateway.create_payment(
                id=invoice.id,
                amount=invoice.amount,
                return_url="https://example.com/success",
                account_field_name=settings.PAYTECHUZ['PAYME']['ACCOUNT_FIELD']
            )

        elif payment_type == 'click':
            gateway = ClickGateway(
                service_id=settings.PAYTECHUZ['CLICK']['SERVICE_ID'],
                merchant_id=settings.PAYTECHUZ['CLICK']['MERCHANT_ID'],
                merchant_user_id=settings.PAYTECHUZ['CLICK']['MERCHANT_USER_ID'],
                secret_key=settings.PAYTECHUZ['CLICK']['SECRET_KEY'],
                is_test_mode=settings.PAYTECHUZ['CLICK']['IS_TEST_MODE']
            )
            payment_url = gateway.create_payment(
                id=invoice.id,
                amount=invoice.amount,
                return_url="https://example.com/success"
            )

            payment_url = gateway.create_payment(
                account_id=invoice.id,
                amount=invoice.amount,
            )

        elif payment_type == 'uzum':
            gateway = UzumGateway(
                service_id=settings.PAYTECHUZ['UZUM']['SERVICE_ID'],
                is_test_mode=settings.PAYTECHUZ['UZUM']['IS_TEST_MODE']
            )
            payment_url = gateway.create_payment(
                id=invoice.id,
                amount=invoice.amount,
                return_url="https://example.com/success"
            )

        elif payment_type == 'paynet':
            gateway = PaynetGateway(
                merchant_id='your_paynet_merchant_id',
                is_test_mode=settings.PAYTECHUZ['PAYNET']['IS_TEST_MODE']
            )
            # Paynet to'lov URL yaratish
            # URL formati: https://app.paynet.uz/?m={merchant_id}&c={payment_id}&a={amount}
            payment_url = gateway.create_payment(
                id=invoice.id,  # To'lov ID (c parametri)
                amount=invoice.amount  # tiyinda summa (ixtiyoriy, a parametri)
            )
            # Yoki summasiz (summa Paynet tomonida sozlanadi)
            # payment_url = gateway.create_payment(id=invoice.id)

        elif payment_type == 'octo':
            gateway = OctoGateway(
                octo_shop_id=settings.PAYTECHUZ['OCTO_BANK']['OCTO_SHOP_ID'],
                octo_secret=settings.PAYTECHUZ['OCTO_BANK']['OCTO_SECRET'],
                notify_url=settings.PAYTECHUZ['OCTO_BANK']['NOTIFY_URL'],
                is_test_mode=settings.PAYTECHUZ['OCTO_BANK']['TEST_MODE']
            )
            # Bir bosqichli to'lov (auto_capture), Octo checkout havolasini qaytaradi
            payment_url = gateway.create_payment(
                id=invoice.id,
                amount=invoice.amount,  # so'mda
                return_url="https://example.com/success",
                description=f"Invoice #{invoice.id}"
            )

        return Response({
            'order_id': order.id,
            'invoice_id': invoice.id,
            'payment_url': payment_url
        }, status=status.HTTP_201_CREATED)
```
