> ## 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="ltr">
  ## نظرة عامة

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

  <Note>
    كل ما في هذه الصفحة يستخدم `https://billapi.oneclickdz.com` وترويسة `X-Access-Token`. إن لم تكن قد تأكدت بعد من البيئة التي ينتمي إليها مفتاحك، فابدأ بـ [التحقق من مفتاح API](/ar/api-reference/bill-payment/validate-key).
  </Note>

  ## التحقق من التوفر

  يُعيد `GET /v3/partners` مدخلاً واحداً لكل مُصدِر فاتورة، ولكل منها حقل `status` واحد.

  <CodeGroup>
    ```bash cURL theme={null}
    curl https://billapi.oneclickdz.com/v3/partners \
      -H "X-Access-Token: YOUR_API_KEY"
    ```

    ```javascript Node.js theme={null}
    const response = await fetch("https://billapi.oneclickdz.com/v3/partners", {
      headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
    });

    const body = await response.json();
    if (!body.success) throw new Error(body.error.code);

    const available = Object.entries(body.data)
      .filter(([, partner]) => partner.status === "ACTIVE")
      .map(([name]) => name);

    console.log(available);
    ```

    ```python Python theme={null}
    import os
    import requests

    response = requests.get(
        'https://billapi.oneclickdz.com/v3/partners',
        headers={'X-Access-Token': os.getenv('ONECLICKDZ_API_KEY')}
    )

    body = response.json()
    if not body['success']:
        raise RuntimeError(body['error']['code'])

    available = [
        name for name, partner in body['data'].items()
        if partner['status'] == 'ACTIVE'
    ]

    print(available)
    ```

    ```php PHP theme={null}
    <?php
    $ch = curl_init('https://billapi.oneclickdz.com/v3/partners');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-Access-Token: ' . getenv('ONECLICKDZ_API_KEY')
    ]);

    $body = json_decode(curl_exec($ch), true);
    curl_close($ch);

    if (!$body['success']) {
        throw new Exception($body['error']['code']);
    }

    $available = array_keys(array_filter(
        $body['data'],
        fn($partner) => $partner['status'] === 'ACTIVE'
    ));

    print_r($available);
    ?>
    ```
  </CodeGroup>

  ```json theme={null}
  {
    "success": true,
    "data": {
      "ADE": { "status": "ACTIVE" },
      "SONELGAZ": { "status": "ACTIVE" },
      "SEAAL": { "status": "UNAVAILABLE" },
      "AADL": { "status": "UNAVAILABLE" },
      "Algérie Télécom": { "status": "ACTIVE" }
    },
    "meta": { "timestamp": "2026-08-31T10:15:32.194Z" },
    "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
  }
  ```

  مُصدِر الفاتورة المُعلَّم بـ `UNAVAILABLE` يُجيب بـ `503 PARTNER_UNAVAILABLE` عند الاستكشاف وعند الدفع. و`SEAAL` و`AADL` حالياً `UNAVAILABLE` في كل من sandbox والإنتاج — وهذا هو الإعداد الحالي للمشغّل، لا قيد دائم، لذا أبقِهما في الكود ودع الخريطة تقرر ما يُعرض.

  <Warning>
    مفتاح `PRODUCTION` يرى التوفر الفعلي؛ أما مفتاح `SANDBOX` فيرى خريطة ثابتة، لأن طلب sandbox لا يصل أبداً إلى مُصدِر فاتورة. لا تستخدم sandbox لاختبار كيفية تفاعل تطبيقك مع تعطّل مُصدِر فاتورة — استخدم [سيناريوهات sandbox](/ar/bill-payment-guides/6-sandbox-testing) المخصصة لذلك.
  </Warning>

  ## المعرّف الخاص بكل مُصدِر فاتورة

  أرسل معرّفاً واحداً بالضبط، وأرسل الحقل الذي يخص مُصدِر الفاتورة الذي تستعلم عنه. تُعيد API الحقل نفسه إليك في `account` في كل معاملة تخص ذلك المُصدِر.

  | الشريك            | الحقل            | الصيغة                                       | مثال صالح                     |
  | ----------------- | ---------------- | -------------------------------------------- | ----------------------------- |
  | `ADE`             | `reference`      | حتى 50 حرفاً                                 | `"0123456789012345678901234"` |
  | `SEAAL`           | `reference`      | حتى 50 حرفاً                                 | `"0123456789012340000000000"` |
  | `SONELGAZ`        | `contractNumber` | حتى 50 حرفاً                                 | `"9876543210"`                |
  | `AADL`            | `aadlNumber`     | حتى 50 حرفاً                                 | `"1112223334"`                |
  | `Algérie Télécom` | `phoneNumber`    | `0` أو `+213`، ثم رقم من 2 إلى 4، ثم 7 أرقام | `"023456789"`                 |

  ```json theme={null}
  {
    "partner": "ADE",
    "account": { "reference": "0123456789012345678901234" },
    "ref": "disc-inv-2026-0042"
  }
  ```

  <Note>
    أرسل `Algérie Télécom` بعلامات التشكيل الفرنسية كما هي. تُقارَن القيمة حرفاً بحرف، وهي أيضاً المفتاح الذي تقرأه من خريطة الشركاء.
  </Note>

  ### أرقام الهاتف الثابت

  `phoneNumber` هو رقم **هاتف ثابت** جزائري، لا رقم هاتف محمول.

  **صالح:**

  * `"023456789"` — صفر في البداية، ثم رقم في المجال 2–4
  * `"+213023456789"` غير صالح؛ استخدم `"+21323456789"` أو الصيغة المحلية `"023456789"`

  **غير صالح:**

  * `"0778037340"` — رقم هاتف محمول، لا رقم هاتف ثابت
  * `"23456789"` — ينقصه الصفر في البداية
  * `"023 45 67 89"` — يحتوي على مسافات
  * `23456789` — رقم بدلاً من سلسلة نصية

  ### صيغ المعرّف الأكثر تفصيلاً

  يقبل مُصدِرا فاتورة كائناً أكمل عندما لا يكفي رقم واحد لتحديد فاتورة بعينها. وكل حقل داخل هذه الكائنات مطلوب.

  <AccordionGroup>
    <Accordion title="SONELGAZ — صيغة الفاتورة" icon="bolt">
      ```json theme={null}
      {
        "partner": "SONELGAZ",
        "account": {
          "sonelgaz": {
            "invoice_number": "9876543210",
            "amount_without_stamp": "15000",
            "ebb_key": "ABC123"
          }
        },
        "ref": "disc-inv-2026-0042"
      }
      ```

      `invoice_number` حتى 20 حرفاً، و`amount_without_stamp` حتى 20، و`ebb_key` حتى 30.
    </Accordion>

    <Accordion title="ADE — صيغة الفاتورة" icon="file-lines">
      ```json theme={null}
      {
        "partner": "ADE",
        "account": {
          "ade": {
            "sub_id": "000123456789",
            "period": "07/2026",
            "amount": "12000",
            "pay_key": "1234567"
          }
        },
        "ref": "disc-inv-2026-0043"
      }
      ```

      `sub_id` بطول 12 حرفاً بالضبط، و`period` بصيغة `MM/YYYY`، و`amount` حتى 20 حرفاً، و`pay_key` بطول 7 أحرف بالضبط.
    </Accordion>

    <Accordion title="ADE وSEAAL — مفتاح من 25 حرفاً" icon="key">
      يُقبل `electronic_payment_key` كبديل عن `reference`، ويجب أن يكون **بطول 25 حرفاً بالضبط**.

      ```json theme={null}
      {
        "partner": "ADE",
        "account": { "electronic_payment_key": "0123456789012345678901234" },
        "ref": "disc-inv-2026-0044"
      }
      ```
    </Accordion>
  </AccordionGroup>

  ## معرّف واحد بالضبط

  يجب أن يحمل كائن `account` معرّفاً **واحداً** لا أكثر. وتنقسم الحقول إلى أربع خانات:

  | الخانة              | الحقول                                                                |
  | ------------------- | --------------------------------------------------------------------- |
  | مفتاح من نمط المرجع | `reference`، `contractNumber`، `aadlNumber`، `electronic_payment_key` |
  | الهاتف الثابت       | `phoneNumber`، `phone_number`                                         |
  | فاتورة SONELGAZ     | `sonelgaz`                                                            |
  | فاتورة ADE          | `ade`                                                                 |

  يجب ملء خانة واحدة بالضبط. أما صفر أو اثنتان فيُرفض الطلب قبل أن يحدث أي شيء آخر.

  ```json theme={null}
  {
    "partner": "ADE",
    "account": {
      "reference": "0123456789012345678901234",
      "phoneNumber": "023456789"
    },
    "ref": "disc-inv-2026-0045"
  }
  ```

  ```json theme={null}
  {
    "success": false,
    "error": {
      "code": "ERR_VALIDATION",
      "message": "account must contain exactly one identifier (electronic_payment_key, phone_number, sonelgaz, or ade)",
      "details": [
        "account must contain exactly one identifier (electronic_payment_key, phone_number, sonelgaz, or ade)"
      ]
    },
    "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
  }
  ```

  التحقق من ذلك في جانبك يكون بسطر واحد، وهو يحوّل رحلة ذهاب وإياب إلى خطأ فوري في النموذج:

  ```javascript theme={null}
  const SLOTS = [
    ["reference", "contractNumber", "aadlNumber", "electronic_payment_key"],
    ["phoneNumber", "phone_number"],
    ["sonelgaz"],
    ["ade"],
  ];

  function hasExactlyOneIdentifier(account) {
    const filled = SLOTS.filter((slot) =>
      slot.some((field) => {
        const value = account[field];
        return value !== undefined && value !== null && value !== "";
      }),
    );

    return filled.length === 1;
  }
  ```

  ## `ERR_VALIDATION` أم `INVALID_ACCOUNT`؟

  كلاهما `400`، لكن معنييهما مختلفان جداً.

  |                          | `ERR_VALIDATION`                                                                                  | `INVALID_ACCOUNT`                           |
  | ------------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------- |
  | السبب                    | الطلب لا يطابق المخطط                                                                             | المعرّف سليم الصيغة لكنه غير قابل للاستخدام |
  | أمثلة                    | غياب `ref`؛ وجود معرّفين؛ `electronic_payment_key` بطول 24 حرفاً؛ رقم هاتف محمول في `phoneNumber` | رقم حساب لا يتعرف عليه مُصدِر الفاتورة      |
  | خطأ من                   | خطأ تكاملك أنت                                                                                    | خطأ في كتابة عميلك                          |
  | إظهاره للعميل            | لا — سجّله فقط                                                                                    | نعم — "تحقق من الرقم المدوَّن على فاتورتك"  |
  | إعادة المحاولة دون تغيير | أبداً                                                                                             | فقط بعد أن يصحح العميل الرقم                |

  <Warning>
    لا تعرض رسائل `ERR_VALIDATION` على العملاء النهائيين. فهي تذكر أسماء حقول داخلية مثل `electronic_payment_key`، وهو ما لا يعني شيئاً لشخص يمسك بفاتورة ورقية.
  </Warning>

  ## تخزين خريطة الشركاء في الكاش

  يتغير التوفر نادراً، لذا حدّثه على فترات زمنية بدلاً من تحديثه قبل كل استكشاف — واستمر في تقديم آخر نسخة صالحة إذا فشل التحديث. فقائمة مُصدِري فواتير فارغة أسوأ لعملائك من قائمة قديمة قليلاً.

  ```javascript theme={null}
  let cache = { map: null, fetchedAt: 0 };
  const TTL_MS = 5 * 60 * 1000;

  async function getPartners() {
    if (cache.map && Date.now() - cache.fetchedAt < TTL_MS) return cache.map;

    try {
      const response = await fetch("https://billapi.oneclickdz.com/v3/partners", {
        headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
      });

      const body = await response.json();
      if (body.success) cache = { map: body.data, fetchedAt: Date.now() };
    } catch {
      // Serve the previous map rather than blocking the customer.
    }

    return cache.map ?? {};
  }
  ```

  <Note>
    التخزين في الكاش لا يُغني عن معالجة `503 PARTNER_UNAVAILABLE` عند الاستكشاف. فقد يتعطل مُصدِر فاتورة بين آخر تحديث لك وضغط العميل على الزر.
  </Note>

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

  <CardGroup cols={2}>
    <Card title="تحقق قبل أن ترسل" icon="circle-check">
      تحقق من قاعدة الخانة الواحدة ومن صيغة الهاتف الثابت في جانب العميل. فذلك يوفّر رحلة ذهاب وإياب ويعطي رسالة خطأ أفضل.
    </Card>

    <Card title="خزّن الخريطة في الكاش لدقائق، لا لساعات" icon="database">
      خمس دقائق كافية تماماً. حدّثها في الخلفية، لا على المسار الحرج للعميل أبداً.
    </Card>

    <Card title="أبقِ مُصدِري الفواتير غير المتاحين في كودك" icon="toggle-on">
      سيعود `SEAAL` و`AADL`. اجعل واجهتك تُقاد من الخريطة، لا من قائمة مرمّزة بشكل ثابت.
    </Card>

    <Card title="فرّق بين خطأي 400" icon="arrows-split">
      `INVALID_ACCOUNT` رسالة موجهة لعميلك. أما `ERR_VALIDATION` فرسالة موجهة لسجلاتك.
    </Card>
  </CardGroup>

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

  <Card title="الخطوة 2: استكشاف الفواتير" icon="magnifying-glass-dollar" href="/ar/bill-payment-guides/2-discovering-bills">
    أرسل استكشافاً، وتابعه حتى `READY`، واقرأ ما هو قابل للدفع
  </Card>

  ## صفحات ذات صلة

  <CardGroup cols={2}>
    <Card title="سرد الشركاء" icon="building-columns" href="/ar/api-reference/bill-payment/list-partners">
      مرجع الـ endpoint
    </Card>

    <Card title="استكشاف الفواتير" icon="magnifying-glass-dollar" href="/ar/api-reference/bill-payment/discover-bills">
      حيث يُرسَل كائن الحساب
    </Card>

    <Card title="نظرة عامة على دفع الفواتير" icon="file-invoice-dollar" href="/ar/bill-payment-guides/overview">
      خريطة الخطوات الخمس
    </Card>

    <Card title="اختبار Sandbox" icon="flask" href="/ar/bill-payment-guides/6-sandbox-testing">
      معرّفات تُنتج نتيجة تختارها
    </Card>
  </CardGroup>
</div>
