Skip to main content

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.
Security Critical: Card codes are valuable credentials. Always encrypt during storage and transmission.

Card Data Structure

Fulfilled orders contain three key fields:
{
  "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

GET /v3/internet/check-id/{id}

Retrieve fulfilled card details

Secure Storage

Always encrypt card codes before storing in your database:
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()
      }
    }
  );
}

Delivery Methods

1. Email Delivery

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

// 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

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

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`);
}

Audit Logging

Log delivery events without exposing card data:
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:
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

Encrypt at Rest

Always encrypt card codes before storing in database

Use HTTPS Only

Never transmit cards over unencrypted connections

Verify Ownership

Check user owns order before showing card

No Plain Text Logs

Never log card codes in plain text

Include Instructions

Always provide clear usage instructions

Audit Trail

Log delivery events without sensitive data

Security Checklist

1

Generate Encryption Key

Create a secure 32-byte encryption key and store in environment variables
2

Encrypt Before Storing

Always encrypt card_code before database insertion
3

Verify User Ownership

Check user ID matches order before displaying card
4

Use HTTPS

Ensure all delivery methods use encrypted transport
5

Audit Logging

Log delivery events without including actual card codes
6

Clear Instructions

Provide step-by-step usage instructions for each service type

Error Handling

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