> ## 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.

# التسليم الآمن للبطاقات

> تشفير وتسليم رموز بطاقات الهدايا بأمان إلى العملاء

<div dir="rtl">
  ## نظرة عامة

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

  <Warning>
    **أمر بالغ الأهمية:** رموز البطاقات بيانات حساسة قابلة للاستبدال بالمال. شفّرها دائماً عند التخزين والإرسال.
  </Warning>

  ## مرجع API

  <Card title="GET /v3/gift-cards/check-order/{orderId}" icon="magnifying-glass" href="/ar/api-reference/gift-cards/check-order">
    استرجاع تفاصيل البطاقة المنفَّذة
  </Card>

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

  تحتوي الطلبات المنفَّذة على بطاقات بحقلين:

  ```json theme={null}
  {
    "cards": [
      {
        "value": "XXXX-XXXX-XXXX-XXXX",  // Primary credential (PIN/code)
        "serial": "123456789"             // Secondary credential (serial number)
      }
    ]
  }
  ```

  كلا الحقلين `value` و`serial` حساسان ويجب حمايتهما.

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

  <CodeGroup>
    ```javascript Node.js theme={null}
    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);
    ```

    ```python Python theme={null}
    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
    import os
    import base64

    # Encryption key (32 bytes)
    ENCRYPTION_KEY = bytes.fromhex(os.getenv('ENCRYPTION_KEY'))

    def encrypt_card_data(text):
        aesgcm = AESGCM(ENCRYPTION_KEY)
        nonce = os.urandom(12)
        
        encrypted = aesgcm.encrypt(nonce, text.encode('utf-8'), None)
        
        return {
            'nonce': base64.b64encode(nonce).decode('utf-8'),
            'encryptedData': base64.b64encode(encrypted).decode('utf-8')
        }

    def decrypt_card_data(nonce_b64, encrypted_data_b64):
        aesgcm = AESGCM(ENCRYPTION_KEY)
        nonce = base64.b64decode(nonce_b64)
        encrypted = base64.b64decode(encrypted_data_b64)
        
        decrypted = aesgcm.decrypt(nonce, encrypted, None)
        
        return decrypted.decode('utf-8')

    # Usage
    encrypted = encrypt_card_data('XXXX-XXXX-XXXX-XXXX')
    decrypted = decrypt_card_data(encrypted['nonce'], encrypted['encryptedData'])
    ```

    ```php PHP theme={null}
    <?php

    define('ENCRYPTION_KEY', getenv('ENCRYPTION_KEY')); // 32 bytes hex
    define('CIPHER_ALGO', 'aes-256-gcm');

    function encryptCardData($text) {
        $key = hex2bin(ENCRYPTION_KEY);
        $iv = random_bytes(16);
        $tag = '';
        
        $encrypted = openssl_encrypt(
            $text, CIPHER_ALGO, $key, OPENSSL_RAW_DATA, $iv, $tag, '', 16
        );
        
        return [
            'iv' => bin2hex($iv),
            'encryptedData' => bin2hex($encrypted),
            'authTag' => bin2hex($tag)
        ];
    }

    function decryptCardData($ivHex, $encryptedHex, $authTagHex) {
        $key = hex2bin(ENCRYPTION_KEY);
        $iv = hex2bin($ivHex);
        $encrypted = hex2bin($encryptedHex);
        $authTag = hex2bin($authTagHex);
        
        $decrypted = openssl_decrypt(
            $encrypted, CIPHER_ALGO, $key, OPENSSL_RAW_DATA, $iv, $authTag
        );
        
        if ($decrypted === false) {
            throw new Exception('Decryption failed');
        }
        
        return $decrypted;
    }

    // Usage
    $encrypted = encryptCardData('XXXX-XXXX-XXXX-XXXX');
    $decrypted = decryptCardData($encrypted['iv'], $encrypted['encryptedData'], $encrypted['authTag']);
    ?>
    ```
  </CodeGroup>

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

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

  <CodeGroup>
    ```javascript Node.js theme={null}
    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()
          }
        }
      );
    }
    ```

    ```python Python theme={null}
    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
    import os
    import base64
    import json

    ENCRYPTION_KEY = bytes.fromhex(os.getenv('ENCRYPTION_KEY'))

    def encrypt_card_data(card_data):
        aesgcm = AESGCM(ENCRYPTION_KEY)
        nonce = os.urandom(12)

        plaintext = json.dumps(card_data).encode('utf-8')
        encrypted = aesgcm.encrypt(nonce, plaintext, None)

        return {
            'nonce': base64.b64encode(nonce).decode('utf-8'),
            'encryptedData': base64.b64encode(encrypted).decode('utf-8')
        }

    def decrypt_card_data(nonce_b64, encrypted_data_b64):
        aesgcm = AESGCM(ENCRYPTION_KEY)
        nonce = base64.b64decode(nonce_b64)
        encrypted = base64.b64decode(encrypted_data_b64)

        decrypted = aesgcm.decrypt(nonce, encrypted, None)
        return json.loads(decrypted.decode('utf-8'))

    def store_order_cards(order_id, cards):
        encrypted_cards = [encrypt_card_data(card) for card in cards]

        db.orders.update_one(
            {'orderId': order_id},
            {
                '$set': {
                    'encryptedCards': encrypted_cards,
                    'status': 'FULFILLED',
                    'fulfilledAt': datetime.now()
                }
            }
        )
    ```

    ```php PHP theme={null}
    <?php

    define('ENCRYPTION_KEY', getenv('ENCRYPTION_KEY'));
    define('CIPHER_ALGO', 'aes-256-gcm');

    function encryptCardData($cardData) {
        $key = hex2bin(ENCRYPTION_KEY);
        $iv = random_bytes(16);
        $tag = '';

        $plaintext = json_encode($cardData);
        $encrypted = openssl_encrypt(
            $plaintext,
            CIPHER_ALGO,
            $key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,
            '',
            16
        );

        return [
            'iv' => bin2hex($iv),
            'encryptedData' => bin2hex($encrypted),
            'authTag' => bin2hex($tag)
        ];
    }

    function decryptCardData($ivHex, $encryptedHex, $authTagHex) {
        $key = hex2bin(ENCRYPTION_KEY);
        $iv = hex2bin($ivHex);
        $encrypted = hex2bin($encryptedHex);
        $authTag = hex2bin($authTagHex);

        $decrypted = openssl_decrypt(
            $encrypted,
            CIPHER_ALGO,
            $key,
            OPENSSL_RAW_DATA,
            $iv,
            $authTag
        );

        if ($decrypted === false) {
            throw new Exception('Decryption failed');
        }

        return json_decode($decrypted, true);
    }
    ?>
    ```
  </CodeGroup>

  ## طرق التسليم

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

  ```javascript theme={null}
  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. العرض داخل التطبيق

  ```javascript theme={null}
  // 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. التحميل الآمن

  ```javascript theme={null}
  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 });
  });
  ```

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

  سجّل أحداث التسليم دون كشف بيانات البطاقة:

  ```javascript theme={null}
  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
  ```

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

  <CodeGroup>
    ```javascript Node.js theme={null}
    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`);
    }
    ```

    ```python Python theme={null}
    def complete_order_delivery(order_id, user_id):
        # 1. Check order is fulfilled
        order_status = check_order_status(order_id)
        
        if order_status['status'] not in ['FULFILLED', 'PARTIALLY_FILLED']:
            raise ValueError('Order not ready for delivery')
        
        # 2. Store encrypted cards
        store_order_cards(order_id, user_id, order_status['cards'])
        
        # 3. Deliver to customer
        deliver_cards_via_email(user_id, order_id, order_status['cards'])
        
        # 4. Log delivery
        log_card_delivery(order_id, user_id, 'email', len(order_status['cards']))
        
        print(f"✅ Order {order_id} delivery complete")
    ```

    ```php PHP theme={null}
    <?php

    function completeOrderDelivery($orderId, $userId, $apiKey) {
        // 1. Check order is fulfilled
        $orderStatus = checkOrderStatus($orderId, $apiKey);
        
        if (!in_array($orderStatus['status'], ['FULFILLED', 'PARTIALLY_FILLED'])) {
            throw new Exception('Order not ready for delivery');
        }
        
        // 2. Store encrypted cards
        storeOrderCards($orderId, $userId, $orderStatus['cards']);
        
        // 3. Deliver to customer
        deliverCardsViaEmail($userId, $orderId, $orderStatus['cards']);
        
        // 4. Log delivery
        logCardDelivery($orderId, $userId, 'email', count($orderStatus['cards']));
        
        error_log("✅ Order {$orderId} delivery complete");
    }
    ?>
    ```
  </CodeGroup>

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

  <Steps>
    <Step title="توليد مفتاح تشفير">
      أنشئ مفتاح تشفير آمن بطول 32 بايت وخزّنه في متغيرات البيئة
    </Step>

    <Step title="التشفير قبل التخزين">
      شفّر دائماً بيانات البطاقة قبل الإدراج في قاعدة البيانات
    </Step>

    <Step title="التحقق من ملكية المستخدم">
      تأكد أن المستخدم يملك الطلب قبل عرض البطاقة
    </Step>

    <Step title="استخدام HTTPS">
      تأكد من أن جميع طرق التسليم تستخدم نقلاً مشفراً
    </Step>

    <Step title="تسجيل التدقيق">
      سجّل أحداث التسليم دون تضمين الرموز الفعلية
    </Step>

    <Step title="الحذف الآمن">
      نفّذ سياسة حذف البطاقات إذا اقتضت اللوائح ذلك
    </Step>
  </Steps>

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

  <CardGroup cols={2}>
    <Card title="التشفير في حالة السكون" icon="lock">
      شفّر دائماً رموز البطاقة قبل تخزينها في قاعدة البيانات
    </Card>

    <Card title="HTTPS فقط" icon="shield-halved">
      لا ترسل بطاقات عبر اتصالات غير مشفرة
    </Card>

    <Card title="التحقق من الملكية" icon="user-lock">
      تحقق أن المستخدم يملك الطلب قبل عرض البطاقة
    </Card>

    <Card title="لا سجلات نصية" icon="file-slash">
      لا تسجّل رموز البطاقة كنص عادي في أي مكان
    </Card>

    <Card title="الحذف الآمن" icon="trash">
      احذف البطاقات بشكل آمن بعد استرجاع العميل لها إذا اقتضت السياسة ذلك
    </Card>

    <Card title="سجل التدقيق" icon="clipboard-list">
      سجّل أحداث التسليم دون تضمين البيانات الحساسة
    </Card>
  </CardGroup>

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

  <CardGroup cols={3}>
    <Card title="نظرة عامة" icon="book-open" href="/ar/gift-card-guides/overview">
      العودة إلى نظرة عامة على التكامل
    </Card>

    <Card title="تتبع الحالة" icon="chart-line" href="/ar/gift-card-guides/4-status-tracking">
      استعلام حالة الطلب
    </Card>

    <Card title="أفضل ممارسات الأمان" icon="shield" href="/ar/security-best-practices">
      إرشادات الأمان العامة
    </Card>

    <Card title="تقديم الطلبات" icon="cart-shopping" href="/ar/gift-card-guides/3-placing-orders">
      تقديم طلبات بطاقات الهدايا
    </Card>

    <Card title="تحميل الكتالوج" icon="list" href="/ar/gift-card-guides/1-loading-catalog">
      جلب المنتجات المتاحة
    </Card>

    <Card title="مرجع API" icon="book" href="/ar/api-reference/gift-cards/check-order">
      التوثيق الكامل للـ endpoint
    </Card>
  </CardGroup>
</div>
