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

# Card Code Delivery

> Securely deliver internet card codes and transaction details to customers

## Overview

Once internet top-up orders are fulfilled, retrieve card codes and transaction numbers from the API and deliver them securely to customers. Card codes must be handled with care as they represent value.

<Warning>
  **Security Critical:** Card codes are valuable credentials. Always encrypt during storage and transmission.
</Warning>

## Card Data Structure

Fulfilled orders contain three key fields:

```json theme={null}
{
  "status": "FULFILLED",
  "card_code": "123456789012",
  "num_trans": "AT-2025-12345",
  "date_traitement": "2025-11-01T12:00:45.000Z"
}
```

* **card\_code:** The rechargeable code to enter (primary credential)
* **num\_trans:** Algérie Télécom transaction number (proof of purchase)
* **date\_traitement:** Processing timestamp

All three should be delivered to the customer.

## API Reference

<Card title="GET /v3/internet/check-id/{id}" icon="magnifying-glass" href="/en/api-reference/internet/check-by-id">
  Retrieve fulfilled card details
</Card>

## Secure Storage

Always encrypt card codes before storing in your database:

<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 encryptCardCode(code) {
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv(
      ALGORITHM,
      Buffer.from(ENCRYPTION_KEY, 'hex'),
      iv
    );
    
    let encrypted = cipher.update(code, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    
    const authTag = cipher.getAuthTag();
    
    return {
      iv: iv.toString('hex'),
      encryptedData: encrypted,
      authTag: authTag.toString('hex')
    };
  }

  function decryptCardCode(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;
  }

  // Store encrypted card
  async function storeCardSecurely(topupId, cardData) {
    const encrypted = encryptCardCode(cardData.card_code);
    
    await db.internetOrders.updateOne(
      { topupId },
      {
        $set: {
          status: 'FULFILLED',
          encryptedCard: encrypted,
          numTrans: cardData.num_trans,
          dateTraitement: cardData.date_traitement,
          fulfilledAt: new Date()
        }
      }
    );
  }
  ```

  ```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_code(code):
      aesgcm = AESGCM(ENCRYPTION_KEY)
      nonce = os.urandom(12)
      
      encrypted = aesgcm.encrypt(nonce, code.encode('utf-8'), None)
      
      return {
          'nonce': base64.b64encode(nonce).decode('utf-8'),
          'encryptedData': base64.b64encode(encrypted).decode('utf-8')
      }

  def decrypt_card_code(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')

  # Store encrypted card
  def store_card_securely(topup_id, card_data):
      encrypted = encrypt_card_code(card_data['card_code'])
      
      db.internet_orders.update_one(
          {'topupId': topup_id},
          {
              '$set': {
                  'status': 'FULFILLED',
                  'encryptedCard': encrypted,
                  'numTrans': card_data['num_trans'],
                  'dateTraitement': card_data['date_traitement'],
                  'fulfilledAt': datetime.now()
              }
          }
      )
  ```

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

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

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

  function decryptCardCode($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;
  }

  // Store encrypted card
  function storeCardSecurely($topupId, $cardData) {
      $encrypted = encryptCardCode($cardData['card_code']);
      
      updateOrderInDatabase($topupId, [
          'status' => 'FULFILLED',
          'encryptedCard' => $encrypted,
          'numTrans' => $cardData['num_trans'],
          'dateTraitement' => $cardData['date_traitement'],
          'fulfilledAt' => date('Y-m-d H:i:s')
      ]);
  }
  ?>
  ```
</CodeGroup>

## Delivery Methods

### 1. Email Delivery

```javascript theme={null}
async function deliverCardViaEmail(userId, topupId, cardData) {
  const user = await db.users.findOne({ _id: userId });
  
  await sendEmail({
    to: user.email,
    subject: 'Your Internet Card is Ready',
    html: `
      <h2>Your internet recharge card</h2>
      <p>Service: ${cardData.type}</p>
      <p>Number: ${cardData.number}</p>
      <p>Value: ${cardData.topup_amount} DA</p>
      
      <h3>Card Details:</h3>
      <p><strong>Card Code:</strong> ${cardData.card_code}</p>
      <p><strong>Transaction Number:</strong> ${cardData.num_trans}</p>
      <p><strong>Date:</strong> ${new Date(cardData.date_traitement).toLocaleString()}</p>
      
      <h3>How to Use:</h3>
      <p>1. Dial *600# from your ${cardData.type} line</p>
      <p>2. Select "Recharge"</p>
      <p>3. Enter the card code: ${cardData.card_code}</p>
      
      <p><strong>Important:</strong> Keep this code secure and don't share it with anyone.</p>
    `
  });
  
  // Mark as delivered
  await db.internetOrders.updateOne(
    { topupId },
    { $set: { deliveredAt: new Date() } }
  );
  
  console.log(`Card delivered to ${user.email}`);
}
```

### 2. In-App Display

```javascript theme={null}
// API endpoint to display card in-app
app.get('/api/internet-orders/:topupId/card', authenticateUser, async (req, res) => {
  const { topupId } = req.params;
  const userId = req.user.id;
  
  // Verify ownership
  const order = await db.internetOrders.findOne({ topupId, 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 card code
  const cardCode = decryptCardCode(
    order.encryptedCard.iv,
    order.encryptedCard.encryptedData,
    order.encryptedCard.authTag
  );
  
  res.json({
    topupId: order.topupId,
    type: order.type,
    number: order.number,
    value: order.value,
    cardCode,
    transactionNumber: order.numTrans,
    processedDate: order.dateTraitement,
    instructions: getUsageInstructions(order.type)
  });
});

function getUsageInstructions(type) {
  if (type === 'ADSL') {
    return [
      'Dial *600# from your ADSL line',
      'Select "Recharge"',
      'Enter the card code',
      'Confirm to add credit to your account'
    ];
  } else { // 4G
    return [
      'Dial *600# from your 4G device',
      'Select "Recharge"',
      'Enter the card code',
      'Your data will be activated immediately'
    ];
  }
}
```

### 3. SMS Delivery

```javascript theme={null}
async function deliverCardViaSMS(phoneNumber, cardData) {
  const message = `Your ${cardData.type} card is ready!\n\nCard Code: ${cardData.card_code}\nTransaction: ${cardData.num_trans}\n\nTo use: Dial *600# and follow instructions.`;
  
  await sendSMS({
    to: phoneNumber,
    message
  });
  
  console.log(`Card delivered via SMS to ${phoneNumber}`);
}
```

## Complete Delivery Flow

<CodeGroup>
  ```javascript Node.js theme={null}
  async function completeOrderDelivery(topupId, userId) {
    // 1. Get order details
    const order = await checkTopupStatus(topupId);
    
    if (order.status !== 'FULFILLED') {
      throw new Error('Order not ready for delivery');
    }
    
    // 2. Store encrypted card
    await storeCardSecurely(topupId, order);
    
    // 3. Deliver to customer
    await deliverCardViaEmail(userId, topupId, order);
    
    // 4. Log delivery (without sensitive data)
    await logCardDelivery(topupId, userId, 'email');
    
    console.log(`✅ Order ${topupId} delivery complete`);
  }
  ```

  ```python Python theme={null}
  async def complete_order_delivery(topup_id, user_id):
      # 1. Get order details
      order = check_topup_status(topup_id)
      
      if order['status'] != 'FULFILLED':
          raise ValueError('Order not ready for delivery')
      
      # 2. Store encrypted card
      store_card_securely(topup_id, order)
      
      # 3. Deliver to customer
      await deliver_card_via_email(user_id, topup_id, order)
      
      # 4. Log delivery (without sensitive data)
      await log_card_delivery(topup_id, user_id, 'email')
      
      print(f"✅ Order {topup_id} delivery complete")
  ```

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

  function completeOrderDelivery($topupId, $userId) {
      // 1. Get order details
      $order = checkTopupStatus($topupId);
      
      if ($order['status'] !== 'FULFILLED') {
          throw new Exception('Order not ready for delivery');
      }
      
      // 2. Store encrypted card
      storeCardSecurely($topupId, $order);
      
      // 3. Deliver to customer
      deliverCardViaEmail($userId, $topupId, $order);
      
      // 4. Log delivery (without sensitive data)
      logCardDelivery($topupId, $userId, 'email');
      
      error_log("✅ Order {$topupId} delivery complete");
  }
  ?>
  ```
</CodeGroup>

## Audit Logging

Log delivery events without exposing card data:

```javascript theme={null}
async function logCardDelivery(topupId, userId, method) {
  await db.auditLogs.insertOne({
    event: 'CARD_DELIVERED',
    topupId,
    userId,
    method, // 'email', 'sms', 'in-app'
    timestamp: new Date(),
    ipAddress: req.ip,
    userAgent: req.headers['user-agent']
  });
  
  // ❌ NEVER log actual card codes
  // console.log('Card code:', card.card_code); // DON'T DO THIS
}
```

## Usage Instructions by Type

Provide clear instructions for each service type:

```javascript theme={null}
function getCardUsageInstructions(type) {
  const instructions = {
    ADSL: {
      title: 'How to use your ADSL card',
      steps: [
        'Pick up your landline phone',
        'Dial *600#',
        'Select "Recharge" or "Flexy"',
        'Enter your card code: ${cardCode}',
        'Press # to confirm',
        'Your credit will be added immediately'
      ],
      support: 'For help, call 3003 from your ADSL line'
    },
    '4G': {
      title: 'How to use your 4G card',
      steps: [
        'Ensure your 4G SIM is active',
        'Dial *600# from your device',
        'Select "Recharge Internet"',
        'Enter your card code: ${cardCode}',
        'Press # to confirm',
        'Your data will be activated within minutes'
      ],
      support: 'For help, call 3003 from your mobile'
    }
  };
  
  return instructions[type];
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Encrypt at Rest" icon="lock">
    Always encrypt card codes before storing in database
  </Card>

  <Card title="Use HTTPS Only" icon="shield-halved">
    Never transmit cards over unencrypted connections
  </Card>

  <Card title="Verify Ownership" icon="user-lock">
    Check user owns order before showing card
  </Card>

  <Card title="No Plain Text Logs" icon="file-slash">
    Never log card codes in plain text
  </Card>

  <Card title="Include Instructions" icon="book">
    Always provide clear usage instructions
  </Card>

  <Card title="Audit Trail" icon="clipboard-list">
    Log delivery events without sensitive data
  </Card>
</CardGroup>

## Security Checklist

<Steps>
  <Step title="Generate Encryption Key">
    Create a secure 32-byte encryption key and store in environment variables
  </Step>

  <Step title="Encrypt Before Storing">
    Always encrypt card\_code before database insertion
  </Step>

  <Step title="Verify User Ownership">
    Check user ID matches order before displaying card
  </Step>

  <Step title="Use HTTPS">
    Ensure all delivery methods use encrypted transport
  </Step>

  <Step title="Audit Logging">
    Log delivery events without including actual card codes
  </Step>

  <Step title="Clear Instructions">
    Provide step-by-step usage instructions for each service type
  </Step>
</Steps>

## Error Handling

```javascript theme={null}
async function deliverCardSafely(topupId, userId) {
  try {
    await completeOrderDelivery(topupId, userId);
    return { success: true };
  } catch (error) {
    console.error('Delivery failed:', error);
    
    if (error.message.includes('not ready')) {
      return {
        success: false,
        error: 'ORDER_NOT_READY',
        message: 'Order is still processing. Please wait.'
      };
    }
    
    if (error.message.includes('not found')) {
      return {
        success: false,
        error: 'ORDER_NOT_FOUND',
        message: 'Order not found or you do not have access to it.'
      };
    }
    
    return {
      success: false,
      error: 'DELIVERY_FAILED',
      message: 'Failed to deliver card. Please contact support.'
    };
  }
}
```

## Next Steps

<CardGroup cols={3}>
  <Card title="Overview" icon="book-open" href="/en/internet-topup-guides/overview">
    Back to integration overview
  </Card>

  <Card title="Track Status" icon="chart-line" href="/en/internet-topup-guides/4-status-tracking">
    Poll order fulfillment
  </Card>

  <Card title="API Reference" icon="book" href="/en/api-reference/internet/check-by-id">
    Complete endpoint documentation
  </Card>

  <Card title="Security Best Practices" icon="shield" href="/en/security-best-practices">
    General security guidelines
  </Card>

  <Card title="Send Top-Ups" icon="paper-plane" href="/en/internet-topup-guides/3-sending-topups">
    Submit validated orders
  </Card>

  <Card title="Load Products" icon="list" href="/en/internet-topup-guides/1-loading-products">
    Fetch available cards
  </Card>
</CardGroup>
