Skip to content

Karta tokenizatsiyasi

Karta tokenizatsiyasi mijozlarga kartalarini bir marta saqlashga imkon beradi, shunda keyingi to'lovlar uchun karta ma'lumotlarini qayta kiritish shart bo'lmaydi.

Nima uchun karta tokenizatsiyasi?

Karta tokenizatsiyasi quyidagi afzalliklarni taqdim etadi:

  • Qulaylik: Mijozlar karta ma'lumotlarini har safarida kiritish shart bo'lmaydi
  • Tezlik: Takroriy to'lovlar tezroq
  • Xavfsizlik: Haqiqiy karta raqamlari serveringizda saqlanmaydi
  • Compliance: PCI DSS talablariga mos keladi

Tokenizatsiya qanday ishlaydi?

Karta Tokenizatsiyasi Ketma-ketligi

  │    oshiriladi        │                     │
  └────────────────────┤────────────────────>│

## Subscribe API usullari

### 1. cards.create

Karta yaratish va token olish uchun ishlatiladi.

```typescript
import { PaymeSubscribe } from '@joyida/payme';

const subscribeClient = new PaymeSubscribe({
  merchantId: 'your_merchant_id'
}, 'client');

const result = await subscribeClient.cardsCreate({
  card: {
    number: '8600069195406311',
    expire: '0399' // MMYY formati
  },
  save: true
});

console.log('Karta tokeni:', result.card.token);
console.log('Karta raqami:', result.card.number);
console.log('Amal qilish muddati:', result.card.expire);

Parametrlar:

  • card.number: Karta raqami (13-19 raqam)
  • card.expire: Amal qilish muddati (MMYY formati)
  • save: true bo'lsa, karta saqlanadi
  • account: Ixtiyoriy hisob ma'lumotlari
  • customer: Ixtiyoriy mijoz identifikatori

2. cards.get_verify_code

SMS kodini olish uchun ishlatiladi.

typescript
const verifyCode = await subscribeClient.cardsGetVerifyCode({
  token: 'card_token_here'
});

console.log('SMS yuborildi:', verifyCode.sent);
console.log('Telefon raqami:', verifyCode.phone);
console.log('Kutish vaqti:', verifyCode.wait, 'ms');

Parametrlar:

  • token: Karta tokeni

Javob:

  • sent: SMS yuborilganmi
  • phone: Maskalangan telefon raqami
  • wait: Keyingi urinishdan oldin kutish vaqti (millisekundlarda)

3. cards.verify

SMS kod bilan kartani tasdiqlash uchun ishlatiladi.

typescript
const verified = await subscribeClient.cardsVerify({
  token: 'card_token_here',
  code: '123456' // Paymedan kelgan SMS kodi
});

console.log('Karta tasdiqlandi:', verified.card.verify);
console.log('Takroriy to\'lovlar uchun:', verified.card.recurrent);

Parametrlar:

  • token: Karta tokeni
  • code: SMS kod

Javob:

  • card.verify: true bo'lsa, karta tasdiqlangan
  • card.recurrent: true bo'lsa, karta takroriy to'lovlar uchun ishlatilishi mumkin

4. cards.check (Server tomon)

Karta holatini tekshirish uchun ishlatiladi (faqat server tomon).

typescript
import { PaymeSubscribe } from '@joyida/payme';

const subscribeServer = new PaymeSubscribe({
  merchantId: 'your_merchant_id',
  password: 'your_password'
}, 'server');

const cardInfo = await subscribeServer.cardsCheck({
  token: 'card_token_here'
});

console.log('Karta tasdiqlanganmi:', cardInfo.card.verify);
console.log('Takroriy to\'lovlar uchun:', cardInfo.card.recurrent);

Parametrlar:

  • token: Karta tokeni

5. cards.remove (Server tomon)

Kartani olib tashlash uchun ishlatiladi (faqat server tomon).

typescript
const removed = await subscribeServer.cardsRemove({
  token: 'card_token_here'
});

console.log('Karta olib tashlandi:', removed.success);

To'liq tokenizatsiya oqimi

typescript
import { PaymeSubscribe } from '@joyida/payme';

// 1. Klient tomon - karta yaratish
const subscribeClient = new PaymeSubscribe({
  merchantId: 'your_merchant_id'
}, 'client');

// Karta yaratish
const result = await subscribeClient.cardsCreate({
  card: {
    number: '8600069195406311',
    expire: '0399'
  },
  save: true
});

console.log('Token:', result.card.token);

// 2. SMS kod so'rash
const verifyCode = await subscribeClient.cardsGetVerifyCode({
  token: result.card.token
});

console.log('SMS yuborildi:', verifyCode.sent);
console.log('Kutish vaqti:', verifyCode.wait, 'ms');

// 3. Mijozdan SMS kodni olish (UI orqali)
const smsCode = prompt('SMS kodni kiriting:');

// 4. Karta tasdiqlash
const verified = await subscribeClient.cardsVerify({
  token: result.card.token,
  code: smsCode!
});

if (verified.card.verify) {
  console.log('✅ Karta muvaffaqiyatli tasdiqlandi!');

  // Tokenni serverda saqlash
  await saveTokenToDatabase(result.card.token);
}

Token bilan to'lov qilish

Token bilan to'lov qilish uchun receipts.create va receipts.pay usullaridan foydalaning.

typescript
import { PaymeSubscribe } from '@joyida/payme';

// Server tomon
const subscribeServer = new PaymeSubscribe({
  merchantId: 'your_merchant_id',
  password: 'your_password'
}, 'server');

// 1. Chek yaratish
const receipt = await subscribeServer.receiptsCreate({
  amount: 500000, // 5000 so'm
  account: { user_id: 'user_123' }
});

console.log('Chek ID:', receipt.receipt._id);

// 2. Chekni token bilan to'lash
const paid = await subscribeServer.receiptsPay({
  id: receipt.receipt._id,
  token: 'saved_card_token' // Tokenizatsiyalangan karta tokeni
});

console.log('To\'lov holati:', paid.receipt.state); // 1 = to'langan

Xavfsizlik amaliyotlari

1. Tokenlarni xavfsiz saqlang

Tokenlarni shifrlangan holatda saqlang:

typescript
async function saveTokenToDatabase(token: string, userId: string) {
  // Tokenni shifrlang
  const encryptedToken = encrypt(token);

  // Ma'lumotlar bazasida saqlang
  await db.cardTokens.create({
    userId,
    token: encryptedToken,
    createdAt: new Date()
  });
}

2. HTTPSdan foydalaning

Har doim HTTPS bilan tokenlarni yuboring:

typescript
// ❌ Yomon - HTTP ishlatilyapti
const response = await fetch('http://api.example.com/save-token', {
  method: 'POST',
  body: JSON.stringify({ token })
});

// ✅ Yaxshi - HTTPS ishlatilmoqda
const response = await fetch('https://api.example.com/save-token', {
  method: 'POST',
  body: JSON.stringify({ token })
});

3. Tokenlarni log qilmang

Tokenlarni hech qachon log fayllariga yozmang:

typescript
// ❌ Yomon - Token logga yozilmoqda
console.log('User token:', token);

// ✅ Yaxshi - Token logga yozilmayapti
await saveToken(token);

4. Tokenlarni qo'lda boshqaring

Server tomon tokenlar uchun server tomon rejimdan foydalaning:

typescript
// ✅ To'g'ri - Server tomon
const subscribe = new PaymeSubscribe({
  merchantId: process.env.PAYME_MERCHANT_ID!,
  password: process.env.PAYME_PASSWORD!
}, 'server');

// ❌ Yomon - Klient tomon token uchun ishlatilyapti
const subscribe = new PaymeSubscribe({
  merchantId: process.env.PAYME_MERCHANT_ID!
}, 'client'); // Parol yo'q!

Umumiy xatolar

Karta allaqachon mavjud (-31310)

Bu xato karta allaqachon saqlanganini bildiradi.

Yechim: Mavjud tokenni olish yoki yangi karta qo'shishni taklif qiling.

typescript
try {
  const result = await subscribeClient.cardsCreate({
    card: { number: '8600069195406311', expire: '0399' },
    save: true
  });
} catch (error) {
  if (error instanceof PaymeError && error.code === -31310) {
    console.log('Karta allaqachon saqlangan');
    // Mavjud tokenni olish
    const existing = await getSavedToken();
  }
}

Karta muddati o'tgan (-31301)

Bu xato karta muddati o'tganini bildiradi.

Yechim: Mijozga yangi karta qo'shishni taklif qiling.

typescript
try {
  const result = await subscribeClient.cardsVerify({
    token: token,
    code: code
  });
} catch (error) {
  if (error instanceof PaymeError && error.code === -31301) {
    console.log('Karta muddati o\'tgan');
    // Yangi karta qo'shishni taklif qiling
  }
}

SMS tasdiqlash muvaffaqiyatsiz (-31304)

Bu xato noto'g'ri SMS kodini bildiradi.

Yechim: Mijozga kodni tekshirib qayta kirishni so'rang.

typescript
try {
  const result = await subscribeClient.cardsVerify({
    token: token,
    code: code
  });
} catch (error) {
  if (error instanceof PaymeError && error.code === -31304) {
    console.log('SMS kod noto\'g\'ri');
    // Kodni qayta kiritish imkoniyatini bering
  }
}

To'liq misol

typescript
import { PaymeSubscribe, PaymeError } from '@joyida/payme';

// Klient tomon
const subscribeClient = new PaymeSubscribe({
  merchantId: process.env.PAYME_MERCHANT_ID!
}, 'client');

// Karta yaratish va tokenizatsiya
async function addCard() {
  try {
    // 1. Karta yaratish
    const result = await subscribeClient.cardsCreate({
      card: {
        number: '8600069195406311',
        expire: '0399'
      },
      save: true
    });

    console.log('Token olingan:', result.card.token);

    // 2. SMS kod so'rash
    const verifyCode = await subscribeClient.cardsGetVerifyCode({
      token: result.card.token
    });

    console.log('SMS yuborildi:', verifyCode.sent);

    // 3. Mijozdan SMS kodni olish
    const code = await promptUserForSMSCode();

    // 4. Karta tasdiqlash
    const verified = await subscribeClient.cardsVerify({
      token: result.card.token,
      code: code
    });

    if (verified.card.verify) {
      console.log('✅ Karta tasdiqlandi!');

      // 5. Tokenni saqlash
      await saveToken(result.card.token);

      return result.card.token;
    }
  } catch (error) {
    if (error instanceof PaymeError) {
      switch (error.code) {
        case -31310:
          console.log('Karta allaqachon saqlangan');
          break;
        case -31301:
          console.log('Karta muddati o\'tgan');
          break;
        case -31304:
          console.log('SMS kod noto\'g\'ri');
          break;
        default:
          console.log('Xato:', error.message);
      }
    }
    throw error;
  }
}

// Token bilan to'lov
async function payWithToken(token: string, amount: number) {
  const subscribeServer = new PaymeSubscribe({
    merchantId: process.env.PAYME_MERCHANT_ID!,
    password: process.env.PAYME_PASSWORD!
  }, 'server');

  // 1. Chek yaratish
  const receipt = await subscribeServer.receiptsCreate({
    amount: amount,
    account: { user_id: 'user_123' }
  });

  // 2. Chekni token bilan to'lash
  const paid = await subscribeServer.receiptsPay({
    id: receipt.receipt._id,
    token: token
  });

  return paid;
}

// Ishlatish
const token = await addCard();
await payWithToken(token, 500000);

MIT Lizenziyasi ostida chiqarilgan.