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

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 الخاص بـ OneClickDz. يغطي هذا الدليل تقديم الطلبات، ومعالجة الردود، وإدارة نظام المراجع الخاص بك.

مرجع API

اطلع على توثيق API الكامل لـ endpoint POST /v3/mobile/send

طلب الشحن الأساسي

مثال بسيط

curl -X POST https://api.oneclickdz.com/v3/mobile/send \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: YOUR_API_KEY" \
  -d '{
    "plan_code": "PREPAID_DJEZZY",
    "MSSIDN": "0778037340",
    "amount": 500,
    "ref": "order-1730462400-user123"
  }'

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

{
  "success": true,
  "data": {
    "topupId": "6901616fe9e88196b4eb64b0",
    "topupRef": "order-1730462400-user123"
  },
  "meta": {
    "timestamp": "2025-11-01T11:00:00.454Z"
  },
  "requestId": "req_1730462400_abc123"
}

توليد مراجع فريدة

احرص دائماً على توفير مراجع فريدة لمنع التكرار وتمكين التتبع:
function generateOrderRef(userId) {
  const timestamp = Date.now();
  const random = Math.random().toString(36).substring(2, 8);
  return `${userId}-${timestamp}-${random}`;
}

// Examples:
// user123-1730462400-x7k2p9
// user456-1730462401-m5n8q3

التحقق من الرصيد قبل الإرسال

تحقق دائماً من كفاية الرصيد لتجنب الطلبات الفاشلة:

مرجع API الرصيد

تعرّف على endpoint GET /v3/account/balance
async function checkBalance() {
  const response = await fetch('https://api.oneclickdz.com/v3/account/balance', {
    headers: {
      'X-Access-Token': process.env.ONECLICKDZ_API_KEY
    }
  });
  
  const data = await response.json();
  
  if (!data.success) {
    throw new Error('Failed to check balance');
  }
  
  return data.data.balance;
}

async function sendTopUpWithBalanceCheck({ planCode, phone, amount, ref, requiredBalance }) {
  // Check balance first
  const balance = await checkBalance();
  
  if (balance < requiredBalance) {
    throw new Error(`Insufficient balance. Required: ${requiredBalance} DZD, Available: ${balance} DZD`);
  }
  
  // Proceed with top-up
  return await sendTopUp({ planCode, phone, amount, ref });
}

معالجة الأخطاء

تعامل مع أخطاء API الشائعة:
راجع مرجع معالجة الأخطاء للاطلاع على رموز الأخطاء الكاملة واستراتيجيات المعالجة.
async function sendTopUpSafe(data) {
  try {
    return await sendTopUp(data);
  } catch (error) {
    // Parse error response
    if (error.response) {
      const errorData = error.response.data;
      
      switch (errorData.error?.code) {
        case 'ERR_VALIDATION':
          console.error('Validation error:', errorData.error.message);
          console.error('Field:', errorData.error.details?.field);
          break;
          
        case 'INSUFFICIENT_BALANCE':
          console.error('Insufficient balance');
          console.error('Required:', errorData.error.details?.required);
          console.error('Available:', errorData.error.details?.available);
          break;
          
        case 'DUPLICATED_REF':
          console.error('Duplicate reference');
          console.error('Existing topup:', errorData.error.details?.existingTopupId);
          // Check status of existing topup
          break;
          
        case 'INTERNAL_ERROR':
          console.error('Server error, contact support');
          console.error('Request ID:', errorData.requestId);
          break;
          
        default:
          console.error('Unknown error:', errorData.error?.message);
      }
    }
    
    throw error;
  }
}

التكامل مع قاعدة البيانات

سجّل الطلبات قبل وبعد استدعاءات API:
async function createTopUpOrder({ userId, planCode, phone, amount }) {
  // Start database transaction
  const transaction = await db.transaction();
  
  try {
    // 1. Generate reference
    const ref = generateOrderRef(userId);
    
    // 2. Get plan details
    const plan = await db.mobilePlans.findOne({
      where: { code: planCode }
    });
    
    const cost = amount * plan.wholesaleCost;
    
    // 3. Check user balance
    const user = await db.users.findOne({
      where: { id: userId },
      lock: true,  // Lock row for update
      transaction
    });
    
    if (user.balance < cost) {
      await transaction.rollback();
      throw new Error('Insufficient user balance');
    }
    
    // 4. Create order record
    const order = await db.orders.create({
      userId,
      ref,
      planCode,
      phone,
      amount,
      cost,
      status: 'PENDING',
      createdAt: new Date()
    }, { transaction });
    
    // 5. Deduct user balance
    await db.users.update({
      balance: user.balance - cost
    }, {
      where: { id: userId },
      transaction
    });
    
    // 6. Send to API
    const result = await sendTopUp({
      planCode,
      phone,
      amount,
      ref
    });
    
    // 7. Update order with API response
    await db.orders.update({
      apiTopupId: result.topupId,
      apiTopupRef: result.topupRef,
      status: 'PROCESSING'
    }, {
      where: { id: order.id },
      transaction
    });
    
    // Commit transaction
    await transaction.commit();
    
    return {
      orderId: order.id,
      topupId: result.topupId,
      ref: ref
    };
    
  } catch (error) {
    // Rollback on any error
    await transaction.rollback();
    throw error;
  }
}

المعالجة غير المتزامنة

للحصول على أداء أفضل، عالج الشحنات بشكل غير متزامن:
const Queue = require('bull');
const topupQueue = new Queue('topup-processing');

// Add job to queue
async function queueTopUp(orderData) {
  const order = await db.orders.create({
    ...orderData,
    status: 'QUEUED'
  });
  
  await topupQueue.add({
    orderId: order.id
  });
  
  return order;
}

// Process queue
topupQueue.process(async (job) => {
  const { orderId } = job.data;
  
  const order = await db.orders.findOne({ where: { id: orderId } });
  
  try {
    // Send top-up
    const result = await sendTopUp({
      planCode: order.planCode,
      phone: order.phone,
      amount: order.amount,
      ref: order.ref
    });
    
    // Update order
    await db.orders.update({
      apiTopupId: result.topupId,
      status: 'PROCESSING'
    }, {
      where: { id: orderId }
    });
    
    // Start status polling (another queue)
    await pollQueue.add({ topupId: result.topupId, orderId });
    
  } catch (error) {
    // Handle error
    await db.orders.update({
      status: 'FAILED',
      errorMessage: error.message
    }, {
      where: { id: orderId }
    });
    
    // Refund user
    await refundUser(order.userId, order.cost);
  }
});

منطق إعادة المحاولة

طبّق إعادة المحاولة لأخطاء الشبكة:
async function sendTopUpWithRetry(data, maxRetries = 3) {
  let lastError;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await sendTopUp(data);
    } catch (error) {
      lastError = error;
      
      // Don't retry on validation or duplicate errors
      if (error.code === 'ERR_VALIDATION' || error.code === 'DUPLICATED_REF') {
        throw error;
      }
      
      // Wait before retry (exponential backoff)
      if (attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s
        console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }
  
  throw lastError;
}

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

أنشئ ref فريداً لكل طلب لمنع التكرار وتمكين التتبع.
تحقق من كفاية الرصيد قبل الإرسال لتجنب الطلبات الفاشلة.
غلّف إنشاء الطلب وخصم الرصيد في معاملات لضمان اتساق البيانات.
استخدم قوائم الانتظار للحصول على أداء أفضل وتجربة مستخدم محسّنة.
أعد المحاولة عند أخطاء الشبكة مع التراجع الأسي، لكن لا تُعد المحاولة عند أخطاء التحقق من الصحة.
سجّل جميع الطلبات والردود لأغراض التنقيح والتدقيق.

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

الخطوة 4: استطلاع الحالة

تعلّم كيفية استطلاع وتتبع حالة الشحن

API التحقق بالمرجع

توثيق API لـ GET /v3/mobile/check-ref/:ref

API التحقق بالمعرّف

توثيق API لـ GET /v3/mobile/check-id/:id

مرجع معالجة الأخطاء

دليل معالجة الأخطاء والتعافي منها

إعداد Webhooks

إعداد إشعارات الحالة في الوقت الفعلي

استراتيجيات الاستطلاع

تحسين تطبيق الاستطلاع الخاص بك

API سجل المعاملات

اطلع على سجل معاملاتك

API الرصيد

endpoint التحقق من رصيد الحساب