API hujjatlari · v1
.md yuklab olish Panel

CardHook API

Versiya: v1 Oxirgi yangilanish: 2026-09-22

CardHook — Humo va Uzcard kartalariga kelgan o'tkazmalarni avtomatik aniqlab, ularni buyurtmalaringizga bog'laydigan servis. Bu hujjat integratsiya uchun kerak bo'ladigan hamma narsani o'z ichiga oladi.


1. Muammo va yechim

Karta o'tkazmasi hech qanday buyurtma raqamini olib kelmaydi. Bankdan faqat shunday xabar keladi:

HUMO *0268 Popolnenie 24 017.00 UZS Balans: 1 250 000.00 UZS

Bu yerda buyurtma raqami yo'q. Kim to'laganini, qaysi buyurtma uchun to'laganini aniqlashning yagona ishonchli yo'li — noyob summa.

1. Platforma 24 000 so'mlik hisob so'raydi
2. CardHook 24 017 so'm qaytaradi          <- oxirgi 2 raqam noyob
3. Mijoz aynan 24 017 o'tkazadi
4. Bank xabari keladi
5. Shu summani kutayotgan yagona hisob topiladi
6. Platformaga imzolangan callback ketadi

Qo'shimcha summa 0 dan 99 so'mgacha — mijoz uchun sezilmaydi, lekin ayni paytda kutilayotgan hisoblar orasida takrorlanmaydi.

Noyoblik qanday kafolatlanadi

Ikki qatlam:

  1. Kod qatlami — hisob yaratilganda band summalar o'qiladi va bo'shi

tanlanadi.

  1. Baza qatlami — UNIQUE(pay_amount) WHERE status='pending' qisman

indeksi. Ikkita so'rov bir vaqtda kelsa ham baza ikkinchisini rad etadi va kod keyingi bo'sh summaga o'tadi.

Shu summa uchun barcha 100 variant band bo'lsa, no_free_amount xatosi qaytadi. Bu vaqtinchalik holat: eski hisoblar muddati tugagach summalar bo'shaydi.

Noaniqlikda taxmin yo'q

Agar bitta summaga ikkita hisob to'g'ri kelsa, CardHook hech birini avtomatik tasdiqlamaydi — tushum adminga qo'lda hal qilish uchun boradi. Bu tizimning eng muhim qoidasi: noto'g'ri buyurtmani yopgandan ko'ra, qo'lda tekshirgan afzal.


2. Boshlash

2.1. Nima kerak

API_KEYso'rovlarni imzolash uchun (pbx_ bilan boshlanadi)
CALLBACK_SECRETcallback imzosini tekshirish uchun
callback_urlto'lov tasdiqlanganda CardHook murojaat qiladigan manzil

Ikkalasini ham biznes panelidan olasiz: panel.cardhook.uz → API kalitlari.

Qayta ko'rish mumkinmiNega
API_KEYyo'qserverda faqat sha256 hash saqlanadi. Yo'qotsangiz «yangi kalit» tugmasi bilan yangisini olasiz — eskisi shu zahoti ishlamay qoladi.
CALLBACK_SECREThaimzo hisoblashda kerak, shuning uchun ochiq saqlanadi. «Ko'rsatish» tugmasi bilan istalgan vaqtda olasiz.

Maxfiy so'z oshkor bo'lsa — «yangi maxfiy so'z» tugmasi. Diqqat: yangilagan zahoti eski maxfiy so'z bilan imzolangan, hali yetkazilmagan callbacklar ham tekshiruvdan o'tmay qoladi.

2.2. Base URL

ManzilQachon ishlatiladi
http://127.0.0.1:8080platforma CardHook bilan bir serverda bo'lsa
https://api.cardhook.uzplatforma boshqa serverda bo'lsa

api.cardhook.uz istalgan manzildan ochiladi — IP ro'yxati yo'q. Autentifikatsiya butunlay API_KEY bo'yicha: kalitsiz yoki noto'g'ri kalit bilan 401 qaytadi. Shuning uchun kalitni sir saqlash MUHIM: u oshkor bo'lsa, istalgan joydan ishlatilishi mumkin. Oshkor bo'lsa panelda darhol yangilang.

Bir serverdagi platformalar uchun 127.0.0.1 afzal: tezroq, TLS va DNS ortiqcha yuki yo'q.

2.3. Autentifikatsiya

Har bir /v1/* so'rovda:

Authorization: Bearer pbx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Kalit sarlavhada uzatiladi, so'rov manzilida emas — aks holda u nginx loglariga, proxy loglariga va brauzer tarixiga tushadi.

Kalit noto'g'ri, yo'q yoki platforma bloklangan bo'lsa — 401 unauthorized.

2.4. Pul birligi

API'da summalar so'mda, butun son:

json
{ "amount": 24000, "pay_amount": 24017 }

Ichkarida hammasi tiyinda (int) saqlanadi, float umuman ishlatilmaydi — yaxlitlash xatosi to'lovda qabul qilinmaydi.

Kasr summalar qo'llab-quvvatlanmaydi. 24000.50 yuborsangiz invalid_amount qaytadi.

2.5. Vaqt formati

Barcha vaqtlar UTC, ISO 8601:

2026-09-21T10:30:00Z

Server vaqt zonasi (O'zbekistonda UTC+5) API javoblariga ta'sir qilmaydi. Foydalanuvchiga ko'rsatishda 5 soat qo'shing.


3. Hisob yaratish

http
POST /v1/invoices
Authorization: Bearer pbx_xxxxxxxx
Content-Type: application/json

So'rov

json
{
  "external_id": "order-123",
  "amount": 24000,
  "callback_url": "https://star.uz/cardhook/callback",
  "expires_in": 1800,
  "description": "100 Stars"
}
MaydonTurMajburiyIzoh
external_idstringhasizning buyurtma raqamingiz, 1–120 belgi
amountintegerhaso'mda, 1 000 – 100 000 000
callback_urlstringyo'qhttp:// yoki https://. Berilmasa callback yuborilmaydi
expires_inintegeryo'qsoniya, 60 – 86400. Default: 1800 (30 daqiqa)
descriptionstringyo'q255 belgigacha, faqat sizning panelingizda ko'rinadi

Javob — 201 Created

json
{
  "invoice_id": "inv_9f2a4c1b8e7d3a56",
  "external_id": "order-123",
  "amount": 24000,
  "pay_amount": 24017,
  "card": {
    "number": "9860 1701 1203 0268",
    "holder": "ISM FAMILIYA",
    "bank": "HUMO"
  },
  "status": "pending",
  "description": "100 Stars",
  "expires_at": "2026-09-21T10:30:00Z",
  "paid_at": null,
  "created_at": "2026-09-21T10:00:00Z"
}
MaydonIzoh
invoice_idCardHook bergan identifikator, inv_ + 16 hex belgi
amountsiz so'ragan summa
pay_amountmijozga ko'rsatiladigan summa — aynan shu to'lanishi kerak
cardmijoz pul o'tkazadigan karta
statuspending · paid · expired · cancelled
expires_atshundan keyin hisob expired bo'ladi va summa bo'shaydi
paid_atto'langan vaqt, pending holatda null

Idempotentlik

Bir xil external_id bilan qayta so'ralsa yangi hisob yaratilmaydi — mavjudi 200 OK bilan qaytadi (201 emas).

Bu tarmoq uzilishidan himoya qiladi: javob yo'lda yo'qolsa, so'rovni xavfsiz takrorlaysiz va o'sha hisobni olasiz.

1-so'rov  external_id=order-123  ->  201  pay_amount 24017
2-so'rov  external_id=order-123  ->  200  pay_amount 24017   (o'sha hisob)

Diqqat: takroriy so'rovda amount boshqacha bo'lsa ham e'tiborga olinmaydi — mavjud hisob o'z summasi bilan qaytadi. Boshqa summa kerak bo'lsa boshqa external_id ishlating.

external_id faqat sizning platformangiz ichida noyob bo'lishi kerak. Turli platformalar bir xil external_id ishlatishi mumkin.

Xatolar

HTTPKodSabab
400invalid_amountbutun son emas, chegaradan tashqarida yoki bool
400invalid_requestexternal_id bo'sh, JSON buzuq, expires_in noto'g'ri, callback_url http(s) emas
401unauthorizedkalit yo'q / noto'g'ri / platforma bloklangan
409no_free_amountshu summa uchun 100 ta variant ham band
429rate_limiteddaqiqalik limitdan oshdi
503no_active_cardfaol karta yo'q yoki kunlik limit to'lgan

4. Hisobni olish

4.1. ID bo'yicha

http
GET /v1/invoices/inv_9f2a4c1b8e7d3a56
Authorization: Bearer pbx_xxxxxxxx

Javob — 3-bo'limdagi bilan bir xil obyekt.

4.2. O'z raqamingiz bo'yicha

http
GET /v1/invoices?external_id=order-123
Authorization: Bearer pbx_xxxxxxxx

invoice_id ni saqlamagan bo'lsangiz qulay.

Xatolar

HTTPKodSabab
400invalid_requestexternal_id parametri berilmagan
401unauthorizedkalit muammosi
404not_foundhisob yo'q yoki boshqa platformaniki

Boshqa platformaning hisobi ham 404 qaytaradi — 403 emas. Ya'ni mavjudligi ham oshkor qilinmaydi.


5. Hisobni bekor qilish

http
POST /v1/invoices/inv_9f2a4c1b8e7d3a56/cancel
Authorization: Bearer pbx_xxxxxxxx

Faqat pending holatdagi hisob bekor qilinadi. Bekor qilingach uning pay_amount summasi darhol bo'shaydi va boshqa hisobga berilishi mumkin.

Javob — hisob obyekti, status: "cancelled".

Xatolar

HTTPKodSabab
404not_foundhisob yo'q yoki boshqa platformaniki
409already_paidhisob allaqachon to'langan

expired yoki cancelled hisobni bekor qilish xato emas — hisob o'z holatida qaytadi.


6. Callback

To'lov aniqlangach CardHook sizning callback_url manzilingizga POST yuboradi.

Callback qaysi manzildan keladi:

Manba IP138.249.7.47
User-AgentPayBox/1.0
MetodPOST, Content-Type: application/json

Xohlasangiz o'z tarafingizda shu IP dan boshqasini rad etishingiz mumkin — lekin bu imzo tekshirish o'rnini bosmaydi. IP ni soxtalashtirish mumkin, imzoni esa yo'q. Imzo har doim tekshirilsin, IP filtri faqat qo'shimcha qatlam.

Agar proxy (Cloudflare, nginx) orqali qabul qilsangiz, haqiqiy IP X-Forwarded-For sarlavhasida bo'ladi.

http
POST /cardhook/callback
X-Signature: sha256=9b1f2c...
X-Timestamp: 1790000000
Content-Type: application/json
User-Agent: PayBox/1.0

{"invoice_id":"inv_9f2a4c1b8e7d3a56","external_id":"order-123","amount":24000,"paid_amount":24017,"paid_at":"2026-09-21T10:12:03Z","status":"paid"}
MaydonIzoh
invoice_idCardHook identifikatori
external_idsizning buyurtma raqamingiz
amountsiz so'ragan summa
paid_amountmijoz haqiqatan o'tkazgan summa (noyob qo'shimcha bilan)
paid_atto'lov tasdiqlangan vaqt, UTC
statushozircha faqat paid

6.1. Imzoni tekshirish — MAJBURIY

HMAC_SHA256(callback_secret, timestamp + "." + raw_body)

Imzo aynan yuborilgan baytlar ustidan hisoblanadi. JSON'ni qayta serializatsiya qilmang — bo'sh joy yoki maydon tartibi o'zgarsa imzo mos kelmaydi.

Imzo tekshirilmasa, istalgan odam sizning manzilingizga "to'landi" deb POST yuborishi mumkin.

Python (aiohttp):

python
import hashlib
import hmac
import json
import time

SECRET = "sizning_callback_secret"

def verify(raw_body: bytes, timestamp: str, signature: str) -> bool:
    # Eski so'rovlarni rad etamiz (replay himoyasi)
    try:
        if abs(time.time() - int(timestamp)) > 300:
            return False
    except (TypeError, ValueError):
        return False

    expected = "sha256=" + hmac.new(
        SECRET.encode(),
        timestamp.encode() + b"." + raw_body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(signature, expected)


async def handle_callback(request):
    raw = await request.read()
    if not verify(
        raw,
        request.headers.get("X-Timestamp", ""),
        request.headers.get("X-Signature", ""),
    ):
        return web.Response(status=403)

    data = json.loads(raw)

    # Idempotentlik - eng muhim qism
    if await already_processed(data["invoice_id"]):
        return web.Response(text="ok")

    await deliver_order(data["external_id"])
    await mark_processed(data["invoice_id"])

    return web.Response(text="ok")   # 2xx bo'lishi SHART

Node.js (Express):

javascript
const crypto = require("crypto");
const SECRET = process.env.CARDHOOK_SECRET;

// raw body kerak - express.json() dan OLDIN
app.post(
  "/cardhook/callback",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const ts = req.get("X-Timestamp") || "";
    const sig = req.get("X-Signature") || "";

    if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
      return res.sendStatus(403);
    }

    const expected =
      "sha256=" +
      crypto
        .createHmac("sha256", SECRET)
        .update(Buffer.concat([Buffer.from(ts + "."), req.body]))
        .digest("hex");

    const ok =
      sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
    if (!ok) return res.sendStatus(403);

    const data = JSON.parse(req.body.toString());
    if (await alreadyProcessed(data.invoice_id)) return res.send("ok");

    await deliverOrder(data.external_id);
    await markProcessed(data.invoice_id);
    res.send("ok");
  }
);

PHP:

php
<?php
$secret = getenv('CARDHOOK_SECRET');
$raw    = file_get_contents('php://input');
$ts     = $_SERVER['HTTP_X_TIMESTAMP'] ?? '';
$sig    = $_SERVER['HTTP_X_SIGNATURE'] ?? '';

if (abs(time() - (int)$ts) > 300) {
    http_response_code(403);
    exit;
}

$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, $secret);

if (!hash_equals($expected, $sig)) {
    http_response_code(403);
    exit;
}

$data = json_decode($raw, true);

if (alreadyProcessed($data['invoice_id'])) {
    echo 'ok';
    exit;
}

deliverOrder($data['external_id']);
markProcessed($data['invoice_id']);
echo 'ok';

6.2. Qayta urinishlar

Javobingiz 2xx bo'lmasa (yoki umuman kelmasa), CardHook qayta uradi:

UrinishQachon
1darhol
25 soniyadan keyin
330 soniyadan keyin
42 daqiqadan keyin
510 daqiqadan keyin
61 soatdan keyin

Jami 6 urinish, taxminan 1 soat 13 daqiqa. Shundan keyin ham yetkazilmasa — CardHook admini Telegram orqali ogohlantiriladi va callback gave_up holatiga o'tadi.

So'rov kutish muddati — 15 soniya. Javobingiz shundan sekin bo'lsa urinish muvaffaqiyatsiz hisoblanadi.

Tavsiya: callback'ni tez qaytaring. Og'ir ishni (buyurtma yetkazish, xabar yuborish) fon vazifasiga qo'ying, 2xx ni darhol bering.

6.3. Idempotentlik — MAJBURIY

Callback takrorlanishi mumkin. Masalan javobingiz yo'lda yo'qolsa, CardHook uni yetkazilmagan deb hisoblab qayta yuboradi.

Shuning uchun qabul qiluvchi tomon invoice_id bo'yicha idempotent bo'lishi shart: bitta invoice_id uchun buyurtma faqat bir marta bajarilsin.

Eng oddiy yo'l — bazada processed_callbacks(invoice_id) jadvali va unda UNIQUE indeks.

6.4. Yetkazilmagan callbackni qayta yuborish

6 urinish tugagach callback to'xtaydi va avtomatik qayta yuborilmaydi. Agar platformangiz uzoq vaqt o'chiq turgan bo'lsa, biznes panelidagi Callbacklar bo'limiga kiring: har bir yetkazilmagan xabar yonida «qayta yuborish» tugmasi bor.

Bu muhim: hisob CardHook'da paid bo'lib turadi, lekin sizning platformangiz bu haqda bilmaydi — mijoz pul to'lagan, buyurtma esa bajarilmagan. Qayta yuborish shu holatdan chiqishning yagona yo'li.

Panelda holatlar:

HolatMa'nosi
yetkazildisizning serveringiz 2xx qaytardi
urinilmoqdaurinishlar davom etmoqda
yetkazilmadi6 urinish tugadi — qo'lda qayta yuborish kerak

6.5. Callback kelmasa nima qilish kerak

Callback — qulaylik, yagona haqiqat manbai emas. Tarmoq muammosi bo'lishi mumkin. Shuning uchun:

(masalan har 30 soniyada, hisob muddati tugagunicha);

Ikkalasi ham idempotent bo'lgani uchun callback bilan to'qnashmaydi.


7. Hisob holatlari

                  to'lov aniqlandi
   pending ─────────────────────────> paid
      │
      ├── expires_at o'tdi ─────────> expired
      │
      └── /cancel ──────────────────> cancelled
HolatMa'nosi
pendingto'lov kutilmoqda, pay_amount band
paidto'lov aniqlandi va tasdiqlandi
expiredmuddati o'tdi, summa bo'shadi
cancelledsiz bekor qildingiz, summa bo'shadi

paid — yakuniy holat. Hisob pending dan paid ga faqat bir marta o'tadi: bu baza darajasidagi shartli UPDATE bilan kafolatlangan, ya'ni ikkita xabar bir vaqtda kelsa ham bitta to'lov ikki marta hisoblanmaydi.


8. Cheklovlar

CheklovQiymatOshsa
So'rovlar60 / daqiqa (har platforma uchun)429 rate_limited
Summa1 000 – 100 000 000 so'm400 invalid_amount
Hisob muddati60 – 86 400 soniya400 invalid_request
Bitta summa uchun faol hisoblar100 ta409 no_free_amount
So'rov tanasi64 KB413
external_id120 belgi400 invalid_request
description255 belgikesiladi

Qabul qilinmaydigan holatlar

Bir nechta o'tkazmani bitta hisobga yig'ish qo'llab-quvvatlanmaydi.

noyob summa mexanizmining ma'nosi yo'qoladi.

so'ramaydi va saqlamaydi. U faqat o'z kartasiga kelgan o'tkazmani kutadi.


9. Xatolar

Barcha xatolar bir xil shaklda:

json
{
  "error": {
    "code": "no_free_amount",
    "message": "Bu summa uchun bo'sh noyob qiymat qolmadi, birozdan keyin urinib ko'ring"
  }
}

Kodga qarab ish tuting, message ga emas — u o'zgarishi mumkin.

HTTPKodNima qilish kerak
400invalid_amountsummani tekshiring: butun son, chegarada
400invalid_requestso'rov maydonlarini tekshiring
401unauthorizedkalitni tekshiring; bloklangan bo'lsa adminga murojaat
403forbiddenpanel API sida: bu amalga ruxsatingiz yo'q
404not_foundinvoice_id yoki external_id noto'g'ri
409already_paidto'langan hisobni bekor qilib bo'lmaydi
409no_free_amount2–3 soniyadan keyin qayta urinib ko'ring
429rate_limitedso'rovlar tezligini kamaytiring
500internal_errorqayta urinib ko'ring; takrorlansa adminga xabar bering
503no_active_cardadminga xabar bering — karta o'chirilgan yoki limiti to'lgan

Qayta urinish tavsiyalari

KodQayta urinsa bo'ladimi
no_free_amountha — 2–3 soniyadan keyin
rate_limitedha — kutib turib
internal_errorha — orani ochib (exponential backoff)
no_active_cardha — lekin admin aralashuvi kerak
invalid_*, unauthorized, not_foundyo'q — so'rovning o'zi noto'g'ri

Qayta urinishda o'sha external_id ni ishlating — idempotentlik ikki marta hisob yaratilishiga yo'l qo'ymaydi.


10. To'liq integratsiya misoli

python
import os
import aiohttp

BASE = os.environ.get("CARDHOOK_URL", "http://127.0.0.1:8080")
KEY = os.environ["CARDHOOK_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}"}


class CardHookError(Exception):
    def __init__(self, code, message):
        super().__init__(f"{code}: {message}")
        self.code = code


async def create_invoice(session, order_id, amount_som, description=""):
    """Hisob yaratadi. Xato bo'lsa CardHookError."""
    payload = {
        "external_id": order_id,
        "amount": amount_som,
        "callback_url": "https://star.uz/cardhook/callback",
        "expires_in": 1800,
        "description": description,
    }
    async with session.post(
        f"{BASE}/v1/invoices", json=payload, headers=HEADERS
    ) as resp:
        data = await resp.json()
        if resp.status not in (200, 201):
            err = data.get("error", {})
            raise CardHookError(err.get("code"), err.get("message"))
        return data


async def get_invoice(session, invoice_id):
    async with session.get(
        f"{BASE}/v1/invoices/{invoice_id}", headers=HEADERS
    ) as resp:
        if resp.status == 404:
            return None
        return await resp.json()


async def cancel_invoice(session, invoice_id):
    async with session.post(
        f"{BASE}/v1/invoices/{invoice_id}/cancel", headers=HEADERS
    ) as resp:
        return await resp.json()


# --- Ishlatish ---

async def start_payment(order_id, amount):
    async with aiohttp.ClientSession() as session:
        invoice = await create_invoice(session, order_id, amount, "100 Stars")

    # Mijozga AYNAN pay_amount ni ko'rsating
    return (
        f"To'lov summasi: {invoice['pay_amount']:,} so'm\n".replace(",", " ")
        + f"Karta: {invoice['card']['number']}\n"
        + f"{invoice['card']['holder']}\n\n"
        + "Aynan shu summani o'tkazing - 1 so'm farq ham qabul qilinmaydi."
    )

11. Mijozga nima ko'rsatish kerak

Bu joy integratsiyaning eng muhim qismi. Noyob summa mexanizmi faqat mijoz aynan o'sha summani o'tkazsagina ishlaydi.

Ko'rsatish shart:

Namuna:

To'lov summasi
24 017 so'm          <- pay_amount, amount emas

aynan shu summani o'tkazing
1 so'm farq ham qabul qilinmaydi

HUMO
9860 1701 1203 0268
ISM FAMILIYA

Qoldi: 29:45

Mijoz 24 000 o'tkazsa, to'lov topilmaydi va qo'lda hal qilishga to'g'ri keladi. Shuning uchun summani yaxlitlash yoki "taxminan" deb ko'rsatish mumkin emas.


12. Sinov

Hozircha alohida test muhiti yo'q. Integratsiyani shunday sinang:

  1. Kichik summali hisob yarating (masalan 1 000 so'm)
  2. O'z kartangizdan aynan pay_amount ni o'tkazing
  3. Callback kelganini va buyurtma bajarilganini tekshiring
  4. Bir xil external_id bilan qayta so'rov yuboring — 200 va o'sha

hisob qaytishi kerak

  1. Callback'ni qasddan 500 qaytaradigan qiling va qayta urinishlar

ishlaganiga ishonch hosil qiling

Imzo tekshirishni alohida sinash uchun:

python
import hashlib, hmac

secret = "sizning_secret"
ts = "1790000000"
body = b'{"invoice_id":"inv_test","status":"paid"}'

signature = "sha256=" + hmac.new(
    secret.encode(), ts.encode() + b"." + body, hashlib.sha256
).hexdigest()

print(signature)

13. Xavfsizlik

Sizning tomoningizda:

kodga yozmang, git'ga tushirmang

Platformangiz nimani ko'radi

Ko'radiKo'rmaydi
Qabul kartasining to'liq raqami va egasining ismi — hisob yaratish javobidagi card maydonida. Busiz mijozga qayerga pul o'tkazishni ayta olmaysiz.Boshqa platformalarning hisoblari, to'lovlari, statistikasi
O'z hisoblaringiz va ularning holatiKartaning kunlik limiti, bugungi aylanmasi
O'z callbacklaringizBog'lanmagan (orphan) tushumlar

Karta raqami sir emas: u mijozga baribir ko'rsatiladi. Sir bo'lgani — API_KEY va CALLBACK_SECRET.

Kartalarni boshqarish (qo'shish, o'chirish, loyihaga biriktirish) va noaniq tushumlarni qo'lda bog'lash API orqali umuman mumkin emas — bular faqat operator panelida bajariladi. Shu sababli bitta platformaning kaliti oshkor bo'lsa ham, u boshqa platformaning puliga yeta olmaydi va kartani o'chirib to'lovlarni to'xtata olmaydi.

CardHook tomonida:


14. Tez-tez so'raladigan savollar

Mijoz noto'g'ri summa o'tkazsa nima bo'ladi?

To'lov hech qanday hisobga bog'lanmaydi va admin panelidagi "Noaniq to'lovlar" bo'limiga tushadi. Admin uni qo'lda kerakli hisobga bog'lashi mumkin — shundan keyin sizga odatdagi callback keladi.

Mijoz ikki marta to'lasa?

Birinchi to'lov hisobni yopadi, ikkinchisi noaniq to'lovlarga tushadi va admin ogohlantiriladi. CardHook avtomatik qaytarish qilmaydi.

Hisob muddati tugagandan keyin mijoz to'lasa?

To'lov noaniq to'lovlarga tushadi. Admin uni qo'lda bog'lashi mumkin.

Bitta buyurtma uchun ikkita hisob yaratsam bo'ladimi?

Ha, lekin har biriga boshqa external_id kerak. Eskisini /cancel bilan yopish tavsiya etiladi — shunda uning summasi bo'shaydi.

pay_amount ni o'zim tanlasam bo'ladimi?

Yo'q. Noyoblikni CardHook boshqaradi — aks holda ikkita hisob bir xil summa olishi va to'lovni bog'lab bo'lmay qolishi mumkin.

Bir nechta karta ishlatsam bo'ladimi?

Ha. Admin bir nechta karta qo'shishi mumkin, CardHook har hisob uchun kunlik limiti to'lmagan kartani tanlaydi. Qaysi karta tanlanganini javobdagi card maydonida ko'rasiz.

Callback nechta marta keladi?

Muvaffaqiyatli bo'lsa — bir marta. Javobingiz 2xx bo'lmasa 6 martagacha. Shuning uchun idempotentlik majburiy.

Valyuta faqat so'mmi?

Ha. Boshqa valyutalar qo'llab-quvvatlanmaydi.


15. Tez ma'lumotnoma

POST   /v1/invoices                     hisob yaratish
GET    /v1/invoices/{invoice_id}        hisobni olish
GET    /v1/invoices?external_id=...     o'z raqami bo'yicha
POST   /v1/invoices/{invoice_id}/cancel bekor qilish

Authorization: Bearer pbx_xxxxxxxx
Summalar: so'mda, butun son
Vaqtlar:  UTC, ISO 8601 (...Z)

Holatlar: pending | paid | expired | cancelled

Callback imzosi:
  HMAC_SHA256(callback_secret, timestamp + "." + raw_body)
  X-Signature: sha256=<hex>

Qayta urinish: darhol, 5s, 30s, 2m, 10m, 1h  (6 marta)
Rate limit:    60 so'rov / daqiqa

16. Integratsiya ro'yxati

Ishga tushirishdan oldin tekshiring:


CardHook v1 · Savollar bo'lsa admin bilan bog'laning.