Paycue — to'lovlarni avtomatlashtirish uchun open source SaaS dastur. To'lov
tizimlariga integratsiya qilmasdan, Humo kartangizga tushgan to'lovlarni Telegram
orqali aniqlab, sizning API'ngizga webhook yuboradi.
Bitta server bir nechta foydalanuvchiga (multi-tenant) xizmat qiladi. Har bir foydalanuvchi API orqali ro'yxatdan o'tadi, o'z Telegram accountini ulaydi, cartalarini qo'shadi va webhook manzilini sozlaydi.
Savollar bo'lsa: @Azamov_Samandar
- Foydalanuvchi ro'yxatdan o'tadi → doimiy
tokenoladi (tasdiq talab qilinmaydi). - Telegram account ulaydi (API orqali: telefon → SMS kod → kerak bo'lsa 2FA parol).
Ulangach dastur avtomatik
@HUMOcardbotni topadi,/startbosilmagan bo'lsa bosadi va chatni kuzatadi. - Carta qo'shadi — cartaning oxirgi 4 raqami (
*7159) bo'yicha. - Webhook URL sozlaydi.
- To'lov kerak bo'lganda transaction yaratadi:
amount+card_idyuboradi, dastur o'sha carta uchun hozir band bo'lmagan summani qaytaradi (masalan20001). Increment har carta bo'yicha alohida hisoblanadi. - Kartaga shu summada pul tushganda dastur webhook orqali xabar beradi.
paycue— API server (Telegram watcher, worker, webhook).paycue-cli— API client (terminal). To'liq API orqali ishlaydi, dastur ichiga kirmaydi.
- Telegram account
- Humo telegram bot (@HUMOcardbot)
- Humo plastik kartasi
- Server
- Telegram
APP_IDvaAPP_HASH(my.telegram.org)
curl -fsSL https://raw.githubusercontent.com/UzStack/paycue/main/install.sh | sudo bashinstall.sh (Linux — server + CLI):
- o'rnatilmagan bo'lsa —
APP_ID/APP_HASHso'raydi,.envtayyorlaydi, oxirgi releasedan binarylarni yuklaydi, systemd servisini sozlaydi,paycue-clini o'rnatadi; - o'rnatilgan bo'lsa — binarylarni oxirgi releasega yangilab, servisni qayta ishga tushiradi.
Faqat paycue-clini o'rnatish (serversiz). macOS'da avtomatik shu rejim tanlanadi
(server systemd talab qiladi, macOS'da bu yo'q):
curl -fsSL https://raw.githubusercontent.com/UzStack/paycue/main/install.sh | sudo bash -s -- --cli-onlyServer Linuxda ishlaydi (SQLite/CGO). macOS uchun faqat CLI build qilinadi — u masofaviy serverga
--apiorqali ulanadi.
.env fayl (namuna .env.exampleda):
APP_ID=<app_id>
APP_HASH=<app_hash>
PORT=8080
DB_PATH=./db.sqlite3
SESSION_DIR=sessions
WORKERS=10
TRANSACTION_TIMEOUT=30
DEBUG=false
CORS_ORIGIN=*
WEB_DIR= # sozlansa, server shu papkadan web UI ni (SPA) xizmat qiladi
STATS_URL=https://paycue.uz # anonim statistika yuboriladigan kollektor
STATS_REPORT=true # anonim foydalanish statistikasini yuborish (false bilan o'chadi)
STATS_DASHBOARD=false # hisobotlarni qabul qilib UI'da ko'rsatish (default o'chiq)
WEB_DIRko'rsatilsa (masalan./web/dist), API va web UI bitta portda ishlaydi:/va dashboard yo'llari UI,/api/*va/health/esa API.install.shbuni avtomatik sozlaydi.
Telemetriya: har bir instance anonim foydalanish sanoqlarini (foydalanuvchi, account, carta, transaction, webhook log soni + versiya/OS)
STATS_URLga 6 soatda bir yuboradi. Hech qanday maxfiy ma'lumot (token, telefon, carta raqami, ism) yuborilmaydi.STATS_REPORT=falsebilan butunlay o'chiriladi.STATS_DASHBOARD=trueqilingan instance hisobotlarni qabul qiladi va dashboardda Statistika sahifasini ko'rsatadi (default o'chiq).
make build # bin/paycue va bin/paycue-cli
./bin/paycue # serverni ishga tushirishBu — dasturchi boshqaradigan to'liq API. paycue-cli ham aynan shu
endpointlarni chaqiradi, ya'ni CLI'dagi har bir buyruq quyidagi so'rovga teng.
Asoslar
- Base URL:
http://<host>:<PORT>(default port8080) - Format: so'rov va javob — JSON (
Content-Type: application/json) - Auth:
POST /api/registervaGET /health/dan tashqari hammasiAuthorization: Bearer <token>(yokiX-API-Key: <token>) talab qiladi - Javob qobig'i:
{ "status": bool, "data": object }. Xatodastatus=falsevadata.detailmatn bo'ladi (HTTP kodi: 400/401/403/404/5xx)
| Metod | Path | Auth | CLI ekvivalenti |
|---|---|---|---|
GET |
/health/ |
✗ | — |
POST |
/api/register |
✗ | register |
POST |
/api/login |
✗ | login |
GET |
/api/pay/{transaction_id} |
✗ | — (public to'lov sahifasi) |
POST |
/api/stats/report |
✗ | — (anonim telemetriya) |
GET |
/api/stats |
✓ | — (kollektor jamlanmasi) |
GET |
/api/webhook |
✓ | webhook (urlsiz) |
POST |
/api/webhook |
✓ | webhook --url |
GET |
/api/webhook/logs |
✓ | webhook logs |
POST |
/api/telegram/send-code |
✓ | telegram connect (1-qadam) |
POST |
/api/telegram/verify |
✓ | telegram connect (2-qadam) |
GET |
/api/telegram |
✓ | telegram list |
DELETE |
/api/telegram/{id} |
✓ | telegram delete |
POST |
/api/cards |
✓ | card add |
GET |
/api/cards |
✓ | card list |
DELETE |
/api/cards/{id} |
✓ | card delete |
POST |
/api/transactions |
✓ | transaction create |
GET |
/api/transactions |
✓ | transaction list |
DELETE |
/api/transactions/{id} |
✓ | transaction delete |
DELETE /api/telegram/{id}accountni, uning cartalarini va tranzaksiyalarini o'chiradi hamda kuzatuvni to'xtatib session faylini olib tashlaydi.DELETE /api/cards/{id}cartani va uning tranzaksiyalarini o'chiradi.
POST /api/register — ro'yxatdan o'tish, doimiy token oladi.
| Maydon | Tur | Majburiy | Izoh |
|---|---|---|---|
name |
string | ✓ | ism familiya |
email |
string | shartli | email yoki phone dan kamida bittasi |
phone |
string | shartli | — |
password |
string | ✗ | berilsa kamida 6 belgi (keyin login uchun). Berilmasa parolsiz account — faqat token bilan kiriladi |
Javob: { "id": int, "name": string, "token": string }
POST /api/login — email/phone + parol orqali tokenni qaytaradi.
| Maydon | Tur | Majburiy | Izoh |
|---|---|---|---|
login |
string | ✓ | email yoki phone |
password |
string | ✓ | bo'sh parol qabul qilinmaydi |
Javob: { "token": string }. Login/parol noto'g'ri bo'lsa yoki account parolsiz
ro'yxatdan o'tgan bo'lsa 401.
POST /api/webhook — webhook URL sozlash.
| Maydon | Tur | Majburiy |
|---|---|---|
url |
string | ✓ |
Javob: { "url": string, "secret": string } — secret keyin webhookda X-API-Key sifatida keladi.
POST /api/telegram/send-code — Telegram account ulashni boshlaydi (SMS kod yuboradi).
| Maydon | Tur | Majburiy |
|---|---|---|
phone |
string | ✓ |
Javob: { "telegram_account_id": int, "message": string }
POST /api/telegram/verify — kodni (kerak bo'lsa 2FA parolni) tasdiqlaydi.
| Maydon | Tur | Majburiy |
|---|---|---|
telegram_account_id |
int | ✓ |
code |
string | ✓ |
password |
string | 2FA yoqilgan bo'lsa |
Javob: 2FA kerak bo'lsa { "need_password": true }; aks holda { "telegram_account_id": int, "status": "active" }.
GET /api/telegram — accountlar ro'yxati. Javob: TelegramAccount[].
POST /api/cards — carta qo'shish.
| Maydon | Tur | Majburiy | Izoh |
|---|---|---|---|
telegram_account_id |
int | ✓ | siznikilardan biri |
number |
string | ✓ | to'liq carta raqami; oxirgi 4 raqam undan avtomatik ajratiladi |
owner_name |
string | ✗ | carta egasining ismi |
Javob: Card obyekti (last4 raqamdan ajratiladi — Telegram xabaridagi *7159 ga moslash uchun).
GET /api/cards — cartalar ro'yxati. Javob: Card[].
POST /api/transactions — to'lov uchun band bo'lmagan summa oladi.
| Maydon | Tur | Majburiy | Izoh |
|---|---|---|---|
amount |
int | ✓ | so'ralayotgan summa (musbat) |
card_id |
int | ✗ | siznikilardan biri; berilmasa avtomatik tanlanadi |
card_id berilmasa, dastur eng kam yuklangan cartani (hozir active transactioni
eng kam) avtomatik tanlaydi — bu summa farqini (drift) minimallashtiradi.
Javob: amount band bo'lmagan summa, va qaysi cartada yaratilgani:
// TelegramAccount
{ "id": 1, "user_id": 1, "phone": "+99890...", "tg_user_id": 123, "username": "ali", "status": "active", "created_at": "..." }
// status: "pending" (kod kutilmoqda) | "active" (ulangan)
// Card (last4 — number'dan avtomatik ajratiladi)
{ "id": 1, "telegram_account_id": 1, "number": "8600...7159", "last4": "7159", "owner_name": "Samandar", "created_at": "..." }Quyida har bir endpoint uchun curl misollari.
curl -X POST http://<host>:8080/api/register \
-H 'content-type: application/json' \
-d '{"name":"Ism Familiya","email":"pochta@example.com"}'
namemajburiy;phonedan kamida bittasi majburiy.passwordixtiyoriy — berilsa keyinloginqila olasiz, berilmasa faqat token bilan kirasiz. Javobda doimiytokenqaytadi.
curl -X POST http://<host>:8080/api/webhook \
-H "Authorization: Bearer <token>" \
-d '{"url":"https://example.com/hook"}'Javobda secret qaytadi — dastur webhook yuborganda uni X-API-Key headerda
yuboradi. Callback URL'ingizda shu kalitni tekshirib, so'rov haqiqatan paycue'dan
kelganini bilib oling.
API ikki qadamli (send-code → verify). CLI'da esa bu bitta telegram connect
buyrug'i — kodni va kerak bo'lsa 2FA parolni interaktiv so'raydi.
# 1) kod yuborish
curl -X POST http://<host>:8080/api/telegram/send-code \
-H "Authorization: Bearer <token>" -d '{"phone":"+99890..."}'
# -> { "telegram_account_id": 1 }
# 2) kodni tasdiqlash (2FA bo'lsa password qo'shing)
curl -X POST http://<host>:8080/api/telegram/verify \
-H "Authorization: Bearer <token>" \
-d '{"telegram_account_id":1,"code":"12345"}'
# 2FA kerak bo'lsa javob: { "need_password": true } -> password bilan qayta yuboringGET /api/telegram — accountlar ro'yxati.
curl -X POST http://<host>:8080/api/cards \
-H "Authorization: Bearer <token>" \
-d '{"telegram_account_id":1,"number":"8600 1234 5678 7159","owner_name":"Samandar"}'GET /api/cards — cartalar ro'yxati.
# card_id bilan (aniq carta):
curl -X POST http://<host>:8080/api/transactions \
-H "Authorization: Bearer <token>" \
-d '{"card_id":1,"amount":20000}'
# card_id'siz (eng kam yuklangan carta avtomatik tanlanadi):
curl -X POST http://<host>:8080/api/transactions \
-H "Authorization: Bearer <token>" \
-d '{"amount":20000}'{ "status": true, "data": { "amount": 20001, "card_id": 1, "transaction_id": "<uuid>", "pay_url": "https://<host>/pay/<uuid>" } }
amount— siz xohlagan summa; javobdagiamount— foydalanuvchidan so'raladigan (band bo'lmagan) summa. Increment har carta bo'yicha alohida hisoblanadi.
pay_url — to'lovchiga yuboriladigan public to'lov sahifasi havolasi. Unda
to'lov summasi, qaysi cartaga o'tkazish kerakligi, qolgan vaqt (countdown) va holat
ko'rinadi; to'lov tasdiqlangach sahifa avtomatik yangilanadi. Sahifa ma'lumotini
GET /api/pay/{transaction_id} (auth talab qilmaydi) qaytaradi: amount,
card_number, card_owner, state, expires_at, timeout_mins.
Kartaga to'lov tushganda yoki transaction bekor qilinganda dastur sizning URL'ingizga POST yuboradi:
{ "action": "confirm", "amount": 20001, "card_id": 1, "transaction_id": "<uuid>" }action: confirm (to'lov tushdi) yoki cancel (muddati o'tdi). Header'da
X-API-Key: <secret> bo'ladi. Callback URL { "ok": true } va 200 qaytarishi kerak,
aks holda dastur 3 marta qayta urinadi.
Har bir yetkazib berish natijasi (muvaffaqiyat, urinishlar soni, HTTP kodi, xato)
saqlanadi. GET /api/webhook/logs orqali ko'rinadi va dashboarddagi Webhook loglar
sahifasida chiqadi; transaction ro'yxatida ham har bir to'lov uchun webhook holati
(webhook_status) va urinishlar soni (webhook_attempts) ko'rsatiladi.
paycue-cli ni argumentsiz ishga tushirsangiz interaktiv menu (TUI) ochiladi —
menyularni strelka (↑/↓) bilan tanlab, Enter bilan tasdiqlaysiz (parol * bilan
yashiriladi):
paycue-cli # interaktiv menuHar bir amalni ikki xil ishlatish mumkin: interaktiv menu (TUI) yoki to'g'ridan-to'g'ri subcommand (skript/avtomatlashtirish uchun qulay):
paycue-cli register --name "Ism" --email pochta@example.com [--password "parol123"]
paycue-cli login --login pochta@example.com --password "parol123" # parol bilan ro'yxatdan o'tgan bo'lsa
paycue-cli webhook # joriy webhookni ko'rish
paycue-cli webhook --url https://example.com/hook # webhook sozlash
paycue-cli telegram connect --phone +99890... # interaktiv: kod va 2FA ni so'raydi
# yoki skriptbop (non-interaktiv) ikki qadam:
paycue-cli telegram send-code --phone +99890... # -> telegram_account_id
paycue-cli telegram verify --account 1 --code 12345 [--password 2FA]
paycue-cli telegram list
paycue-cli card add --account 1 --number "8600 1234 5678 7159" --owner "Samandar"
paycue-cli card list
paycue-cli transaction create --amount 20000 # carta avtomatik tanlanadi
paycue-cli transaction create --card 1 --amount 20000 # aniq carta
paycue-cli transaction list # holati bilan ro'yxat
paycue-cli transaction delete --id 5GET /api/transactions har bir transactionni carta ma'lumoti (to'liq card_number,
card_last4, card_owner) va hisoblangan state bilan qaytaradi:
state |
Ma'nosi |
|---|---|
active |
ochiq, to'lov kutilmoqda (timeout ichida) |
confirmed |
to'lov tushdi (webhook confirm) |
cancelled |
muddati o'tib bekor qilindi (cancel) |
expired |
muddati o'tgan, lekin close worker hali yopmagan |
CLI bir nechta paycue accountni profillar orqali boshqaradi. Har profil o'z
api + tokenini ~/.config/paycue/config.jsonda saqlaydi.
paycue-cli register --name "Ali" --email ali@x.com --profile ali # 'ali' profili
paycue-cli register --name "Vali" --phone +998... --profile vali # 'vali' profili
paycue-cli profile list # profillar (joriy * bilan belgilanadi)
paycue-cli profile current # joriy profil
paycue-cli profile token [ali] # profil tokenini chiqarish (default: joriy)
paycue-cli profile use ali # joriy profilni almashtirish
paycue-cli profile add boss --token <token> [--api URL] # tashqi token qo'shish
paycue-cli profile remove vali
# bitta buyruq uchun profilni almashtirmasdan tanlash:
paycue-cli --profile vali card listYechim tartibi (token/api uchun): --token/--api flag → tanlangan profil →
PAYCUE_TOKEN/PAYCUE_API env → default. Eski yagona ~/.config/paycue/token
fayli ilk ishga tushishda avtomatik default profilga ko'chiriladi.
- Transaction
TRANSACTION_TIMEOUTdaqiqa (default 30) active qoladi, keyin avtomatik bekor qilinadi. - Har Telegram account uchun alohida session
SESSION_DIRda saqlanadi. - Ko'p transactionda summa farqi o'sib boradi; buni kamaytirish uchun bir nechta carta/account ishlating.
Telegram accountni ulash xavfsizmi?— Ha, dastur open source, ma'lumotlar o'z serveringizda qoladi, session fayllari sizda saqlanadi.Yordam bera olamanmi?— Albatta, fork qiling va pull request yuboring.
{ "amount": 20001, "card_id": 1, "transaction_id": "<uuid>", "card": { "id": 1, "number": "8600...7159", "last4": "7159", "owner_name": "Samandar" } }