> ## 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>
    لا تُضمِّن مفاتيح API في نظام التحكم بالإصدار أو تعرِّضها في كود جانب العميل أبداً.
  </Warning>

  ```javascript theme={null}
  // ❌ Bad: Hardcoded in source code
  const API_KEY = "sk_live_abc123";

  // ✅ Good: Use environment variables
  const API_KEY = process.env.FLEXY_API_KEY;
  ```

  ### متغيرات البيئة

  ```bash theme={null}
  # .env file
  FLEXY_API_KEY=sk_live_your_key_here
  FLEXY_SANDBOX_KEY=sk_test_your_sandbox_key
  API_BASE_URL=https://api.oneclickdz.com
  ```

  ```javascript theme={null}
  // Load environment variables
  require("dotenv").config();

  const apiKey = process.env.FLEXY_API_KEY;
  ```

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

  ```javascript theme={null}
  // Support multiple keys for zero-downtime rotation
  const API_KEYS = {
    primary: process.env.FLEXY_API_KEY_PRIMARY,
    secondary: process.env.FLEXY_API_KEY_SECONDARY,
  };

  async function callApiWithRotation(endpoint, data) {
    try {
      return await callApi(endpoint, data, API_KEYS.primary);
    } catch (error) {
      if (error.status === 401) {
        // Try secondary key
        return await callApi(endpoint, data, API_KEYS.secondary);
      }
      throw error;
    }
  }
  ```

  ## فرض HTTPS

  ```javascript theme={null}
  // Always use HTTPS
  const API_BASE_URL = "https://api.oneclickdz.com";

  // Reject self-signed certificates in production
  const axios = require("axios");
  const https = require("https");

  const client = axios.create({
    baseURL: API_BASE_URL,
    httpsAgent: new https.Agent({
      rejectUnauthorized: process.env.NODE_ENV === "production",
    }),
  });
  ```

  ## التحقق من صحة الطلبات

  ```javascript theme={null}
  // Validate all inputs before sending to API
  const Joi = require("joi");

  const mobileTopupSchema = Joi.object({
    plan_code: Joi.string().required(),
    MSSIDN: Joi.string()
      .pattern(/^0[567][0-9]{8}$/)
      .required(),
    amount: Joi.number()
      .min(50)
      .max(5000)
      .when("plan_code", {
        is: Joi.string().pattern(/^DYN/),
        then: Joi.required(),
        otherwise: Joi.forbidden(),
      }),
    reference: Joi.string().max(100).required(),
  });

  function validateTopupRequest(data) {
    const { error, value } = mobileTopupSchema.validate(data);
    if (error) {
      throw new Error(`Validation error: ${error.message}`);
    }
    return value;
  }
  ```

  ## التعامل مع البيانات الحساسة

  ### لا تسجِّل البيانات الحساسة

  ```javascript theme={null}
  // ❌ Bad: Logs API key
  console.log("Request:", {
    headers: { "X-Access-Token": apiKey },
    body: data,
  });

  // ✅ Good: Redact sensitive info
  function sanitizeLog(data) {
    const sanitized = { ...data };
    if (sanitized.headers?.["X-Access-Token"]) {
      sanitized.headers["X-Access-Token"] = "***REDACTED***";
    }
    return sanitized;
  }

  console.log("Request:", sanitizeLog(request));
  ```

  ### حماية أرقام الهاتف

  ```javascript theme={null}
  // Mask phone numbers in logs/UI
  function maskPhone(phone) {
    if (phone.length !== 10) return phone;
    return phone.slice(0, 4) + "****" + phone.slice(-2);
  }

  console.log("Top-up sent to:", maskPhone("0551234567")); // 0551****67
  ```

  ### تأمين أكواد البطاقات

  ```javascript theme={null}
  // Never log full card codes
  function maskCardCode(code) {
    if (code.length <= 4) return "****";
    return "****" + code.slice(-4);
  }

  // Store securely
  await db.orders.create({
    data: {
      userId: user.id,
      cardCode: encrypt(cardCode), // Encrypt sensitive data
      cardCodeMasked: maskCardCode(cardCode),
    },
  });
  ```

  ## تحديد معدل الطلبات

  ```javascript theme={null}
  // Implement client-side rate limiting
  const rateLimit = require("express-rate-limit");

  const apiLimiter = rateLimit({
    windowMs: 60 * 1000, // 1 minute
    max: 60, // Max 60 requests per minute
    message: "Too many requests, please try again later",
  });

  app.use("/api/topup", apiLimiter, topupHandler);
  ```

  ## القائمة البيضاء لعناوين IP

  <Info>
    تواصل مع الدعم لإضافة عناوين IP الخاصة بخادمك إلى القائمة البيضاء لأمان إضافي.
  </Info>

  ```javascript theme={null}
  // Make requests from whitelisted IPs only
  const WHITELISTED_IPS = ["192.168.1.100", "10.0.0.50"];

  function isWhitelisted(ip) {
    return WHITELISTED_IPS.includes(ip);
  }

  app.use((req, res, next) => {
    const clientIp = req.ip;
    if (!isWhitelisted(clientIp)) {
      return res.status(403).json({ error: "Forbidden" });
    }
    next();
  });
  ```

  ## تسجيل المراجعة

  ```javascript theme={null}
  // Log all API interactions for audit
  async function auditLog(event, data) {
    await db.auditLogs.create({
      data: {
        timestamp: new Date(),
        event,
        userId: data.userId,
        action: data.action,
        ipAddress: data.ip,
        userAgent: data.userAgent,
        requestId: data.requestId,
        success: data.success,
        // Don't log sensitive data
        metadata: sanitize(data.metadata),
      },
    });
  }

  // Usage
  await auditLog("topup_sent", {
    userId: user.id,
    action: "SEND_MOBILE_TOPUP",
    ip: req.ip,
    userAgent: req.get("user-agent"),
    requestId: response.requestId,
    success: true,
  });
  ```

  ## رسائل الخطأ

  ```javascript theme={null}
  // Don't expose internal details in error messages
  function getSafeErrorMessage(error) {
    // Internal errors
    if (error.status >= 500) {
      return {
        message: "An error occurred. Please try again later.",
        code: "INTERNAL_ERROR",
        requestId: error.requestId, // Include for support
      };
    }

    // Client errors - be specific but safe
    return {
      message: error.message,
      code: error.code,
    };
  }
  ```

  ## الإعداد الآمن

  ```javascript theme={null}
  // Separate configs for sandbox/production
  const config = {
    sandbox: {
      apiKey: process.env.FLEXY_SANDBOX_KEY,
      baseUrl: "https://api.oneclickdz.com",
      testMode: true,
      logLevel: "debug",
    },
    production: {
      apiKey: process.env.FLEXY_API_KEY,
      baseUrl: "https://api.oneclickdz.com",
      testMode: false,
      logLevel: "error",
    },
  };

  const env = process.env.NODE_ENV || "sandbox";
  const currentConfig = config[env];
  ```

  ## أمان التبعيات

  ```bash theme={null}
  # Regularly audit dependencies
  npm audit

  # Update vulnerable packages
  npm audit fix

  # Use tools like Snyk
  npm install -g snyk
  snyk test
  ```

  ## التشفير في وقت الراحة

  ```javascript theme={null}
  // Encrypt sensitive data before storing
  const crypto = require("crypto");

  const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // 32-byte key
  const IV_LENGTH = 16;

  function encrypt(text) {
    const iv = crypto.randomBytes(IV_LENGTH);
    const cipher = crypto.createCipheriv(
      "aes-256-cbc",
      Buffer.from(ENCRYPTION_KEY),
      iv
    );
    let encrypted = cipher.update(text);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    return iv.toString("hex") + ":" + encrypted.toString("hex");
  }

  function decrypt(text) {
    const parts = text.split(":");
    const iv = Buffer.from(parts.shift(), "hex");
    const encrypted = Buffer.from(parts.join(":"), "hex");
    const decipher = crypto.createDecipheriv(
      "aes-256-cbc",
      Buffer.from(ENCRYPTION_KEY),
      iv
    );
    let decrypted = decipher.update(encrypted);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
  }

  // Usage
  const cardCode = "1234-5678-9012";
  const encrypted = encrypt(cardCode);
  await db.orders.create({ data: { cardCode: encrypted } });
  ```

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

  <Steps>
    <Step title="مفاتيح API">
      ✓ مخزّنة في متغيرات البيئة ✓ غير ملتزم بها في نظام إدارة الإصدارات ✓ يتم تدويرها دورياً
    </Step>

    <Step title="HTTPS">
      ✓ جميع الطلبات تستخدم HTTPS ✓ التحقق من الشهادة مفعّل
    </Step>

    <Step title="التحقق من المدخلات">
      ✓ جميع المدخلات يتم التحقق منها قبل استدعاءات API ✓ التحقق بالمخطط مطبّق
    </Step>

    <Step title="التسجيل">
      ✓ البيانات الحساسة غير مسجّلة ✓ سجلات المراجعة مفعّلة ✓ معرّفات الطلبات مُتتبَّعة
    </Step>

    <Step title="تحديد معدل الطلبات">
      ✓ تحديد من جانب العميل ✓ منطق إعادة المحاولة مع التراجع التدريجي
    </Step>

    <Step title="حماية البيانات">
      ✓ البيانات الحساسة مشفّرة في وقت الراحة ✓ أرقام الهاتف مُخفاة في السجلات ✓ أكواد البطاقات محمية
    </Step>
  </Steps>

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

  <CardGroup cols={2}>
    <Card title="لا تكشف المفاتيح أبداً" icon="key">
      استخدم متغيرات البيئة
    </Card>

    <Card title="استخدم HTTPS دائماً" icon="lock">
      أمّن جميع الاتصالات
    </Card>

    <Card title="تحقق من كل شيء" icon="circle-check">
      افحص المدخلات قبل الإرسال
    </Card>

    <Card title="شفّر البيانات الحساسة" icon="shield">
      احمِ البيانات في وقت الراحة
    </Card>
  </CardGroup>

  ## ذات صلة

  <CardGroup cols={2}>
    <Card title="المصادقة" href="/ar/authentication">
      إعداد مفاتيح API
    </Card>

    <Card title="معالجة الأخطاء" href="/ar/api-reference/error-handling">
      التعامل مع الأخطاء بأمان
    </Card>
  </CardGroup>
</div>
