Dasturchilar uchun

MirPay API hujjatlari

Virtual kassangizga to‘lovlarni qabul qilishni ulash uchun to‘liq qo‘llanma. Barcha so‘rovlar HTTPS orqali, javoblar JSON formatida.

Kirish

MirPay API orqali siz o‘z saytingiz yoki ilovangizdan to‘lov yaratasiz, mijozni to‘lov sahifasiga yo‘naltirasiz va natijani callback orqali olasiz.

Asosiy manzil
https://mirpay.uz
Joriy versiya
/api/v2
Yangi integratsiyalar uchun v2 dan foydalaning. Eski v1 ishlashda davom etadi, lekin yangi imkoniyatlar faqat v2 ga qo‘shiladi.

Kassa ID va API kalit

  1. Ro‘yxatdan o‘ting va emailingizni tasdiqlang.
  2. Identifikatsiya hujjatlarini yuklang va tasdiqlanishini kuting.
  3. Virtual kassa oching — do‘kon ma’lumotlari va webhook manzilini kiriting.
  4. Kassa tasdiqlangach Kassalarim → Batafsil oynasida Kassa ID, API kalit va Callback sirini ko‘rasiz.
API kalit va callback siri — maxfiy. Ularni brauzer kodida, mobil ilova ichida yoki ochiq repozitoriyada saqlamang. Faqat server tomonda ishlating.

To‘lov oqimi

1

Invoice yaratasiz

Serveringiz /api/v2/pay ga so‘rov yuboradi va payid hamda redirect_url oladi.

2

Mijozni yo‘naltirasiz

Mijoz redirect_url bo‘yicha MirPay to‘lov sahifasida kartasini kiritadi va SMS kodni tasdiqlaydi.

3

Natijani olasiz

MirPay sizning webhook manzilingizga imzolangan POST yuboradi. Qo‘shimcha ravishda holatni so‘rab ham olishingiz mumkin.

Muhim: buyurtmani faqat callback imzosini tekshirgandan keyin yoki holatni API orqali qayta so‘rab tasdiqlang. Mijoz brauzerining success_url ga qaytishi to‘lov dalili emas.

Avtorizatsiya

Barcha himoyalangan endpointlar Bearer token talab qiladi. Token kassaid va api_key juftligi orqali olinadi va faqat o‘sha kassa nomidan amal qiladi.

HTTP sarlavhalari
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json

Token olish

POST /api/v2/kassa/token Ochiq
ParametrTuriTavsif
kassaid majburiyintegerKassangiz raqami
api_key majburiystringKassa API kaliti
curl
curl -X POST https://mirpay.uz/api/v2/kassa/token \
  -H "Content-Type: application/json" \
  -d '{"kassaid": 1408, "api_key": "sizning_api_kalitingiz"}'
200 OK
{
  "success": true,
  "message": "Muvaffaqiyatli!",
  "data": {
    "token_type": "Bearer",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs..."
  }
}
401 — kalit noto‘g‘ri
{
  "success": false,
  "message": "Parametrlar yaroqsiz!"
}

Bu endpoint daqiqasiga 10 marta chaqirilishi mumkin. Tokenni har so‘rovda emas, keshda saqlab ishlating.

Kassa ma’lumoti

GET /api/v2/kassa/me Bearer

Token qaysi kassaga tegishli ekanini tekshirish uchun.

200 OK
{
  "success": true,
  "message": "OK",
  "data": {
    "kassa_id": 1408,
    "owner_user_id": "3"
  }
}

Invoice yaratish

POST /api/v2/pay Bearer
ParametrTuriTavsif
summa majburiy numeric To‘lov summasi so‘mda. 1 000 — 100 000 000 oralig‘ida.
info_pay majburiy string(255) Buyurtma tavsifi. Mijozga to‘lov sahifasida ko‘rinadi.
curl
curl -X POST https://mirpay.uz/api/v2/pay \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"summa": 250000, "info_pay": "Buyurtma #1042"}'
201 Created
{
  "success": true,
  "message": "Muvaffaqiyatli",
  "data": {
    "payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
    "payinfo": {
      "status": "Jarayonda",
      "order_info": "Buyurtma #1042",
      "summa": 250000,
      "yaratilgan": "2026-08-11T10:15:00.000000Z",
      "redirect_url": "https://mirpay.uz/pay/3d86e36e-d91a-4258-9e36-8f09366c6c13"
    }
  }
}

payid ni o‘z bazangizda buyurtmaga bog‘lab saqlang — callback aynan shu qiymat bilan keladi.

To‘lanmagan invoice 15 daqiqadan keyin avtomatik bekor qilinadi (mijoz karta kiritib, SMS kodni kutayotgan bo‘lsa — 40 daqiqa).

To‘lov holati

GET /api/v2/pay/{payid} Bearer

Faqat o‘z kassangizga tegishli to‘lovni ko‘ra olasiz — boshqa kassaning payid siga 403 qaytadi.

200 OK
{
  "success": true,
  "message": "OK",
  "data": {
    "payinfo": {
      "payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
      "summa": 250000,
      "comment": "Buyurtma #1042",
      "status": "Muvaffaqiyatli",
      "sana": "2026-08-11T10:15:00.000000Z"
    }
  }
}

Invoice (muqobil endpoint)

/api/v2/pay bilan bir xil vazifani bajaradi, lekin parametr nomlari boshqacha. Yangi loyihalarda /api/v2/pay ni tavsiya qilamiz.

POST /api/v2/invoices Bearer
ParametrTuriTavsif
amount majburiynumericSumma (1 000 — 100 000 000)
commentstring(255)Izoh
201 Created
{
  "success": true,
  "message": "Invoice yaratildi",
  "data": {
    "payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
    "status": "Jarayonda",
    "amount": 250000,
    "storeid": "1408"
  }
}
GET /api/v2/invoices/{payid} Bearer
200 OK
{
  "success": true,
  "message": "OK",
  "data": {
    "payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
    "status": "Muvaffaqiyatli",
    "amount": 250000,
    "comment": "Buyurtma #1042",
    "send": 1
  }
}

Balans

GET /api/v2/balance Bearer
200 OK
{
  "success": true,
  "message": "OK",
  "data": {
    "kassa_id": 1408,
    "balans": 1750000
  }
}

Ping

GET /api/v2/ping Ochiq

Integratsiyani tekshirish uchun. Token talab qilmaydi.

200 OK
{"success": true, "message": "V2 API OK", "data": []}

Callback va imzo tekshirish

To‘lov holati aniqlangach MirPay sizning kassangizda ko‘rsatilgan manzilga application/x-www-form-urlencoded ko‘rinishida POST yuboradi.

MaydonTuriTavsif
payidstringInvoice identifikatori
summastringHaqiqiy to‘langan summa
statusstringMuvaffaqiyatli! yoki Bekor qilindi!
commentstringBuyurtma izohi (URL-kodlangan)
chekstringChek sahifasiga havola
fiskalstringFiskal chek havolasi
sanastringYaratilgan sana, d.m.Y H:i:s

Sarlavhalar

HTTP
X-MirPay-Kassa-Id: 1408
X-MirPay-Timestamp: 1786443365
X-MirPay-Signature: 5f2c9a1e...   (HMAC-SHA256, hex)

Imzo quyidagicha hisoblanadi:

formula
signature = HMAC_SHA256(timestamp + "." + raw_body, callback_secret)

Bu yerda raw_body — so‘rovning xom tanasi (payid=...&summa=...), callback_secret — Kassalarim sahifasidagi maxfiy kalit.

PHP

callback.php
<?php
$secret = getenv('MIRPAY_CALLBACK_SECRET');

$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_MIRPAY_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_MIRPAY_SIGNATURE'] ?? '';

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

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

// Takroriy so'rovga qarshi: 5 daqiqadan eski bo'lmasin
if (abs(time() - (int) $ts) > 300) {
    http_response_code(408);
    exit('stale');
}

parse_str($body, $data);

// $data['payid'], $data['status'], $data['summa']
// Buyurtmani shu yerda tasdiqlang — idempotent bo'lsin!

http_response_code(200);
echo 'ok';

Node.js (Express)

callback.js
const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/mirpay/callback',
  express.raw({ type: 'application/x-www-form-urlencoded' }),
  (req, res) => {
    const body = req.body.toString('utf8');
    const ts   = req.get('X-MirPay-Timestamp') || '';
    const sig  = req.get('X-MirPay-Signature') || '';

    const expected = crypto
      .createHmac('sha256', process.env.MIRPAY_CALLBACK_SECRET)
      .update(ts + '.' + body)
      .digest('hex');

    const ok = sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));

    if (!ok) return res.status(403).send('bad signature');
    if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
      return res.status(408).send('stale');
    }

    const data = Object.fromEntries(new URLSearchParams(body));
    // data.payid, data.status, data.summa

    res.send('ok');
  });

Python (Flask)

callback.py
import hmac, hashlib, os, time
from urllib.parse import parse_qs
from flask import request, abort

SECRET = os.environ['MIRPAY_CALLBACK_SECRET'].encode()

@app.post('/mirpay/callback')
def callback():
    body = request.get_data(as_text=True)
    ts   = request.headers.get('X-MirPay-Timestamp', '')
    sig  = request.headers.get('X-MirPay-Signature', '')

    expected = hmac.new(SECRET, f'{ts}.{body}'.encode(), hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected, sig):
        abort(403)
    if abs(time.time() - int(ts or 0)) > 300:
        abort(408)

    data = {k: v[0] for k, v in parse_qs(body).items()}
    # data['payid'], data['status'], data['summa']

    return 'ok'
Callback muvaffaqiyatsiz bo‘lsa (2xx qaytmasa) MirPay uni 5 martagacha qayta yuboradi. Shuning uchun ishlov beruvchi kodingiz idempotent bo‘lishi shart — bitta payid ikki marta kelsa, buyurtma ikki marta bajarilmasin.

Limitlar va cheklovlar

CheklovQiymatIzoh
Eng kam summa1 000 so‘mGlobal
Eng ko‘p summa100 000 000 so‘mGlobal
Tranzaksiya limitikassa sozlamasiKassa tahrirlash sahifasida belgilanadi
Kunlik limitkassa sozlamasiBir kunda qabul qilinadigan jami summa
IP oq ro‘yxatikassa sozlamasiTo‘ldirilsa — API faqat shu IP’lardan ishlaydi
Token olish10 / daqiqaIP bo‘yicha
Boshqa endpointlar120 / daqiqaToken bo‘yicha

Limitdan oshsangiz 429 Too Many Requests qaytadi. Retry-After sarlavhasiga qarab kuting.

Statuslar va xatoliklar

To‘lov statuslari

Javobdagi qiymatMa’nosi
JarayondaInvoice yaratilgan, hali to‘lanmagan
MuvaffaqiyatliTo‘lov o‘tdi, mablag‘ kassa balansiga qo‘shildi
Bekor qilingan!Muddati tugagan yoki bekor qilingan

HTTP kodlari

KodSabab
200 / 201Muvaffaqiyatli
401Token yo‘q, muddati tugagan yoki kalit noto‘g‘ri
403Boshqa kassaning ma’lumoti, bloklangan kassa yoki ruxsat etilmagan IP
404To‘lov topilmadi
422Parametrlar noto‘g‘ri yoki limitdan oshgan
429So‘rovlar chastotasi oshib ketdi
Xatolik javobi (v2)
{
  "success": false,
  "message": "To‘lov summasi juda katta. Ruxsat etilgan eng yuqori summa: 100 000 000 so‘m.",
  "errors": {
    "summa": ["The summa field must not be greater than 100000000."]
  }
}

Eski v1 API

Avvalgi integratsiyalar uchun saqlanmoqda. Javob formatlari o‘zgarmagan.

POST /api/connect Ochiq
so‘rov / javob
POST /api/connect
{"kassaid": 1408, "api_key": "..."}

→ {"token": "eyJ0eXAi...", "natija": "Muvaffaqiyatli!"}
POST /api/create-pay Bearer
so‘rov / javob
POST /api/create-pay
{"summa": 250000, "info_pay": "Buyurtma #1042"}

→ {
  "id": "3d86e36e-...",
  "payinfo": {
    "status": "jarayonda",
    "order_info": "Buyurtma #1042",
    "summa": 250000,
    "yaratilgan": "2026-08-11T10:15:00.000000Z",
    "redicet_url": "https://mirpay.uz/pay/3d86e36e-..."
  },
  "natija": "Muvaffaqiyatli"
}

Diqqat: v1 da maydon nomi redicet_url (imlo xatosi bilan) — moslik uchun o‘zgartirilmagan. v2 da u redirect_url.

POST /api/pay/invoice/ Bearer
so‘rov / javob
POST /api/pay/invoice/
{"payid": "3d86e36e-..."}

→ {"payinfo": {
     "payid": "3d86e36e-...",
     "summa": "250000",
     "comment": "Buyurtma #1042",
     "status": "Muvaffaqiyatli",
     "sana": "2026-08-11T10:15:00.000000Z"
   }}
GET /api/balans Bearer
javob
{"balans": 1750000}

Savol qoldimi?

Integratsiya bo‘yicha yordam kerak bo‘lsa yozing.

Telegram orqali yozish