💳 pay-engine
pay-engine — O'zbekistonning asosiy to'lov tizimlarini (Payme, Click, Uzum Bank) birlashtiruvchi, xavfsiz to'lov havolalari yaratish, Telegram bot tugmalari hosil qilish, avtomatik yechish (auto-charge) hamda idempotent webhooklarni boshqarish imkonini beruvchi professional Python kutubxonasi.
🚀 Imkoniyatlar (Features)
- ⚡ 1 qatorlik to'lov havolalari: Payme, Click va Uzum Bank rasmiy havolalarini bir lahzada hosil qilish.
- 🤖 Telegram Botlar:
aiogramva boshqa botlar uchun to'lov tugmalari (payment_buttons). - 🛡️ Haqiqiy Idempotentlik: Takroriy so'rovlar kelganda (retry),
on_successqayta chaqirilmaydi. Bitta buyurtma ikki marta bajarilishidan 100% himoyalangan. - 💾 Doimiy saqlash (Persistent Storage): Tranzaksiyalarni ko'p workerli (gunicorn/uvicorn
--workers) tizimlarda saqlash uchun tayyorSQLiteStorageva kengaytiriladiganBaseStorage. - 🐍 Django & FastAPI integratsiyasi: Tayyor Class-Based View'lar (
PaymeWebhookView,ClickWebhookView,UzumWebhookView) va FastAPI routerlari (pay_router). - 🔄 Avtomatik yechish (Auto-charge): Payme Subscribe API (
X-Auth) va Click Merchant API (/card_token/payment) orqali karta tokenidan qayta to'lov yechish. - 🔒 Qat'iy xavfsizlik (Fail-closed): Kalitsiz so'rovlar mutlaqo qabul qilinmaydi. Timing-attack himoyasi (
hmac.compare_digest).
📦 O'rnatish (Installation)
pip install pay-engine
FastAPI, Django yoki Telegram bot bilan birga:
pip install "pay-engine[fastapi,django,telegram]"
⚙️ Sozlash (.env)
# Payme
PAYME_MERCHANT_ID=your_payme_merchant_id
PAYME_SECRET_KEY=your_payme_secret_key
PAYME_TEST_MODE=false
# Click
CLICK_SERVICE_ID=your_click_service_id
CLICK_MERCHANT_ID=your_click_merchant_id
CLICK_SECRET_KEY=your_click_secret_key
CLICK_MERCHANT_USER_ID=your_click_user_id
# Uzum Bank
UZUM_SHOP_ID=your_uzum_shop_id
UZUM_SECRET_KEY=your_uzum_secret_key
📖 Foydalanish (Quickstart)
1. To'lov havolasini olish (1 qatorda)
from pay_engine import payme, click, uzum
# Payme havolasi:
payme_url = payme.link(amount=100_000, order_id="ORDER_123")
# Click havolasi:
click_url = click.link(amount=100_000, order_id="ORDER_123")
# Uzum Bank havolasi:
uzum_url = uzum.link(amount=100_000, order_id="ORDER_123")
2. FastAPI da to'lovlarni qabul qilish (Webhook)
from fastapi import FastAPI
from pay_engine.integrations.fastapi import pay_router
from pay_engine import SQLiteStorage
app = FastAPI()
# Doimiy SQLite storage (server restart bo'lsa ham ma'lumotlar saqlanadi):
storage = SQLiteStorage("payments.db")
def check_order(order_id: str, amount: float) -> bool:
"""Buyurtma mavjudligi va summasini bazangizdan tekshiring."""
# Agar summa mos bo'lmasa yoki buyurtma topilmasa False qaytaring:
return True
async def on_success(order_id: str, amount: float):
"""Pul to'langanda faqat BIR MARTA chaqiriladi (idempotent)."""
print(f"✅ To'lov qabul qilindi: Buyurtma #{order_id}, Summa: {amount} so'm")
# /payments/payme, /payments/click, /payments/uzum ulanadi:
app.include_router(pay_router(
on_success=on_success,
check_order=check_order,
storage=storage
))
3. Django Loyihalarida foydalanish
views.py:
from pay_engine.integrations.django import PaymeWebhookView, ClickWebhookView
from pay_engine import SQLiteStorage
storage = SQLiteStorage("payments.db")
class MyPaymeView(PaymeWebhookView):
secret_key = "your_payme_secret"
storage = storage
def check_order(self, order_id: str, amount: float) -> bool:
# Bazadan buyurtmani tekshiring
return True
def on_success(self, order_id: str, amount: float):
# Buyurtmani to'landi deb belgilang
pass
def on_cancel(self, order_id: str, amount: float, reason):
# To'lov bekor qilinganda yoki refund bo'lganda
pass
urls.py:
from django.urls import path
from .views import MyPaymeView
urlpatterns = [
path("payments/payme/", MyPaymeView.as_view(), name="payme_webhook"),
]
4. Telegram Botda to'lov tugmalari (aiogram)
from aiogram import Bot, Dispatcher, types
from pay_engine.integrations.telegram import payment_buttons
bot = Bot(token="BOT_TOKEN")
dp = Dispatcher()
@dp.message(lambda msg: msg.text == "/tolov")
async def pay_command(message: types.Message):
keyboard = payment_buttons(amount=75_000, order_id=message.from_user.id)
await message.answer("To'lov usulini tanlang:", reply_markup=keyboard)
5. Avtomatik yechish (Card Token Auto-charge)
from pay_engine import payme, click
# Payme Subscribe API:
res_payme = payme.charge(
card_token="token_xyz",
amount=50_000,
order_id="SUB_101",
description="Oylik obuna"
)
# Click Merchant API:
res_click = click.charge(
card_token="token_xyz",
amount=50_000,
order_id="SUB_101"
)
🧪 Testlarni ishga tushirish
Barcha 34 ta integratsion va xavfsizlik testlarini ishga tushirish:
python -m unittest discover -s tests -p "test_*.py"
📄 Litsenziya
MIT License. Ochiq va bepul foydalanish mumkin!
Release files for pay-engine 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pay_engine-0.3.0.tar.gz | 28.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pay_engine-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 61.5 kB
Release files / pay_engine-0.3.0.tar.gz
| Download URL | pay_engine-0.3.0.tar.gz |
|---|---|
| Size | 28.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d0a512bdbb1a556acae42eaa1b9e9d338edebd36407648e4627119859815aa81
|
|
BLAKE2b-256 checksum How to use checksums |
e4055ef8b3315a54c70e5ec4155d58cdba87bfa60783b0155ba76c7313be58d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pay_engine-0.3.0-py3-none-any.whl
| Download URL | pay_engine-0.3.0-py3-none-any.whl |
|---|---|
| Size | 33.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ae03e1246188d8d3ad8eb126a6a05a1abdc1e014bd718dd4a9ee0617266976e1
|
|
BLAKE2b-256 checksum How to use checksums |
59d803b68718878f21037473cc51ecac918d4313cef42ac02d1f37a60e04ac57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|