# واجهة WhatsApp

يستطيع تطبيقك إرسال رسائل `WhatsApp` إلى مشتري المتجر عبر أربع نقاط وصول. تستعمل الرسائل قوالب الطلبات التي اعتمدتها `Meta` لـ `DZBuild`، وتُدفع كل رسالة من رصيد `WhatsApp` الخاص بالمتجر، تمامًا مثل الرسائل التي ترسلها إضافة `WhatsApp Sender` تلقائيًا. لا يمكنك إرسال نص حر ولا قوالبك الخاصة.

المرجع الكامل للطلبات والردود موجود في وصف `OpenAPI`، ورابطه في صفحة [مرجع الواجهة البرمجية](https://dzbuild.dev/ar/ar/api-reference.md). تشرح هذه الصفحة كيف تترابط هذه الأجزاء.

## الصلاحيات[​](#الصلاحيات "رابط مباشر إلى الصلاحيات")

| الصلاحية        | تسمح بـ                                                                               |
| --------------- | ------------------------------------------------------------------------------------- |
| `whatsapp:read` | `GET /v1/whatsapp/templates`، `GET /v1/whatsapp/balance`، `GET /v1/whatsapp/messages` |
| `whatsapp:send` | `POST /v1/orders/{id}/whatsapp`                                                       |

لا تطلب في رابط التفويض إلا الصلاحيات التي تحتاجها. الطلب الذي تنقصه الصلاحية يُجاب بـ `403` مع رمز الخطأ `forbidden` والرسالة `Missing scope: whatsapp:send` (أو `whatsapp:read`). راجع [الصلاحيات](https://dzbuild.dev/ar/ar/scopes.md).

## القوالب[​](#القوالب "رابط مباشر إلى القوالب")

تعرض `GET /v1/whatsapp/templates` القوالب الستة. تقرأ حالة الاعتماد التي تحفظها `DZBuild` ولا تتصل بـ `Meta` أبدًا.

| المفتاح           | يُرسل عندما                            |
| ----------------- | -------------------------------------- |
| `received`        | استُلم الطلب.                          |
| `confirmed`       | أُكّد الطلب.                           |
| `shipped_home`    | الطرد في الطريق إلى عنوان المشتري.     |
| `shipped_desk`    | الطرد في الطريق إلى مكتب شركة التوصيل. |
| `delivery_failed` | فشلت محاولة التوصيل.                   |
| `desk_ready`      | الطرد جاهز للاستلام.                   |

يحمل كل عنصر `key` و`name` (اسم القالب لدى `Meta`، مثل `dz_order_confirmed`) و`toggle` (زر التفعيل المقابل لدى التاجر في الإضافة) و`languages`. يحتوي كل من `languages.ar` و`languages.fr` على `body` بمتغيّراته، و`example`، و`status`. لا يُرسل القالب إلا بلغة حالتها `APPROVED`. وتعني `UNKNOWN` أن `DZBuild` لا تملك بعدُ أي حالة محفوظة.

## الرصيد[​](#الرصيد "رابط مباشر إلى الرصيد")

تُرجع `GET /v1/whatsapp/balance`:

| الحقل          | المعنى                                                                                                                                          |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `balance`      | عدد الرسائل المتبقية في رصيد المتجر. كل رسالة تكلّف رصيدًا واحدًا.                                                                              |
| `low_balance`  | `true` عندما يبقى أقل من 50 رسالة.                                                                                                              |
| `addon_active` | هل فعّل التاجر إضافة `WhatsApp Sender`.                                                                                                         |
| `stats`        | عدد الرسائل خلال آخر 30 يومًا حسب الحالة (`sent`، `delivered`، `read`، `failed`) و`used_month`، أي الرصيد المستهلك منذ أول يوم من الشهر الجاري. |

يشحن التاجر رصيده من لوحة تحكم `DZBuild`. لا يستطيع تطبيقك إضافة رصيد.

## إرسال رسالة[​](#إرسال-رسالة "رابط مباشر إلى إرسال رسالة")

تضع `POST /v1/orders/{id}/whatsapp` قالبًا واحدًا لطلب واحد من طلبات المتجر في طابور الإرسال. هي عملية كتابة، لذا تحتاج ترويسة `Idempotency-Key` (راجع [حدود معدّل الطلبات](https://dzbuild.dev/ar/ar/rate-limits.md)).

```
POST /v1/orders/98765/whatsapp HTTP/1.1

Host: api.dzbuild.app

Authorization: Bearer dzpk_live_xxxxxxxx

Idempotency-Key: wa-98765-confirmed

Content-Type: application/json



{"template": "confirmed", "language": "fr"}
```

| حقل الجسم  | إلزامي | المعنى                                                                                                                                                                                       |
| ---------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `template` | نعم    | أحد المفاتيح الستة، أو `shipped`. يختار `shipped` القالب المناسب حسب نوع توصيل الطلب: `shipped_home` للتوصيل إلى المنزل، `shipped_desk` للمكتب، `desk_ready` للاستلام.                       |
| `language` | لا     | `ar` أو `fr`. من دونه تُستعمل اللغة المضبوطة في إضافة `WhatsApp Sender` للمتجر، أو لغة المتجر إن لم تكن الإضافة مضبوطة. وإن لم تكن هذه اللغة البديلة `ar` ولا `fr`، تُرسَل الرسالة بالعربية. |

الإرسال اليدوي يتجاهل أزرار الإرسال التلقائي التي ضبطها التاجر في الإضافة. لكن يجب أن تكون الإضافة نفسها مفعّلة في المتجر.

يُجاب الطلب بـ `202` عندما تدخل الرسالة الطابور ويُخصم الرصيد:

```
{

  "data": { "message_id": 4411, "status": "queued", "template": "confirmed", "language": "fr" },

  "meta": { "request_id": "8f2c1a9d4b7e6035", "api_version": "v1" }

}
```

ترسل `DZBuild` الرسائل الموجودة في الطابور في الخلفية. تابع النتيجة عبر `GET /v1/whatsapp/messages`.

## الردود ورموز الأخطاء[​](#الردود-ورموز-الأخطاء "رابط مباشر إلى الردود ورموز الأخطاء")

| الحالة | رمز الخطأ               | المعنى                                                                               |
| ------ | ----------------------- | ------------------------------------------------------------------------------------ |
| `202`  |                         | في الطابور، وخُصم رصيد واحد.                                                         |
| `400`  | `bad_request`           | معرّف الطلب ليس رقمًا، أو الجسم ليس `JSON` صالحًا.                                   |
| `402`  | `no_credit`             | رصيد `WhatsApp` للمتجر فارغ. لم يدخل شيء الطابور ولم يُخصم شيء.                      |
| `403`  | `addon_not_active`      | لم يفعّل التاجر إضافة `WhatsApp Sender`.                                             |
| `403`  | `forbidden`             | الرمز لا يملك `whatsapp:send`.                                                       |
| `404`  | `not_found`             | لا يوجد طلب بهذا المعرّف في هذا المتجر.                                              |
| `409`  | `already_sent`          | أُرسل هذا القالب من قبل لهذا الطلب. يحمل كائن الخطأ `id` و`status` الرسالة الموجودة. |
| `422`  | `unknown_template`      | قيمة `template` ليست من المفاتيح المقبولة.                                           |
| `422`  | `invalid_language`      | قيمة `language` ليست `ar` ولا `fr`.                                                  |
| `422`  | `invalid_number`        | هاتف المشتري ليس رقم هاتف محمول جزائريًا صالحًا.                                     |
| `422`  | `suppressed`            | رقم المشتري محظور من رسائل `WhatsApp` على المنصة.                                    |
| `422`  | `template_not_approved` | القالب غير معتمد بهذه اللغة.                                                         |
| `422`  | `empty_param`           | قيمة يحتاجها القالب فارغة في الطلب.                                                  |
| `500`  | `send_failed`           | تعذّر إدخال الرسالة إلى الطابور. أعد المحاولة لاحقًا.                                |

يمكن إرسال كل قالب مرة واحدة لكل طلبية عبر الواجهة البرمجية. أي استدعاء لاحق للقالب نفسه والطلبية نفسها يُجاب بـ `409`، حتى لو فشلت الرسالة الأولى. أما ردود `422` من `invalid_number` إلى `empty_param` فمختلفة: لم يُخصم شيء، والاستدعاء الموالي لذلك القالب وتلك الطلبية يعيد المحاولة. أصلح السبب (رقم الهاتف في الطلبية مثلًا)، ثم أعد الاستدعاء بقيمة `Idempotency-Key` جديدة.

## سجل الرسائل[​](#سجل-الرسائل "رابط مباشر إلى سجل الرسائل")

تعرض `GET /v1/whatsapp/messages` رسائل المتجر من الأحدث إلى الأقدم. معاملات الاستعلام: `order_id` لتصفية طلب واحد، و`limit` (50 افتراضيًا، 200 كحد أقصى)، و`cursor` (قيمة `next_cursor` من الصفحة السابقة). لا يُرجع رقم هاتف المشتري أبدًا.

| الحقل           | المعنى                                                                                                                                                     |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`            | معرّف الرسالة، وهو نفس `message_id` في رد الإرسال.                                                                                                         |
| `order_id`      | الطلب.                                                                                                                                                     |
| `event`         | مفتاح القالب للرسائل المرسلة عبر الواجهة البرمجية، أو حدث الإضافة (`received`، `confirmed`، `shipped`، `delivery_failed`، `desk_ready`) للرسائل التلقائية. |
| `source`        | `api` للرسائل المرسلة عبر الواجهة البرمجية، و`auto` للرسائل التلقائية من الإضافة.                                                                          |
| `status`        | `queued` أو `sending` أو `sent` أو `delivered` أو `read` أو `failed` أو `skipped`.                                                                         |
| `language`      | `ar` أو `fr`.                                                                                                                                              |
| `template_name` | اسم القالب لدى `Meta`.                                                                                                                                     |
| `error_title`   | سبب فشل الرسالة أو تخطيها، أو `null`.                                                                                                                      |
| `refunded`      | `true` عندما يُعاد الرصيد.                                                                                                                                 |
| `billing`       | `charged` عندما يفوتر WhatsApp الرسالة، و`free` عندما يعود رصيدها، و`null` ما دام WhatsApp لم يبلّغ عن النتيجة.                                            |
| `created_at`    | وقت دخول الرسالة إلى الطابور.                                                                                                                              |

الرسالة التي تفشل، أو لا تصل خلال 30 يوماً، أو تصل دون أن يفوترها WhatsApp، يُعاد رصيدها مرة واحدة: تصبح `refunded` هي `true` و`billing` هي `free`. الرسالة التي يفوترها WhatsApp تستقر على `charged`.
