openapi: 3.0.3
info:
  title: Paynet UWS (Universal Web Service) API
  description: |
    UWS protokoli (universal konnektor) orqali Paynet to'lov tizimi bilan integratsiya uchun API spetsifikatsiyasi.
    O'zaro aloqa TLS v1.3 (HTTPS) bilan himoyalangan HTTP 1.1 POST ustidan JSON-RPC 2.0 orqali amalga oshiriladi.
    2025-yil 07-maydagi UWS v3.4 spetsifikatsiyasiga mos keladi.

    **Muhim talablar:**
    - Barcha so'rovlar `UTF-8` kodirovkasi va `Content-Type: application/json`, `Accept: application/json` sarlavhalaridan foydalanishi shart.
    - Sana formati qat'iy `YYYY-MM-dd HH:mm:ss`, vaqt mintaqasi GMT+5.
      **Yagona istisno:** `CheckTransaction` so'rovidagi `timestamp` parametri
      `EEE MMM dd HH:mm:ss z yyyy` formatida keladi (masalan, `Mon Jun 16 06:12:41 UZT 2021`). Format tarixan
      o'rnatilgan va o'zgartirilmaydi.
    - `HTTP Basic Authentication` majburiy. Avtorizatsiya ma'lumotlari bo'lmasa yoki noto'g'ri bo'lsa,
      tizim `HTTP 401 Unauthorized` qaytarishi shart (JSON-RPC xatosi bilan 200 OK emas).
    - SLA: tranzaksiyani qayta ishlash — 500 ms dan ko'p emas (1 s gacha ruxsat etiladi, lekin sutkasiga 30 daqiqadan ko'p emas);
      30 soniya ichida javob olinmasa, Paynet taymaut bo'yicha ulanishni uzadi.
      SLA muntazam buzilganda Paynet sabab bartaraf etilgunga qadar yetkazib beruvchini uzib qo'yishi mumkin.
    - Summalar (`amount`) — tiyinlardagi butun sonlar (1 so'm = 100 tiyin).
    - `fields` obyektining tarkibi va qiymat turlari hamkor tomonidan
      «Texnik o'zaro aloqa tartibi» anketasida (3/5-jadvallar) belgilanadi; satr qiymatlari tavsiya etiladi.
  version: 3.4.0
  contact:
    name: Paynet Integration Team
    email: support@paynet.uz

servers:
  - url: https://api.partner.domain
    description: Hamkorning production serveri (URL hamkor tomonidan taqdim etiladi)

security:
  - basicAuth: []

paths:
  /uws:
    post:
      summary: JSON-RPC so'rovlari uchun yagona kirish nuqtasi
      description: |
        Paynet'dan hamkor billingiga barcha so'rovlar POST orqali ushbu endpointga yuboriladi.
        So'rov tanasi JSON-RPC 2.0 standartiga mos kelishi shart. Metod `method` maydoni bilan aniqlanadi;
        `params` strukturasi `method` qiymatiga qat'iy bog'langan (`RpcRequest` sxemasiga qarang).
      operationId: processRpcRequest
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RpcRequest'
            examples:
              GetInformation:
                summary: Ma'lumotnoma so'rovi
                value:
                  jsonrpc: "2.0"
                  method: "GetInformation"
                  id: 12350
                  params:
                    serviceId: 1
                    fields:
                      client_id: "634247"
              PerformTransaction:
                summary: To'lovni amalga oshirish
                value:
                  jsonrpc: "2.0"
                  method: "PerformTransaction"
                  id: 12345
                  params:
                    amount: 100000
                    serviceId: 1
                    transactionId: 12345678900
                    fields:
                      client_id: "634247"
              CheckTransaction:
                summary: Statusni tekshirish (timestamp formatiga e'tibor bering!)
                value:
                  jsonrpc: "2.0"
                  method: "CheckTransaction"
                  id: 12346
                  params:
                    serviceId: 1
                    transactionId: 12345678900
                    timestamp: "Mon Jun 16 06:12:41 UZT 2021"
              CancelTransaction:
                summary: Tranzaksiyani bekor qilish
                value:
                  jsonrpc: "2.0"
                  method: "CancelTransaction"
                  id: 12347
                  params:
                    serviceId: 1
                    transactionId: 12345678900
                    timestamp: "2021-06-16 12:44:57"
              GetStatement:
                summary: Davr uchun solishtirish
                value:
                  jsonrpc: "2.0"
                  method: "GetStatement"
                  id: 12348
                  params:
                    serviceId: 1
                    dateFrom: "2021-04-20 08:00:00"
                    dateTo: "2021-04-30 08:00:00"
              ChangePassword:
                summary: Parolni o'zgartirish (majburiy bo'lmagan metod)
                value:
                  jsonrpc: "2.0"
                  method: "ChangePassword"
                  id: 12351
                  params:
                    newPassword: "newSecurePassword"
      responses:
        '200':
          description: Muvaffaqiyatli yoki muvaffaqiyatsiz RPC javobi (result XOR error)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RpcResponse'
              examples:
                GetInformationResult:
                  summary: GetInformation javobi
                  value:
                    jsonrpc: "2.0"
                    id: 12350
                    result:
                      status: 0
                      timestamp: "2021-04-30 08:00:00"
                      fields:
                        balance: "420000"
                        name: "Pushkin A.S."
                PerformTransactionResult:
                  summary: PerformTransaction javobi
                  value:
                    jsonrpc: "2.0"
                    id: 12345
                    result:
                      timestamp: "2021-06-16 12:41:54"
                      providerTrnId: 2323
                      fields:
                        client_id: "634247"
                CheckTransactionResult:
                  summary: CheckTransaction javobi
                  value:
                    jsonrpc: "2.0"
                    id: 12346
                    result:
                      transactionState: 1
                      timestamp: "2021-06-16 12:44:57"
                      providerTrnId: 2323
                GetStatementResult:
                  summary: GetStatement javobi (faqat muvaffaqiyatli tranzaksiyalar)
                  value:
                    jsonrpc: "2.0"
                    id: 12348
                    result:
                      statements:
                        - amount: 120000
                          providerTrnId: 23
                          transactionId: 12345679800
                          timestamp: "2021-04-23 17:04:22"
                        - amount: 780000
                          providerTrnId: 47
                          transactionId: 12346578901
                          timestamp: "2021-04-24 13:25:02"
                ChangePasswordResult:
                  summary: ChangePassword javobi
                  value:
                    jsonrpc: "2.0"
                    id: 12351
                    result: "success"
                BusinessError:
                  summary: Biznes xatosi (mijoz topilmadi)
                  value:
                    jsonrpc: "2.0"
                    id: 12350
                    error:
                      code: 302
                      message: "Mijoz topilmadi"
        '401':
          description: Unauthorized. HTTP Basic Auth ma'lumotlari yo'q yoki noto'g'ri. Javob tanasi talab qilinmaydi.

components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: Login va parol Paynet so'rovlarini avtorizatsiya qilish uchun hamkor tomonidan taqdim etiladi.

  schemas:
    RpcId:
      description: So'rov identifikatori. Har qanday turda bo'lishi mumkin (son yoki satr); javob xuddi shu qiymatni qaytarishi shart.
      oneOf:
        - type: integer
          format: int64
        - type: string

    RpcRequest:
      description: JSON-RPC 2.0 so'rovi. `params` strukturasi `method` qiymati bilan aniqlanadi.
      oneOf:
        - $ref: '#/components/schemas/GetInformationRequest'
        - $ref: '#/components/schemas/PerformTransactionRequest'
        - $ref: '#/components/schemas/CheckTransactionRequest'
        - $ref: '#/components/schemas/CancelTransactionRequest'
        - $ref: '#/components/schemas/GetStatementRequest'
        - $ref: '#/components/schemas/ChangePasswordRequest'

    GetInformationRequest:
      type: object
      additionalProperties: false
      required: [jsonrpc, method, id, params]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        method:
          type: string
          enum: [GetInformation]
        id:
          $ref: '#/components/schemas/RpcId'
        params:
          $ref: '#/components/schemas/GetInformationParams'

    PerformTransactionRequest:
      type: object
      additionalProperties: false
      required: [jsonrpc, method, id, params]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        method:
          type: string
          enum: [PerformTransaction]
        id:
          $ref: '#/components/schemas/RpcId'
        params:
          $ref: '#/components/schemas/PerformTransactionParams'

    CheckTransactionRequest:
      type: object
      additionalProperties: false
      required: [jsonrpc, method, id, params]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        method:
          type: string
          enum: [CheckTransaction]
        id:
          $ref: '#/components/schemas/RpcId'
        params:
          $ref: '#/components/schemas/CheckTransactionParams'

    CancelTransactionRequest:
      type: object
      additionalProperties: false
      required: [jsonrpc, method, id, params]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        method:
          type: string
          enum: [CancelTransaction]
        id:
          $ref: '#/components/schemas/RpcId'
        params:
          $ref: '#/components/schemas/CancelTransactionParams'

    GetStatementRequest:
      type: object
      additionalProperties: false
      required: [jsonrpc, method, id, params]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        method:
          type: string
          enum: [GetStatement]
        id:
          $ref: '#/components/schemas/RpcId'
        params:
          $ref: '#/components/schemas/GetStatementParams'

    ChangePasswordRequest:
      type: object
      additionalProperties: false
      required: [jsonrpc, method, id, params]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        method:
          type: string
          enum: [ChangePassword]
        id:
          $ref: '#/components/schemas/RpcId'
        params:
          $ref: '#/components/schemas/ChangePasswordParams'

    GetInformationParams:
      type: object
      additionalProperties: false
      required: [serviceId, fields]
      properties:
        serviceId:
          type: integer
          description: Yetkazib beruvchi tomonidagi xizmat identifikatori (statik, «Texnik o'zaro aloqa tartibi»da ko'rsatiladi)
        fields:
          type: object
          description: To'ldirilgan xizmat maydonlari ro'yxati (masalan, telefon raqami, shaxsiy hisob). Tarkib va qiymat turlari — hamkor anketasi bo'yicha.

    PerformTransactionParams:
      type: object
      additionalProperties: false
      required: [amount, serviceId, transactionId, fields]
      properties:
        amount:
          type: integer
          format: int64
          minimum: 1
          description: Tiyinlardagi operatsiya summasi (butun son, 1 so'm = 100 tiyin)
        serviceId:
          type: integer
          description: Yetkazib beruvchi tomonidagi xizmat identifikatori
        transactionId:
          type: integer
          format: int64
          description: Noyob PAYNET tranzaksiya identifikatori (idempotentlik kaliti)
        fields:
          type: object
          description: To'ldirilgan xizmat maydonlari ro'yxati. Tarkib va qiymat turlari — hamkor anketasi bo'yicha.

    CheckTransactionParams:
      type: object
      additionalProperties: false
      required: [serviceId, transactionId, timestamp]
      properties:
        serviceId:
          type: integer
        transactionId:
          type: integer
          format: int64
        timestamp:
          type: string
          pattern: '^[A-Z][a-z]{2} [A-Z][a-z]{2} \d{2} \d{2}:\d{2}:\d{2} [A-Z]{2,5} \d{4}$'
          description: |
            PAYNET tomonida so'rovni qayta ishlash sanasi va vaqti (GMT+5).
            **DIQQAT: umumiy qoidadan istisno.** Format — `EEE MMM dd HH:mm:ss z yyyy`
            (masalan, `Mon Jun 16 06:12:41 UZT 2021`). Format tarixan o'rnatilgan va o'zgartirilmaydi.
            Oy — qat'iy qisqartirilgan `MMM` shaklida («Jun»).
          example: "Mon Jun 16 06:12:41 UZT 2021"

    CancelTransactionParams:
      type: object
      additionalProperties: false
      required: [serviceId, transactionId, timestamp]
      properties:
        serviceId:
          type: integer
        transactionId:
          type: integer
          format: int64
        timestamp:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: |
            PAYNET tomonida so'rovni qayta ishlash sanasi va vaqti (GMT+5).
            Core-jamoa tasdiqladi: CancelTransaction so'rovi ham, javobi ham standart
            `YYYY-MM-dd HH:mm:ss` formatidan foydalanadi (CheckTransaction'dan farqli). Spetsifikatsiyaning
            legacy misollarida `dd.MM.yyyy HH:mm:ss` ishlatilgan — bu manba xatosi.
          example: "2021-06-16 12:44:57"

    GetStatementParams:
      type: object
      additionalProperties: false
      required: [serviceId, dateFrom, dateTo]
      properties:
        serviceId:
          type: integer
        dateFrom:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: Davr boshlanishining sanasi va vaqti (GMT+5)
        dateTo:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: Davr tugashining sanasi va vaqti (GMT+5)

    ChangePasswordParams:
      type: object
      additionalProperties: false
      required: [newPassword]
      properties:
        newPassword:
          type: string
          minLength: 8
          description: Yangi parol (minimal uzunlik Paynet bilan kelishiladi)

    RpcResponse:
      description: JSON-RPC 2.0 javobi. Yoki `result` (muvaffaqiyat), yoki `error` (muvaffaqiyatsizlik) ni o'z ichiga oladi — hech qachon ikkalasini birga emas.
      oneOf:
        - $ref: '#/components/schemas/RpcSuccessResponse'
        - $ref: '#/components/schemas/RpcErrorResponse'

    RpcSuccessResponse:
      type: object
      additionalProperties: false
      required: [jsonrpc, id, result]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        id:
          $ref: '#/components/schemas/RpcId'
        result:
          $ref: '#/components/schemas/RpcResult'

    RpcErrorResponse:
      type: object
      additionalProperties: false
      required: [jsonrpc, id, error]
      properties:
        jsonrpc:
          type: string
          enum: ["2.0"]
        id:
          description: So'rov id'siga mos keladi; parsing xatosi (-32700) uchun null ruxsat etiladi.
          oneOf:
            - type: integer
              format: int64
            - type: string
              nullable: true
        error:
          $ref: '#/components/schemas/RpcError'

    RpcResult:
      oneOf:
        - $ref: '#/components/schemas/GetInformationResult'
        - $ref: '#/components/schemas/PerformTransactionResult'
        - $ref: '#/components/schemas/CheckCancelTransactionResult'
        - $ref: '#/components/schemas/GetStatementResult'
        - $ref: '#/components/schemas/ChangePasswordResult'

    GetInformationResult:
      type: object
      additionalProperties: false
      required: [status, timestamp, fields]
      properties:
        status:
          type: integer
          description: So'rov holati (0 — muvaffaqiyatli). Legacy misollarda "0" satri ishlatilgan — butun son qaytaring.
        timestamp:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: Yetkazib beruvchi tomonida so'rovni qayta ishlash sanasi va vaqti (GMT+5)
        fields:
          type: object
          description: Qo'shimcha parametrlar ro'yxati (masalan, mijoz balansi va ismi)

    PerformTransactionResult:
      type: object
      additionalProperties: false
      required: [providerTrnId, fields, timestamp]
      properties:
        providerTrnId:
          type: integer
          format: int64
          description: Yetkazib beruvchining tranzaksiya identifikatori
        fields:
          type: object
          description: |
            To'ldirilgan xizmat maydonlari ro'yxati. Agar anketada (4-jadval) kelishilgan bo'lsa,
            bu yerda tranzaksiyadan keyingi to'lovchi balansi (tiyinlarda) qaytariladi.
        timestamp:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: Yetkazib beruvchi tomonida so'rovni qayta ishlash sanasi va vaqti (GMT+5)

    CheckCancelTransactionResult:
      type: object
      additionalProperties: false
      required: [providerTrnId, timestamp, transactionState]
      properties:
        providerTrnId:
          type: integer
          format: int64
        timestamp:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: Yetkazib beruvchi tomonida so'rovni qayta ishlash sanasi va vaqti (GMT+5)
        transactionState:
          $ref: '#/components/schemas/TransactionStateEnum'

    GetStatementResult:
      type: object
      additionalProperties: false
      required: [statements]
      properties:
        statements:
          type: array
          description: Davr uchun tranzaksiyalar massivi. FAQAT muvaffaqiyatli tranzaksiyalar (state 1) kiritiladi; bekor qilinganlar kiritilmaydi.
          items:
            $ref: '#/components/schemas/StatementItem'

    StatementItem:
      type: object
      additionalProperties: false
      required: [amount, transactionId, providerTrnId, timestamp]
      properties:
        amount:
          type: integer
          format: int64
          minimum: 1
          description: Tiyinlardagi moliyaviy operatsiya summasi
        transactionId:
          type: integer
          format: int64
        providerTrnId:
          type: integer
          format: int64
        timestamp:
          type: string
          pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$'
          description: Yetkazib beruvchi tomonida tranzaksiyani qayta ishlash sanasi va vaqti (GMT+5)

    ChangePasswordResult:
      type: string
      description: So'rovni qayta ishlash statusi (satr, masalan "success")
      example: "success"

    TransactionStateEnum:
      type: integer
      description: |
        1 – Muvaffaqiyatli o'tkazilgan tranzaksiya, 2 – Bekor qilingan tranzaksiya, 3 – Tranzaksiya topilmadi.
        Noma'lum tranzaksiya uchun CheckTransaction'da xato 203 emas, state 3 (muvaffaqiyatli javob) qaytaring.
      enum: [1, 2, 3]

    RpcError:
      type: object
      additionalProperties: false
      required:
        - code
        - message
      properties:
        code:
          type: integer
          description: |
            Paynet xato kodi — JSON-RPC darajasidagi kod, error obyekti ichida qaytariladi (javobning HTTP statusi 200 OK bo'lib qoladi; bu HTTP kodi EMAS, ular ko'pincha adashtiriladi). To'liq ma'lumotnoma:
            0: Muvaffaqiyatli o'tkazildi (status qiymati; hech qachon error obyekti ichida qaytarilmaydi)
            77: To'lovni bekor qilish uchun mijoz hisobida mablag' yetarli emas
            100: Xizmat vaqtincha qo'llab-quvvatlanmaydi
            101: Kvota tugagan
            102, 103: Tizim/Noma'lum xato
            113: Hamyon identifikatsiya qilinmagan
            140: Ushbu akkaunt uchun oylik limit oshib ketdi
            141: Ushbu akkaunt uchun kunlik limit oshib ketdi
            201, 202: Tranzaksiya mavjud/bekor qilingan
            203: Tranzaksiya topilmadi (CancelTransaction'da ishlatiladi; CheckTransaction uchun — state 3)
            301, 302, 304, 305: Obyekt topilmadi
            306: Tranzaksiyani bekor qilish uchun ruxsat etilgan vaqt tugagan (yetkazib beruvchi o'z biznes-qoidalariga ko'ra qaytarishni rad etadi — yopuvchi hujjatlar shakllantirilgan, hisobot davri yopilgan; masalan, yanvarda to'lov, martda qaytarishga urinish)
            401-410: 1-10 parametrlarni validatsiya qilish xatolari (parametrlar taqsimoti xizmatga bog'liq)
            411: Bitta yoki bir nechta majburiy parametrlar ko'rsatilmagan (biznes darajasi; protokol darajasida -32602 bilan solishtiring)
            412: Noto'g'ri login yoki parol (legacy; autentifikatsiya HTTP 401 orqali bajariladi)
            413: Noto'g'ri summa
            414: Sana va vaqt formati noto'g'ri
            415: Summa maksimal limitdan oshib ketdi
            501, 601, 603: Kirish/buyruq cheklovlari
            JSON-RPC: -32300, -32700, -32600, -32601, -32602, -32603
        message:
          type: string
          description: Xato tavsifi
