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

DZBuild POS

DZBuild POS هو برنامج صندوق مجاني على ويندوز للمحلات التي تبيع أيضاً عبر الإنترنت. يعمل دون اتصال، وبعد ربطه يبقى متزامناً مع متجر DZBuild واحد أو أكثر. تذكر هذه الصفحة النداءات التي يرسلها الصندوق المرتبط، ليعرف فريق الدعم والشركاء ما يستطيع الصندوق فعله وما لا يستطيعه.

لا تجيب هذه النقاط إلا الرموز الصادرة للصندوق. مفتاح API الشخصي أو رمز التطبيق يتلقى 403 على المسارات الخاصة بالصندوق، ورمز الصندوق يتلقى 403 على كل مسار خارج قائمته.

لمن هو​

  • لأصحاب المتاجر الذين يبيعون في محل وفي متجرهم على DZBuild. صاحب المتجر وحده يستطيع ربط صندوق؛ أعضاء الفريق لا يستطيعون.
  • لكل الخطط. الصندوق ليس مفتاح API، فلا يحتاج خطة Enterprise ولا يأخذ مكان مفتاح.
  • بعد تسجيل أول صندوق تظهر إضافة DZBuild POS في لوحة التحكم مع الصناديق المرتبطة وزر الفصل وآخر المبيعات والمرتجعات وإغلاقات Z. الرابط https://dzbuild.com/dashboard/connected-devices يفتح هذه الصفحة.

كيف يرتبط الصندوق​

  • الاكتشاف: GET https://dzbuild.com/.well-known/oauth-authorization-server (RFC 8414).
  • الصندوق عميل OAuth 2.0 عام اسمه dzbuild-pos-windows، بلا سرّ. يُقبل S256 وحده في PKCE، والتحويل يكون إلى http://127.0.0.1:PORT/oauth/callback على أي منفذ.
  • يدخل صاحب المتجر من متصفح النظام ويختار المتاجر التي يستعملها الصندوق، حتى 10 متاجر. ويمكن ربط الصندوق برمز أيضاً: يعرض الصندوق رمزاً، ويكتبه صاحب المتجر في https://dzbuild.com/device من هاتفه.
  • رمز الوصول يبدأ بـ dzpos_ ويدوم 15 دقيقة. رمز التحديث يُستبدل عند كل استعمال وينتهي بعد 30 يوماً دون استعمال أو 180 يوماً في المجموع. إرسال رمز تحديث قديم من جديد ينهي الربط.
  • كل نداء يحمل X-DZ-Store مع رقم المتجر، ما عدا GET /v1/me. المتجر الذي لم يختره صاحبه يُرجع 403.
  • كل POST وPATCH وDELETE يحمل Idempotency-Key، بالقواعد المذكورة في التكرار الآمن.
  • الحدود: 120 طلباً في الدقيقة لكل صندوق و600 لكل متجر. حصة الواجهة البرمجية الشهرية لا تنطبق على الصناديق.
  • فصل الصندوق من لوحة التحكم ينهي الربط: التحديث التالي يُرجع 400 invalid_grant ونبضة الاتصال التالية 410 device_revoked.

الصلاحيات الـ 19​

يطلب الصندوق الصلاحيات الـ 19 دائماً، وتمنحها DZBuild كلها دائماً.

الصلاحياتما يستطيعه الصندوق
openid وprofile وoffline_accessمعرفة من ربطه والبقاء مرتبطاً
store:readقراءة متاجر الربط ولغتها وخطتها وحدّ منتجاتها
products:read وproducts:writeقراءة المنتجات وإنشاؤها وتعديلها على دفعات وإضافة الصور
inventory:read وinventory:writeقراءة مخزون المنتجات وتعديله
orders:read وorders:writeاستقبال طلبات المتجر وأخذ طلب وتحريكه وإلغاؤه
customers:readالتحقق من رقم هاتف قبل البيع
pos:sales:read وpos:sales:writeتسجيل المبيعات والمرتجعات وإغلاقات Z
locations:read وlocations:writeتسجيل المحل الذي يوجد فيه الصندوق
backups:read وbackups:writeمحجوزة: النسخ الاحتياطية غير متاحة
devices:selfتسجيل الصندوق وإرسال نبضات الاتصال وفك الربط
events:readقراءة تدفق التغييرات

النقاط​

الطريقة والمسارما تفعله
GET /v1/meصاحب المتجر ومتاجر الربط
GET /v1/storeالمتجر المختار: الاسم واللغة والعملة DZD وتوقيت خصم المخزون والخطة وحدّ المنتجات
POST /v1/devices وGET /v1/devicesتسجيل الصندوق (سطر واحد لكل صندوق ومتجر) وعرض الصناديق
POST /v1/devices/{id}/heartbeatكل 15 دقيقة: الإصدار والإرسالات المنتظرة والفاشلة
DELETE /v1/devices/{id}فك ربط هذا الصندوق
GET /v1/locations وPOST /v1/locationsالمحل الذي يوجد فيه الصندوق
POST /v1/products/batchإنشاء أو تعديل حتى 100 منتج
GET /v1/products وGET /v1/products/{id}المنتجات المعدّلة منذ تاريخ معيّن، ومنتج واحد
POST /v1/media/uploads وPOST /v1/products/{id}/imagesتذكرة الصورة، ثم ربط الصورة المرفوعة
POST /v1/inventory/adjustments/batchحتى 500 تثبيت أو تغيير للمخزون
POST /v1/pos/sales وPOST /v1/pos/sales/{sale_id}/refunds وPOST /v1/pos/closuresالمبيعات والمرتجعات وإغلاقات Z
GET /v1/orders وGET /v1/orders/{id}طلبات المتجر بصيغة الصندوق
POST /v1/orders/{id}/claim وPATCH /v1/orders/{id} وPOST /v1/orders/{id}/cancelأخذ طلب وتحريكه وإلغاؤه
GET /v1/customers?phone=مؤشرات رقم هاتف واحد
GET /v1/eventsتدفق التغييرات

بعض المسارات مشتركة مع مفاتيح API (المنتجات والطلبات والزبائن). الصندوق يتلقى الصيغ المذكورة في هذه الصفحة، ومفتاح API يحتفظ بالصيغ المذكورة في قسم الموارد.

دفعة المنتجات​

تأخذ POST /v1/products/batch الحقل items، حتى 100 عنصر. لكل عنصر external_id الخاص بالصندوق وname وsku وbarcode اختياريان وpricing.price كنص بخانتين عشريتين ("4500.00") وinventory.track_stock وstatus (active أو draft أو archived) وcategory اختيارية لها external_id وname خاصان بها.

  • يعدّل العنصر المنتج المرتبط مسبقاً بـ external_id الخاص به. وإن لم يوجد، يتبنّى منتجاً بلا متغيرات له نفس sku وغير مرتبط بعد. وإن لم يوجد، ينشئ منتجاً بمخزون 0.
  • يُعثر على الفئة بـ external_id الخاص بها، أو تُنشأ من اسمها.
  • تذكر الاستجابة كل عنصر: external_id وid وstatus (created أو updated) وerror: null. العنصر المرفوض يحمل كائن error ولا يحمل id ولا status.
  • حدّ الخطة: عندما يملك المتجر عدد المنتجات النشطة الذي تسمح به خطته، فإن الدفعة التي تنشئ منتجاً، مسودة كان أو لا، تُرجع 402 product_limit_reached. العناصر التي سبقته تبقى مكتوبة. وتحويل منتج موجود إلى active بعد الحدّ خطأ على ذلك العنصر وحده.
  • الدفعة لا تضبط المخزون أبداً. المخزون يمرّ عبر نداء التعديلات.

الصور​

  1. POST /v1/media/uploads مع filename وcontent_type (image/jpeg أو image/png أو image/webp) وsize (حتى 8 ميغابايت) وsha256. تحمل الاستجابة media_id ورابطاً موقّعاً upload_url صالحاً 10 دقائق.
  2. يرسل الصندوق البايتات الخام بـ PUT إلى upload_url، دون ترويسات DZBuild.
  3. POST /v1/products/{id}/images مع media_id وposition يربط الصورة. يجب أن يطابق الحجم وsha256 التذكرة، وإلا يُرجع النداء 422 media_mismatch. التذكرة المجهولة أو المنتهية تُرجع 404 media_not_found. يحمل المنتج حتى 20 صورة.

المخزون​

تأخذ POST /v1/inventory/adjustments/batch حتى 500 عنصر. يذكر كل عنصر product_external_id وtarget: "product" وإما set (قطع كاملة) وإما delta، وreason (pos_sale أو pos_return أو restock أو count أو loss) وref فريداً.

  • لا يُعدَّل إلا مخزون المنتجات التي تتابع المخزون على مستوى المنتج. المنتج الذي له مخزون لكل متغير يُرجع خطأ العنصر variant_product، والذي لا يتابع المخزون not_tracked، والمنتج الذي لم يعد موجوداً unknown_product.
  • تذكر الاستجابة كل عنصر بـ ref مع status إما ok وإما error.
  • تغييرات مخزون الصندوق لا تظهر أبداً في سجل تغييرات لوحة التحكم ولا تعرض تراجعاً.

وثائق الصندوق​

تسجّل POST /v1/pos/sales تذكرة أو فاتورة أو وصل تسليم، وPOST /v1/pos/sales/{sale_id}/refunds وصل إرجاع أو إشعاراً دائناً على ذلك البيع، وPOST /v1/pos/closures إغلاق Z بمجاميعه وبصماته.

  • تُحفظ الوثائق كما أُرسلت ولا تتغير أبداً: لا يوجد مسار تعديل أو حذف.
  • يُرجع البيع 201 مع {"id": 99120, "stock_applied": false}. المخزون يمرّ عبر نداء التعديلات، ولا يمرّ أبداً عبر وثيقة.
  • وثائق الصندوق منفصلة عن الطلبات. لا تُحسب في حدّ الطلبات الشهري للمتجر، ولا تُرسل أي إشعار، ولا تصل أبداً إلى Google Sheets ولا إلى webhooks.
  • المبالغ نصوص بخانتين عشريتين، والكميات أرقام بثلاث خانات عشرية على الأكثر، مع حتى 500 سطر و20 دفعة في الوثيقة.
  • إرسال وثيقة سُجّل external_id الخاص بها من قبل يُرجع 409 already_exists مع الرقم المسجّل في error.details.id. يعدّ الصندوق ذلك نجاحاً.
  • المرتجع على بيع متجر آخر يُرجع 404 not_found.

الطلبات​

  • تعطي GET /v1/orders?updated_since=... وGET /v1/orders/{id} طلبات المتجر بصيغة الصندوق مع منتجاتها. order_number هو الرقم القصير للمتجر إن وُجد.
  • POST /v1/orders/{id}/claim مع device_id وterminal: أول صندوق يأخذ الطلب. الصندوق نفسه إذا أخذه من جديد يتلقى 200، وأي صندوق آخر يتلقى 409 order_claimed.
  • PATCH /v1/orders/{id} مع status يتطلب أخذ الطلب (409 claim_required في غير ذلك). الانتقالات المسموحة: من pending أو confirmed إلى processing أو shipped أو delivered، ومن processing إلى shipped أو delivered، ومن shipped إلى delivered. أي انتقال آخر يُرجع 409 transition_not_allowed.
  • تأخذ POST /v1/orders/{id}/cancel الحقل reason (out_of_stock أو customer_unreachable أو duplicate أو other) وnote اختيارية حتى 500 حرف. يعود المخزون حسب قواعد مخزون المتجر. إذا كان صندوق آخر قد أخذ الطلب، يُرجع الإلغاء 409 order_claimed.
  • تغيير الحالة من الصندوق يشغّل نفس الخطوات التي يشغّلها تغيير من لوحة التحكم، ومنها الإشعارات وتحديث Google Sheets.

الزبائن​

تُرجع GET /v1/customers?phone=0550123456 صفحة فيها عنصر واحد على الأكثر: id وis_banned وfraud_score. تبحث في زبائن المتجر وحدهم، وتقبل الرقم مع +213 أو بدونه، ولا تعطي اسماً ولا عنواناً ولا سجلاً. الرقم المجهول يعطي صفحة فارغة.

الأحداث​

تُرجع GET /v1/events?wait=25&limit=200&cursor=... الحقول items وnext_cursor وhas_more. الحقل next_cursor موجود دائماً، حتى في صفحة فارغة، ويعيده الصندوق في النداء التالي.

  • تحتفظ الحافة بالنداء حتى 25 ثانية وتجيب فور حدوث تغيير.
  • النداء الأول، دون مؤشر، يبدأ بحدث order.updated لكل طلب في حالة pending أو confirmed أو processing.
  • الأنواع: order.created وorder.updated وproduct.updated وproduct.deleted وinventory.level_changed وcustomer.updated وdevice.revoked. لكل حدث id ثابت، فيستطيع الصندوق تجاهل التكرار.
  • يحمل inventory.level_changed الحقول old وnew وdelta وsource: order عندما يحرّك طلبٌ المخزون (مع رقم الطلب)، وdashboard لأي تغيير آخر حدث خارج الصندوق، وpos عندما يغيّره صندوق آخر في المتجر نفسه (يتجاهل الصندوق هذا المصدر).
  • كتابات الصندوق نفسه على المنتجات والمخزون لا تُرسل إليه من جديد.
  • يحمل device.revoked الحقل device_id كنص، مرة واحدة، بعد فصل الصندوق.
  • المؤشر الذي لم تُصدره هذه الواجهة يُرجع 400 bad_request.

النسخ الاحتياطية​

لا تحفظ DZBuild النسخ الاحتياطية للصناديق. تُرجع GET /v1/backups وPOST /v1/backups وPOST /v1/backups/{id}/complete وGET /v1/backups/{id}/download دائماً 501 not_implemented، ويحتفظ الصندوق بنسخه على الحاسوب.

رموز الأخطاء​

الحالةcodeمتى
400bad_requestupdated_since خاطئ أو مؤشر لم تُصدره هذه الواجهة
401unauthorizedرمز مفقود أو خاطئ أو منتهٍ، أو ربط منتهٍ
402product_limit_reachedدفعة تنشئ منتجاً بعد حدّ الخطة
403forbiddenمسار خارج قائمة الصندوق، أو متجر لم يختره صاحبه
404not_foundمنتج أو بيع أو طلب ليس في هذا المتجر
404device_not_foundرقم صندوق ليس هذا الصندوق في هذا المتجر
404media_not_foundتذكرة صورة مجهولة أو منتهية
409already_existsوثيقة بهذا external_id مسجّلة؛ رقمها في details.id
409order_claimedصندوق آخر أخذ الطلب
409claim_requiredتحريك طلب لم يأخذه هذا الصندوق
409transition_not_allowedالانتقال غير مسموح من حالة الطلب
410device_revokedفُصل الصندوق
413payload_too_largeجسم أكبر من 1 ميغابايت
422validation_errorحقل خاطئ؛ يذكره details.field
422media_mismatchالصورة المرفوعة لا تطابق تذكرتها
422idempotency_key_reuseنفس Idempotency-Key مع جسم مختلف
429rate_limitedتجاوز حدّ؛ انتظر Retry-After
501not_implementedمسارات النسخ الاحتياطية
503storage_unavailableتخزين الصور غير متاح؛ أعد المحاولة لاحقاً
هذه الصفحة لأدوات الذكاء الاصطناعيعرض بصيغة Markdownفتح في ChatGPTفتح في Claude