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

  يبثّ إيصال مُصدِر الفواتير لفاتورة مدفوعة. وهو endpoint دفع الفواتير الوحيد الذي لا يُرجع JSON عند النجاح — فمتن الاستجابة هو الملف الخام نفسه.

  لا توجد الإيصالات إلا للمعاملات التي تكون `status` فيها `SUCCESS`. وأي حالة أخرى — معاملة ما زالت جارية، أو فاشلة، أو مستردة، أو تخصّ شريكًا آخر — تُجيب بغلاف خطأ JSON المعتاد مع `404 NOT_FOUND`.

  <Note>
    `receiptUrl` في معاملة ناجحة هو هذا endpoint بالضبط. وهو لا يزال يحتاج إلى ترويسة `X-Access-Token` الخاصة بك، لذلك فهو **ليس** رابطًا يمكنك إعطاؤه لعميل أو تضمينه في بريد إلكتروني. نزّل البايتات، وخزّنها، وقدّمها من نظامك أنت.
  </Note>

  ## معاملات المسار

  <ParamField path="transactionId" type="string" required>
    معرّف المعاملة. سلسلة سداسية عشرية من 24 حرفًا بأحرف صغيرة، من [الحصول على معاملة بالمعرّف](/ar/api-reference/bill-payment/check-by-id) أو من أي قائمة.
  </ParamField>

  ## الاستجابة

  عند النجاح يكون المتن هو الملف نفسه. اقرأ ترويسات الاستجابة لتعرف ما الذي تلقّيته.

  <ResponseField name="Content-Type" type="header" required>
    نوع وسائط الملف: `application/pdf` أو `image/png` أو `image/jpeg`. وأي شيء لا نستطيع تحديده يُقدَّم على أنه `application/octet-stream`.

    **تفرّع دائمًا بناءً على هذه الترويسة** بدلًا من افتراض أنه PDF.
  </ResponseField>

  <ResponseField name="Content-Disposition" type="header" required>
    `attachment; filename="..."` — اسم الملف المقترح، بالامتداد المطابق لـ `Content-Type`.
  </ResponseField>

  <ResponseField name="Content-Length" type="header" required>
    حجم الملف بالبايت.
  </ResponseField>

  <ResponseField name="Cache-Control" type="header" required>
    `private, max-age=86400`. الإيصال يخصّ شريكًا واحدًا؛ لا تخزّنه أبدًا في ذاكرة تخزين مؤقت مشتركة أو عامة.
  </ResponseField>

  <ResponseField name="X-Content-Type-Options" type="header" required>
    `nosniff`.
  </ResponseField>

  <ResponseField name="X-Request-Id" type="header" required>
    معرّف الربط لهذا الطلب. لا يوجد متن JSON عند النجاح، لذا فإن هذه الترويسة هي المكان الوحيد الذي يظهر فيه — سجّله.
  </ResponseField>

  ## الأمثلة

  يتحقق كل مثال من الحالة قبل كتابة أي شيء، ويأخذ امتداد الملف من الاستجابة بدلًا من افتراضه.

  <CodeGroup>
    ```bash cURL theme={null}
    # -J -O writes the file under the name the server suggests
    curl https://billapi.oneclickdz.com/v3/bills/transactions/68b2f4c1a7d3e9f204c81a55/receipt \
      -H "X-Access-Token: YOUR_API_KEY" \
      --fail \
      --remote-header-name --remote-name
    ```

    ```javascript Node.js theme={null}
    import { writeFile } from "node:fs/promises";

    const transactionId = "68b2f4c1a7d3e9f204c81a55";

    const response = await fetch(
      `https://billapi.oneclickdz.com/v3/bills/transactions/${transactionId}/receipt`,
      { headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY } },
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`${error.error.code}: ${error.error.message}`);
    }

    const contentType = response.headers.get("content-type");
    const extension = contentType.includes("pdf")
      ? "pdf"
      : contentType.includes("png")
        ? "png"
        : contentType.includes("jpeg")
          ? "jpg"
          : "bin";

    const bytes = Buffer.from(await response.arrayBuffer());
    await writeFile(`receipt-${transactionId}.${extension}`, bytes);

    console.log(response.headers.get("x-request-id"), bytes.length);
    ```

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

    transaction_id = '68b2f4c1a7d3e9f204c81a55'

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

    if response.status_code != 200:
        error = response.json()
        raise RuntimeError(f"{error['error']['code']}: {error['error']['message']}")

    content_type = response.headers.get('Content-Type', '')
    extension = (
        'pdf' if 'pdf' in content_type
        else 'png' if 'png' in content_type
        else 'jpg' if 'jpeg' in content_type
        else 'bin'
    )

    with open(f'receipt-{transaction_id}.{extension}', 'wb') as handle:
        handle.write(response.content)

    print(response.headers.get('X-Request-Id'), len(response.content))
    ```

    ```php PHP theme={null}
    <?php
    $transactionId = '68b2f4c1a7d3e9f204c81a55';

    $ch = curl_init("https://billapi.oneclickdz.com/v3/bills/transactions/$transactionId/receipt");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-Access-Token: ' . getenv('ONECLICKDZ_API_KEY')
    ]);

    $bytes  = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $type   = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    curl_close($ch);

    if ($status !== 200) {
        $error = json_decode($bytes, true);
        throw new Exception($error['error']['code'] . ': ' . $error['error']['message']);
    }

    $extension = str_contains($type, 'pdf') ? 'pdf'
        : (str_contains($type, 'png') ? 'png'
        : (str_contains($type, 'jpeg') ? 'jpg' : 'bin'));

    file_put_contents("receipt-$transactionId.$extension", $bytes);

    echo strlen($bytes);
    ?>
    ```
  </CodeGroup>

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

  المتن ثنائي. وتبدو الترويسات هكذا:

  ```http theme={null}
  HTTP/1.1 200 OK
  Content-Type: application/pdf
  Content-Length: 48211
  Content-Disposition: attachment; filename="receipt-68b2f4c1a7d3e9f204c81a55.pdf"
  Cache-Control: private, max-age=86400
  X-Content-Type-Options: nosniff
  X-Request-Id: req_9f3a1c72e0b84d51aB3xZq07
  ```

  ## استجابات الخطأ

  تُرجَع الأخطاء بصيغة JSON، في الغلاف نفسه المستخدم مع كل endpoint آخر.

  <AccordionGroup>
    <Accordion title="401 — رمز وصول مفقود أو غير صالح">
      **كان المفتاح غائبًا أو مرفوضًا.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "INVALID_ACCESS_TOKEN",
          "message": "The provided access token is invalid."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** تحقّق من المفتاح باستخدام [التحقق من مفتاح API](/ar/api-reference/bill-payment/validate-key).
    </Accordion>

    <Accordion title="404 — لا يوجد إيصال متاح">
      **إما أن المعاملة ليست لك في هذه البيئة، وإما أنه لا إيصال لها.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "NOT_FOUND",
          "message": "Receipt not available for this transaction."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      لا يوجد الإيصال إلا بعد أن تصل عملية الدفع إلى `SUCCESS`. التنزيل بينما المعاملة `PROCESSING` يُرجع هذا، وكذلك معاملة `FAILED` أو `REFUNDED` — فلا إيصال لأيٍّ منهما لأنه لم تكتمل أي عملية دفع.

      **ما العمل:** اقرأ المعاملة أولًا، ولا تنزّل إلا عندما تكون `status` هي `SUCCESS` وتكون `receiptUrl` موجودة.
    </Accordion>

    <Accordion title="503 — المصادقة أو الخدمة غير متاحة">
      **لم نتمكن من التحقق من مفتاحك في الوقت المناسب، أو أن الواجهة في صيانة مُخطّط لها.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "AUTH_UNAVAILABLE",
          "message": "Authentication is temporarily unavailable. Please retry shortly."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** التزم بترويسة `Retry-After` (5 ثوانٍ) وأعد المحاولة. تكرار التنزيل آمن.
    </Accordion>

    <Accordion title="500 — خطأ داخلي">
      **تعذّرت قراءة الإيصال.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "INTERNAL_ERROR",
          "message": "An unexpected error occurred."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** أعد المحاولة مرة واحدة، ثم تواصل مع الدعم مع ذكر `requestId`. عملية الدفع نفسها غير متأثرة — فالمعاملة لا تزال `SUCCESS`.
    </Accordion>
  </AccordionGroup>

  ## التنزيل في اللحظة الصحيحة

  اجلب الإيصال فور وصول عملية الدفع إلى `SUCCESS`، في الخطوة نفسها التي تسجّل فيها النجاح لديك.

  ```javascript theme={null}
  async function settle(transactionId) {
    const response = await fetch(
      `https://billapi.oneclickdz.com/v3/bills/transactions/${transactionId}`,
      { headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY } },
    );

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

    const transaction = body.data;
    if (transaction.status !== "SUCCESS") return transaction.status;

    // operationId is the biller's proof; the receipt is the document for it.
    await saveOrder({
      transactionId: transaction.transactionId,
      operationId: transaction.operationId,
      total: transaction.total,
    });

    await downloadReceipt(transactionId);

    return "SUCCESS";
  }
  ```

  <Warning>
    خزّن البايتات، لا عنوان URL. يتطلب `receiptUrl` مفتاح API الخاص بك، لذا فالرابط المخزَّن عديم الفائدة لعميلك وخطر على المشاركة.
  </Warning>

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

  <CardGroup cols={2}>
    <Card title="نزّل مرة واحدة، وخزّن إلى الأبد" icon="box-archive">
      احتفظ بالإيصال مع سجل طلبك الخاص. فهو المستند الذي تُحسم به منازعة العميل.
    </Card>

    <Card title="اقرأ Content-Type" icon="file-lines">
      الإيصال ملف PDF أو صورة بحسب مُصدِر الفواتير. خذ الامتداد من الترويسة.
    </Card>

    <Card title="لا تكشف عنوان URL أبدًا" icon="shield-halved">
      قدّم الإيصالات من نظامك أنت، خلف مصادقتك أنت.
    </Card>

    <Card title="اقرنه بـ operationId" icon="receipt">
      الإيصال هو المستند؛ و`operationId` هو المرجع. خزّن كليهما.
    </Card>
  </CardGroup>

  ## Endpoints ذات الصلة

  <CardGroup cols={2}>
    <Card title="الحصول على معاملة بالمعرّف" icon="id-card" href="/ar/api-reference/bill-payment/check-by-id">
      حيث يظهر `receiptUrl` و`operationId`
    </Card>

    <Card title="قائمة المعاملات" icon="list" href="/ar/api-reference/bill-payment/list-transactions">
      اعثر على كل ما دُفع في فترة ما
    </Card>

    <Card title="دفع فاتورة" icon="money-bill-transfer" href="/ar/api-reference/bill-payment/pay-bill">
      عملية الدفع التي أنتجته
    </Card>

    <Card title="الإيصالات والتسوية" icon="scale-balanced" href="/ar/bill-payment-guides/5-receipts-and-reconciliation">
      تخزين الإيصالات وتسويتها
    </Card>
  </CardGroup>
</div>
