django-click-uz
Django 5+ integration for the Click.uz Shop API: payment URLs, prepare/complete webhooks, MD5 signatures, optional audit log, replay protection, HTTPS and optional IP checks on callbacks.
| O‘zbekcha (batafsil) | README_UZ.md |
| Changelog | CHANGELOG.md |
| Repository | github.com/Matnazar-Matnazarov/django-click-uz |
| Extra docs (Markdown) | docs/ |
What’s in the package
| Part | Role |
|---|---|
click_uz |
Django app: add to INSTALLED_APPS, run migrations, include urls. Endpoints: prepare/, complete/, callback/, webhook/. Includes webhook_guard, ModelOrderHandler, signals, Uzbek locale/uz. |
click_up |
Compatibility imports only: ClickUp, ClickWebhook, unique_transaction_param. Do not add to INSTALLED_APPS. |
| Config | CLICK dict or flat CLICK_*; optional WEBHOOK_ALLOWED_CIDRS, WEBHOOK_REQUIRE_HTTPS, WEBHOOK_STRICT_IN_DEBUG. |
Requirements
- Python 3.12+
- Django 5.0+
Installation
pip install django-click-uz
# settings.py
INSTALLED_APPS = [
# ...
"django.contrib.contenttypes",
"django.contrib.auth",
"click_uz",
"orders", # your app with Order model
]
Configuration
Use either the CLICK dict or flat CLICK_* variables. If both are set, CLICK wins.
Option A — CLICK dict (recommended)
import os
CLICK = {
"SERVICE_ID": int(os.environ["CLICK_SERVICE_ID"]),
"MERCHANT_ID": int(os.environ["CLICK_MERCHANT_ID"]),
"SECRET_KEY": os.environ["CLICK_SECRET_KEY"],
# Optional Click user id for Merchant API; defaults to MERCHANT_ID if omitted
# "USER_ID": 12345,
"ACCOUNT_MODEL": "orders.Order",
"AMOUNT_FIELD": "amount",
"STATUS_FIELD": "status",
"STATUS_PENDING": "pending",
"STATUS_WAITING": "waiting_payment",
"STATUS_PAID": "paid",
"STATUS_CANCELLED": "cancelled",
"MERCHANT_TRANS_FIELD": "transaction_param",
"COMMISSION_PERCENT": 0,
"DISABLE_ADMIN": False,
"ENABLE_AUDIT": True,
# Production hardening (optional):
# "WEBHOOK_ALLOWED_CIDRS": ["203.0.113.0/24"],
# "WEBHOOK_STRICT_IN_DEBUG": True,
}
Option B — flat settings (legacy / click-pkg style)
CLICK_SERVICE_ID = 12345
CLICK_MERCHANT_ID = 67890
CLICK_SECRET_KEY = "your-secret-key"
CLICK_ACCOUNT_MODEL = "orders.Order"
CLICK_AMOUNT_FIELD = "amount"
CLICK_STATUS_FIELD = "status"
CLICK_MERCHANT_TRANS_FIELD = "transaction_param"
CLICK_COMMISSION_PERCENT = 0
CLICK_DISABLE_ADMIN = False
Webhooks require HANDLER_CLASS or ACCOUNT_MODEL + AMOUNT_FIELD + STATUS_FIELD.
Example: Order model
After prepare, the default handler sets status to waiting_payment; on success complete → paid; on rejection → cancelled. Align STATUS_* in CLICK with your choices.
# orders/models.py
from django.conf import settings
from django.db import models
class Order(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null=True,
blank=True,
)
amount = models.DecimalField(max_digits=12, decimal_places=2)
status = models.CharField(
max_length=32,
choices=[
("pending", "Pending"),
("waiting_payment", "Waiting payment"),
("paid", "Paid"),
("cancelled", "Cancelled"),
],
default="pending",
)
transaction_param = models.CharField(max_length=255, blank=True, default="")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self) -> str:
return f"Order {self.pk} — {self.amount}"
python manage.py makemigrations
python manage.py migrate
URLs
A) Include package routes (single webhook URL for the Click cabinet):
from django.urls import include, path
urlpatterns = [
path("payment/click/", include("click_uz.urls")),
]
Webhook example: https://your-domain.example/payment/click/webhook/
(same prefix: prepare/, complete/, callback/).
B) Custom path with your ClickWebhook subclass:
from django.urls import path
from orders.views import ClickWebhookAPIView
urlpatterns = [
path("payment/click/update/", ClickWebhookAPIView.as_view(), name="click-webhook"),
]
Register the full HTTPS URL in the Click merchant cabinet.
Views: webhook + pay link
Webhook subclass
params contains snapshot fields (id, merchant_trans_id, amount, state, …) and a nested payload with Click fields.
# orders/views.py
from click_up.views import ClickWebhook
from .models import Order
class ClickWebhookAPIView(ClickWebhook):
def successfully_payment(self, params):
order_id = params.get("id")
try:
order = Order.objects.get(pk=order_id)
# Model handler already set status to paid; add email, analytics, etc.
except Order.DoesNotExist:
pass
def cancelled_payment(self, params):
pass
def prepare_accepted(self, params):
"""Optional: runs after prepare succeeds."""
pass
Create order + payment link (simple — order PK as transaction_param)
import json
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from click_up import ClickUp
from .models import Order
@method_decorator(csrf_exempt, name="dispatch")
class CreateOrderView(View):
def post(self, request):
body = json.loads(request.body or "{}")
amount = body.get("amount")
order = Order.objects.create(
user=request.user if getattr(request, "user", None) and request.user.is_authenticated else None,
amount=amount,
)
paylink = ClickUp().initializer.generate_pay_link(
id=order.pk,
amount=order.amount,
return_url="https://example.com/orders/done/",
unique_transaction_id=False,
)
return JsonResponse({"order_id": order.pk, "payment_link": paylink})
Recommended: unique transaction_param per checkout
from click_up import ClickUp, unique_transaction_param
from .models import Order
tid = unique_transaction_param(order.pk)
order.transaction_param = tid
order.save(update_fields=["transaction_param"])
paylink = ClickUp().initializer.generate_pay_link(
id=order.pk,
amount=order.amount,
return_url="https://example.com/orders/done/",
transaction_param=tid,
)
Requires MERCHANT_TRANS_FIELD / CLICK_MERCHANT_TRANS_FIELD pointing at transaction_param (see configuration above).
Django REST Framework: same logic inside APIView.post, using request.data instead of json.loads.
Security & operations
- Callback JSON to Click stays in English; Django admin / config messages can use
click_uztranslations (locale/uz/). - MD5
sign_stringverification is the main authenticity check. click_uz.webhook_guard: enforce HTTPS in production; optionalWEBHOOK_ALLOWED_CIDRS. Behind a TLS-terminating proxy, setSECURE_PROXY_SSL_HEADER.
Documentation (local)
No hosted doc site is provided. To build the MkDocs site locally:
pip install -e ".[dev]"
# or: uv sync --all-extras
mkdocs serve
Open the URL printed in the terminal (usually http://127.0.0.1:8000).
Development
pip install -e ".[dev]"
pytest
Releases: bump version in pyproject.toml, update CHANGELOG.md, commit, then tag and push vX.Y.Z (e.g. v0.1.2) to trigger publish.yml. Each PyPI upload needs a new version.
vs older click-pkg tutorials
| Old tutorial | This package |
|---|---|
pip install click-pkg |
pip install django-click-uz |
INSTALLED_APPS: click_up |
Only click_uz |
is_test_mode |
Use Click test credentials / PAY_URL from Click docs if applicable |
License
MIT — see LICENSE.
Click API reference: docs.click.uz.
Metadata
Release files for django-click-uz 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_click_uz-0.1.2.tar.gz | 27.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_click_uz-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.3 kB
Release files / django_click_uz-0.1.2.tar.gz
| Download URL | django_click_uz-0.1.2.tar.gz |
|---|---|
| Size | 27.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
088b8506f4e82184128acf638fc630ac88cd4c61e65ed39037e2511b29e52b4a
|
|
BLAKE2b-256 checksum How to use checksums |
d0be79a934edfadd4069cacbb299c5263d560c4f882d4e1ea414f865a4354142
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 5, 2026.
Transparency logRelease files / django_click_uz-0.1.2-py3-none-any.whl
| Download URL | django_click_uz-0.1.2-py3-none-any.whl |
|---|---|
| Size | 29.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0fccc6ce14f4d4bb7ba5b4d587398459b7b0f3fb721266a63a8b8c882d07bb2d
|
|
BLAKE2b-256 checksum How to use checksums |
cbdf56c61e3fa81c930daac6e898e51e32a12e03442328a74e08e4f8388d777d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 5, 2026.
Transparency log