Skip to content

Oddiy To'lov Misoli

Payme Merchant API dan foydalangan holda to'lovni qayta ishlashning to'liq misoli.

Umumiy Ko'rinish

Ushbu misol quyidagilarni ko'rsatadi:

  • To'lov mumkinligini tekshirish
  • Tranzaktsiya yaratish
  • Tranzaktsiyani bajarish
  • Xatolarni ishlash
  • Ma'lumotlar bazasi integratsiyasi

Talablar

bash
bun add @joyida/payme

Muxit Sozlash

.env faylini yarating:

bash
PAYME_MERCHANT_ID=your_merchant_id
PAYME_SECRET_KEY=your_secret_key
DATABASE_URL=./app.db

Ma'lumotlar BazasiSxemasi

sql
-- Tranzaktsiyalar jadvalini yaratish
CREATE TABLE IF NOT EXISTS payme_transactions (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  payme_id TEXT UNIQUE NOT NULL,
  order_id TEXT NOT NULL,
  amount INTEGER NOT NULL,
  state INTEGER NOT NULL DEFAULT 1,
  reason INTEGER,
  create_time INTEGER NOT NULL,
  perform_time INTEGER DEFAULT 0,
  cancel_time INTEGER DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Buyurtmalar jadvalini yaratish
CREATE TABLE IF NOT EXISTS orders (
  id TEXT PRIMARY KEY,
  user_id INTEGER NOT NULL,
  amount INTEGER NOT NULL,
  status TEXT DEFAULT 'pending',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Indekslarni yaratish
CREATE INDEX idx_payme_transactions_payme_id ON payme_transactions(payme_id);
CREATE INDEX idx_payme_transactions_order_id ON payme_transactions(order_id);
CREATE INDEX idx_orders_user_id ON orders(user_id);

To'liq Implementatsiya

typescript
import { PaymeMerchant, TransactionStates, PaymeError, ValidationError, NetworkError } from '@joyida/payme';
import { Database } from 'bun:sqlite';

// Payme klientini ishga tushirish
const payme = new PaymeMerchant({
  merchantId: process.env.PAYME_MERCHANT_ID!,
  secretKey: process.env.PAYME_SECRET_KEY!,
  timeout: 30000
});

// Ma'lumotlar bazasini ishga tushirish
const db = new Database(process.env.DATABASE_URL!);

// 24-belgili Payme tranzaktsiya ID yaratish
function generatePaymeId(): string {
  const chars = '0123456789abcdef';
  let id = '';
  for (let i = 0; i < 24; i++) {
    id += chars[Math.floor(Math.random() * chars.length)];
  }
  return id;
}

// Buyurtma mavjudligini tekshirish va tafsilotlarini olish
function getOrder(orderId: string) {
  const order = db.query(`
    SELECT * FROM orders WHERE id = ? AND status = 'pending'
  `).get(orderId);

  if (!order) {
    throw new Error('Buyurtma topilmadi yoki allaqachon qayta ishlandi');
  }

  return order;
}

// Tranzaktsiyani ma'lumotlar bazasiga saqlash
function saveTransaction(data: {
  paymeId: string;
  orderId: string;
  amount: number;
  state: number;
  createTime: number;
}) {
  db.run(`
    INSERT INTO payme_transactions
    (payme_id, order_id, amount, state, create_time)
    VALUES (?, ?, ?, ?, ?)
  `, [
    data.paymeId,
    data.orderId,
    data.amount,
    data.state,
    data.createTime
  ]);
}

// Tranzaktsiya holatini yangilash
function updateTransactionState(paymeId: string, state: number, performTime?: number) {
  if (performTime) {
    db.run(`
      UPDATE payme_transactions
      SET state = ?, perform_time = ?, updated_at = CURRENT_TIMESTAMP
      WHERE payme_id = ?
    `, [state, performTime, paymeId]);
  } else {
    db.run(`
      UPDATE payme_transactions
      SET state = ?, updated_at = CURRENT_TIMESTAMP
      WHERE payme_id = ?
    `, [state, paymeId]);
  }
}

// Buyurtma holatini yangilash
function updateOrderStatus(orderId: string, status: string) {
  db.run(`
    UPDATE orders
    SET status = ?, updated_at = CURRENT_TIMESTAMP
    WHERE id = ?
  `, [status, orderId]);
}

// Asosiy to'lovni qayta ishlash funktsiyasi
async function processPayment(orderId: string) {
  console.log(`\n🔄 Buyurtma uchun to'lovni qayta ishlash: ${orderId}`);

  try {
    // 1. Buyurtma tafsilotlarini olish
    console.log('📋 Buyurtma tafsilotlarini olish...');
    const order = getOrder(orderId);
    console.log(`✅ Buyurtma topildi: ${order.amount} tiyin`);

    // 2. To'lov mumkinligini tekshirish
    console.log('\n🔍 To\'lov mumkinligini tekshirish...');
    const check = await payme.checkPerformTransaction({
      amount: order.amount,
      account: { order_id: orderId }
    });

    if (!check.allow) {
      throw new Error('To\'lov ruxsat etilmagan');
    }
    console.log('✅ To\'lov ruxsat etildi');

    // 3. Tranzaktsiya yaratish
    console.log('\n📝 Tranzaktsiya yaratish...');
    const paymeId = generatePaymeId();
    console.log(`Yaratilgan Payme ID: ${paymeId}`);

    const created = await payme.createTransaction({
      id: paymeId,
      time: Date.now(),
      amount: order.amount,
      account: { order_id: orderId }
    });

    console.log(`✅ Tranzaktsiya yaratildi: ${created.transaction}`);
    console.log(`   Holat: ${created.state} (yaratilgan)`);
    console.log(`   Yaratish vaqti: ${new Date(created.create_time).toISOString()}`);

    // 4. Ma'lumotlar bazasiga saqlash
    console.log('\n💾 Ma\'lumotlar bazasiga saqlash...');
    saveTransaction({
      paymeId,
      orderId,
      amount: order.amount,
      state: created.state,
      createTime: created.create_time
    });
    updateOrderStatus(orderId, 'awaiting_payment');
    console.log('✅ Ma\'lumotlar bazasiga saqlandi');

    // 5. Tranzaktsiyani bajarish (to'lovni yakunlash)
    console.log('\n💳 Tranzaktsiyani bajarish...');
    const performed = await payme.performTransaction({
      id: paymeId
    });

    console.log(`✅ Tranzaktsiya bajarildi: ${performed.transaction}`);
    console.log(`   Holat: ${performed.state} (yakunlangan)`);
    console.log(`   Bajarish vaqti: ${new Date(performed.perform_time).toISOString()}`);

    // 6. Ma'lumotlar bazasini yangilash
    console.log('\n💾 Ma\'lumotlar bazasini yangilash...');
    updateTransactionState(paymeId, performed.state, performed.perform_time);
    updateOrderStatus(orderId, 'paid');
    console.log('✅ Ma\'lumotlar bazasi yangilandi');

    // 7. Yakuniy holatni tekshirish
    console.log('\n🔍 Yakuniy holatni tekshirish...');
    const status = await payme.checkTransaction({
      id: paymeId
    });

    console.log('✅ Yakuniy holat:');
    console.log(`   Holat: ${status.state}`);
    console.log(`   Yaratildi: ${new Date(status.create_time).toISOString()}`);
    console.log(`   Bajarildi: ${new Date(status.perform_time).toISOString()}`);

    if (status.state === TransactionStates.COMPLETED) {
      console.log('\n🎉 To\'lov muvaffaqiyatli!');
      return {
        success: true,
        paymeId,
        transactionId: status.transaction,
        amount: order.amount
      };
    } else {
      throw new Error(`Kutilmagan tranzaktsiya holati: ${status.state}`);
    }

  } catch (error) {
    console.error('\n❌ To\'lov muvaffaqiyatsiz!');

    if (error instanceof ValidationError) {
      console.error('Tekshirish xatosi:', error.message);
      throw new Error(`Noto'g'ri kiritma: ${error.message}`);

    } else if (error instanceof PaymeError) {
      console.error('Payme xatosi:', error.code, error.message);

      switch (error.code) {
        case -32504:
          throw new Error('To\'lov tizimi sozlamalari xatosi');
        case -31001:
          throw new Error('Noto\'g\'ri to\'lov summasi');
        case -31003:
          throw new Error('Tranzaktsiya topilmadi');
        case -31050:
          throw new Error('Buyurtma topilmadi');
        case -32400:
          throw new Error('To\'lov tizimi vaqtinchalik mavjud emas');
        default:
          throw new Error(`To'lov xatosi: ${error.message}`);
      }

    } else if (error instanceof NetworkError) {
      console.error('Tarmoq xatosi:', error.message);
      if (error.timeout) {
        throw new Error(`So'rov ${error.timeout}ms dan keyin vaqt tugadi`);
      } else {
        throw new Error('Tarmoq aloqa xatosi');
      }

    } else {
      console.error('Noma\'lum xato:', error);
      throw error;
    }
  }
}

// Misol foydalanish
async function main() {
  // Test buyurtma yaratish
  const orderId = `ORD-${Date.now()}`;
  const amount = 500000; // 5000 so'm tiyinda

  db.run(`
    INSERT INTO orders (id, user_id, amount, status)
    VALUES (?, ?, ?, ?)
  `, [orderId, 1, amount, 'pending']);

  console.log(`Test buyurtma yaratildi: ${orderId}`);

  // To'lovni qayta ishlash
  try {
    const result = await processPayment(orderId);
    console.log('\n✅ To\'lov natijasi:', result);
  } catch (error) {
    console.error('\n❌ To\'lov xatosi:', error.message);
    process.exit(1);
  }
}

// Misolni ishga tushirish
main();

Misolni Ishga Tushirish

bash
# Bog'liqliklarni o'rnatish
bun install

# Muxit o'zgaruvchilarini o'rnatish
export PAYME_MERCHANT_ID=your_merchant_id
export PAYME_SECRET_KEY=your_secret_key

# Misolni ishga tushirish
bun run example.ts

Kutulgan Natija

Test buyurtma yaratildi: ORD-1234567890

🔄 Buyurtma uchun to'lovni qayta ishlash: ORD-1234567890
📋 Buyurtma tafsilotlarini olish...
✅ Buyurtma topildi: 500000 tiyin

🔍 To'lov mumkinligini tekshirish...
✅ To'lov ruxsat etildi

📝 Tranzaktsiya yaratish...
Yaratilgan Payme ID: 5305e3bab097f420a62ced0b
✅ Tranzaktsiya yaratildi: 5123
   Holat: 1 (yaratilgan)
   Yaratish vaqti: 2024-01-15T10:30:00.000Z

💾 Ma'lumotlar bazasiga saqlash...
✅ Ma'lumotlar bazasiga saqlandi

💳 Tranzaktsiyani bajarish...
✅ Tranzaktsiya bajarildi: 5123
   Holat: 2 (yakunlangan)
   Bajarish vaqti: 2024-01-15T10:30:01.000Z

💾 Ma'lumotlar bazasini yangilash...
✅ Ma'lumotlar bazasi yangilandi

🔍 Yakuniy holatni tekshirish...
✅ Yakuniy holat:
   Holat: 2
   Yaratildi: 2024-01-15T10:30:00.000Z
   Bajarildi: 2024-01-15T10:30:01.000Z

🎉 To'lov muvaffaqiyatli!

✅ To'lov natijasi: {
  success: true,
  paymeId: '5305e3bab097f420a62ced0b',
  transactionId: '5123',
  amount: 500000
}

Xato Ishlash Misollari

Noto'g'ri Suma

typescript
// Bu ValidationError tashlaydi
await payme.createTransaction({
  id: paymeId,
  time: Date.now(),
  amount: -100, // ❌ Manfiy suma
  account: { order_id: orderId }
});

// Natija:
// ❌ To'lov muvaffaqiyatsiz!
// Validation error: Amount must be a positive integer

Buyurtma Topilmadi

typescript
// Bu -31050 kodli PaymeError tashlaydi
await payme.checkPerformTransaction({
  amount: 500000,
  account: { order_id: 'NON_EXISTENT' } // ❌ Buyurtma mavjud emas
});

// Natija:
// ❌ To'lov muvaffaqiyatsiz!
// Payme error: -31050 Order not found

Tarmoq Vaqt Tugashi

typescript
// Bu NetworkError tashlaydi
const payme = new PaymeMerchant({
  merchantId: process.env.PAYME_MERCHANT_ID!,
  secretKey: process.env.PAYME_SECRET_KEY!,
  timeout: 1 // ❌ Juda qisqa vaqt tugashi
});

// Natija:
// ❌ To'lov muvaffaqiyatsiz!
// Network error: Request timed out after 1ms

Keyingi Qadamlar

MIT Lizenziyasi ostida chiqarilgan.