الانتقال إلى المحتوى الرئيسي

Documentation Index

Fetch the complete documentation index at: https://docs.oneclickdz.com/llms.txt

Use this file to discover all available pages before exploring further.

نظرة عامة

بعد تنفيذ طلبات بطاقات الهدايا، احصل على رموز البطاقات من API وسلّمها للعملاء بأمان. رموز البطاقات ذات قيمة مالية ويجب التعامل معها بعناية فائقة.
أمر بالغ الأهمية: رموز البطاقات بيانات حساسة قابلة للاستبدال بالمال. شفّرها دائماً عند التخزين والإرسال.

مرجع API

GET /v3/gift-cards/check-order/{orderId}

استرجاع تفاصيل البطاقة المنفَّذة

هيكل بيانات البطاقة

تحتوي الطلبات المنفَّذة على بطاقات بحقلين:
{
  "cards": [
    {
      "value": "XXXX-XXXX-XXXX-XXXX",  // Primary credential (PIN/code)
      "serial": "123456789"             // Secondary credential (serial number)
    }
  ]
}
كلا الحقلين value وserial حساسان ويجب حمايتهما.

مساعدات التشفير

const crypto = require('crypto');

// Encryption configuration
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // Must be 32 bytes
const ALGORITHM = 'aes-256-gcm';

function encryptCardData(text) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv(
    ALGORITHM,
    Buffer.from(ENCRYPTION_KEY, 'hex'),
    iv
  );
  
  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  
  const authTag = cipher.getAuthTag();
  
  return {
    iv: iv.toString('hex'),
    encryptedData: encrypted,
    authTag: authTag.toString('hex')
  };
}

function decryptCardData(iv, encryptedData, authTag) {
  const decipher = crypto.createDecipheriv(
    ALGORITHM,
    Buffer.from(ENCRYPTION_KEY, 'hex'),
    Buffer.from(iv, 'hex')
  );
  
  decipher.setAuthTag(Buffer.from(authTag, 'hex'));
  
  let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  
  return decrypted;
}

// Usage
const encrypted = encryptCardData('XXXX-XXXX-XXXX-XXXX');
const decrypted = decryptCardData(encrypted.iv, encrypted.encryptedData, encrypted.authTag);

التخزين الآمن

شفّر رموز البطاقات دائماً قبل تخزينها في قاعدة البيانات:
const crypto = require('crypto');

const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // Must be 32 bytes
const ALGORITHM = 'aes-256-gcm';

function encryptCardData(cardData) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv(
    ALGORITHM,
    Buffer.from(ENCRYPTION_KEY, 'hex'),
    iv
  );

  const plaintext = JSON.stringify(cardData);
  let encrypted = cipher.update(plaintext, 'utf8', 'hex');
  encrypted += cipher.final('hex');

  const authTag = cipher.getAuthTag();

  return {
    iv: iv.toString('hex'),
    encryptedData: encrypted,
    authTag: authTag.toString('hex')
  };
}

function decryptCardData(iv, encryptedData, authTag) {
  const decipher = crypto.createDecipheriv(
    ALGORITHM,
    Buffer.from(ENCRYPTION_KEY, 'hex'),
    Buffer.from(iv, 'hex')
  );

  decipher.setAuthTag(Buffer.from(authTag, 'hex'));

  let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
  decrypted += decipher.final('utf8');

  return JSON.parse(decrypted);
}

// Store encrypted cards
async function storeOrderCards(orderId, cards) {
  const encryptedCards = cards.map(card => ({
    ...encryptCardData(card),
    cardType: card.type
  }));

  await db.orders.updateOne(
    { orderId },
    {
      $set: {
        encryptedCards,
        status: 'FULFILLED',
        fulfilledAt: new Date()
      }
    }
  );
}

طرق التسليم

1. التسليم عبر البريد الإلكتروني

async function deliverCardsViaEmail(userId, orderId, cards) {
  const user = await db.users.findOne({ _id: userId });

  // Build email content with cards
  const cardList = cards.map((card, index) => `
    Card ${index + 1}:
    Code: ${card.value}
    Serial: ${card.serial}
  `).join('\n\n');

  await sendEmail({
    to: user.email,
    subject: 'Your Gift Card Order',
    html: `
      <h2>Your gift cards are ready!</h2>
      <p>Order ID: ${orderId}</p>
      <pre>${cardList}</pre>
      <p><strong>Important:</strong> Keep these codes secure and don't share them.</p>
    `
  });

  // Mark as delivered
  await db.orders.updateOne(
    { orderId },
    { $set: { 'encryptedCards.$[].deliveredAt': new Date() } }
  );

  console.log(`Delivered ${cards.length} cards to ${user.email}`);
}

2. العرض داخل التطبيق

// API endpoint to display cards in-app
app.get('/api/orders/:orderId/cards', authenticateUser, async (req, res) => {
  const { orderId } = req.params;
  const userId = req.user.id;

  // Verify ownership
  const order = await db.orders.findOne({ orderId, userId });

  if (!order) {
    return res.status(404).json({ error: 'Order not found' });
  }

  if (order.status !== 'FULFILLED') {
    return res.status(400).json({ error: 'Order not fulfilled yet' });
  }

  // Decrypt and return cards
  const cards = await getOrderCards(orderId);

  res.json({
    orderId,
    cards: cards.map((card, index) => ({
      cardNumber: index + 1,
      code: card.value,
      serial: card.serial
    }))
  });
});

3. التحميل الآمن

async function generateSecureCardFile(orderId, cards) {
  const content = cards.map((card, index) => `
Gift Card ${index + 1}
Code: ${card.value}
Serial: ${card.serial}
--------------------
  `).join('\n');

  // Encrypt the file content
  const encrypted = encryptCardData(content);

  // Store temporarily with unique token
  const token = crypto.randomBytes(32).toString('hex');
  await db.downloadTokens.insertOne({
    token,
    orderId,
    encrypted,
    expiresAt: new Date(Date.now() + 5 * 60 * 1000) // 5 minutes
  });

  return token;
}

// Download endpoint
app.get('/api/download/:token', async (req, res) => {
  const { token } = req.params;

  const download = await db.downloadTokens.findOne({ token });

  if (!download || download.expiresAt < new Date()) {
    return res.status(404).json({ error: 'Download link expired' });
  }

  const content = decryptCardData(
    download.encrypted.iv,
    download.encrypted.encryptedData,
    download.encrypted.authTag
  );

  res.setHeader('Content-Type', 'text/plain');
  res.setHeader('Content-Disposition', `attachment; filename="cards-${download.orderId}.txt"`);
  res.send(content);

  // Delete token after use
  await db.downloadTokens.deleteOne({ token });
});

تسجيل التدقيق

سجّل أحداث التسليم دون كشف بيانات البطاقة:
async function logCardDelivery(orderId, userId, method, cardCount) {
  await db.auditLogs.insertOne({
    event: 'CARDS_DELIVERED',
    orderId,
    userId,
    method, // 'email', 'in-app', 'download'
    cardCount,
    timestamp: new Date(),
    ipAddress: req.ip,
    userAgent: req.headers['user-agent']
  });

  console.log(`[AUDIT] Delivered ${cardCount} cards for order ${orderId} via ${method}`);
}

// ❌ Never log actual card codes
// console.log('Card code:', card.value); // Don't do this

سير التسليم الكامل

async function completeOrderDelivery(orderId, userId) {
  // 1. Check order is fulfilled
  const orderStatus = await checkOrderStatus(orderId);
  
  if (orderStatus.status !== 'FULFILLED' && orderStatus.status !== 'PARTIALLY_FILLED') {
    throw new Error('Order not ready for delivery');
  }
  
  // 2. Store encrypted cards
  await storeOrderCards(orderId, userId, orderStatus.cards);
  
  // 3. Deliver to customer
  await deliverCardsViaEmail(userId, orderId, orderStatus.cards);
  
  // 4. Log delivery
  await logCardDelivery(orderId, userId, 'email', orderStatus.cards.length);
  
  console.log(`✅ Order ${orderId} delivery complete`);
}

قائمة التحقق الأمنية

1

توليد مفتاح تشفير

أنشئ مفتاح تشفير آمن بطول 32 بايت وخزّنه في متغيرات البيئة
2

التشفير قبل التخزين

شفّر دائماً بيانات البطاقة قبل الإدراج في قاعدة البيانات
3

التحقق من ملكية المستخدم

تأكد أن المستخدم يملك الطلب قبل عرض البطاقة
4

استخدام HTTPS

تأكد من أن جميع طرق التسليم تستخدم نقلاً مشفراً
5

تسجيل التدقيق

سجّل أحداث التسليم دون تضمين الرموز الفعلية
6

الحذف الآمن

نفّذ سياسة حذف البطاقات إذا اقتضت اللوائح ذلك

أفضل الممارسات

التشفير في حالة السكون

شفّر دائماً رموز البطاقة قبل تخزينها في قاعدة البيانات

HTTPS فقط

لا ترسل بطاقات عبر اتصالات غير مشفرة

التحقق من الملكية

تحقق أن المستخدم يملك الطلب قبل عرض البطاقة

لا سجلات نصية

لا تسجّل رموز البطاقة كنص عادي في أي مكان

الحذف الآمن

احذف البطاقات بشكل آمن بعد استرجاع العميل لها إذا اقتضت السياسة ذلك

سجل التدقيق

سجّل أحداث التسليم دون تضمين البيانات الحساسة

الخطوات التالية

نظرة عامة

العودة إلى نظرة عامة على التكامل

تتبع الحالة

استعلام حالة الطلب

أفضل ممارسات الأمان

إرشادات الأمان العامة

تقديم الطلبات

تقديم طلبات بطاقات الهدايا

تحميل الكتالوج

جلب المنتجات المتاحة

مرجع API

التوثيق الكامل للـ endpoint