إن كان متجرك يعمل ببرمجية بنيتها بنفسك، أو على منصة ليس لها موصل جاهز، فيمكنه إرسال أحداث موقّعة إلى ربط متجر. هذه الصفحة للمطوّر الذي يضيف جهة الإرسال: فيها العنوان والتوقيع وصيغ الأحداث والردود.
قبل أن تبدأ
- من يستطيع إنشاء الربط: مالك الشركة ومسؤولوها.
- الباقة: متاح عندما تشمل باقتك ربط المتاجر.
- مسار مبيعات يجب أن يوجد: طلبات عروض الأسعار تصبح فرصًا في المرحلة التي تختارها. راجع الفرص والمسارات.
- متجرك يرسل، ورُتبة CRM لا يجلب. لا يُستورد شيء تلقائيًا من متجر مخصص، فالطلبات السابقة لا تصل إلا إن أرسلها متجرك.
أنشئ الربط
- من القائمة الجانبية افتح المنتجات، ثم اضغط ربط المتاجر.
- في نموذج ربط متجر اختر منصتنا أو متجر مخصص في منصة المتجر. وعملة المتجر اختيارية لهذه المنصة.
- في تبدأ طلبات عروض الأسعار في اختر مرحلة طلبات العروض، وفي إسناد الفرص الجديدة إلى الشخص الذي يستلمها.
- اضغط ربط متجر. انسخ سر التوقيع الآن، فلن يظهر مرة أخرى.
- انسخ العنوان في العنوان الذي يرسل إليه متجرك.
احفظ القيمتين في إعدادات بيئة متجرك، لا في الكود:
STORE_EVENTS_URL=ADDRESS_FOR_YOUR_STORE
STORE_EVENTS_SECRET=YOUR_SIGNING_SECRET
وقّع كل طلب
أرسل POST بجسم JSON وترويستين:
| الترويسة | القيمة |
|---|---|
X-CRM-Timestamp |
الوقت الحالي بثواني Unix |
X-CRM-Signature |
sha256= ثم HMAC-SHA256 بصيغة hex للنص TIMESTAMP.BODY، بمفتاح هو سر التوقيع |
BODY هو البايتات نفسها التي ترسلها. الطلب الذي يبتعد وقته أكثر من 5 دقائق عن ساعة الخادم يُرفض، فأبقِ ساعة خادمك مضبوطة.
$body = json_encode(['event' => $event, $key => $document], JSON_THROW_ON_ERROR);
$time = (string) time();
$signature = 'sha256='.hash_hmac('sha256', $time.'.'.$body, getenv('STORE_EVENTS_SECRET'));
// POST $body to STORE_EVENTS_URL with Content-Type: application/json,
// X-CRM-Timestamp: $time and X-CRM-Signature: $signature
أرسل من مهمة في الخلفية بعد حفظ الطلب، حتى لا يؤخر الرد البطيء أي عملية شراء. وأعد المحاولة عند رد 5xx أو انتهاء المهلة فقط.
الأحداث
| الحدث | المفتاح في الجسم | الأثر |
|---|---|---|
order.created |
order |
يحفظ الطلب ويجد العميل أو ينشئه |
order.updated |
order |
الأمر نفسه عند أي تغيير. أرسل updated_at أحدث في كل مرة |
quote.requested |
quote |
ينشئ فرصة في المرحلة المختارة بالبنود، مرة واحدة لكل id |
product.upserted |
product |
ينشئ منتجًا أو يحدّثه |
حقول الطلب وطلب العرض
{"event": "order.updated", "order": {
"id": "1001", "number": "A-1001", "status": "paid", "currency": "SAR",
"total": "1250.50", "placed_at": "2026-11-06T10:00:00Z", "updated_at": "2026-11-06T10:05:00Z",
"customer": {"name": "Sample Customer", "email": "customer@example.com", "phone": "+966500000001", "company": "Sample Cafe"},
"items": [{"sku": "M-1", "name": "Espresso machine", "quantity": 1, "total": "1250.50"}],
"attribution": {"source": "google", "medium": "cpc", "campaign": "autumn-sale"}}}
| الحقل | القاعدة |
|---|---|
id |
مطلوب، معرف الطلب عندك، حتى 100 حرف |
number |
اختياري، الرقم الذي يراه العميل، حتى 60 حرفًا |
status |
اختياري، حتى 40 حرفًا، وقيمته الافتراضية pending |
currency |
مطلوب: USD أو EUR أو GBP أو TRY أو SAR أو AED |
total |
مطلوب، نص مثل "1250.50"، بنقطة عشرية وخانتين عشريتين على الأكثر |
placed_at وupdated_at |
placed_at مطلوب، وكلاهما تاريخ بصيغة مثل ISO 8601 |
customer.name |
مطلوب، حتى 160 حرفًا |
customer.email وcustomer.phone |
أحدهما على الأقل مطلوب. الهاتف من 6 إلى 15 رقمًا، ويُفضل مع رمز الدولة |
customer.company |
اختياري |
items |
اختياري، حتى 200 بند. يحتاج كل بند name وquantity عددًا صحيحًا لا يقل عن 1 وtotal نصًا، وsku اختياري |
attribution |
source وmedium وcampaign اختيارية، حتى 120 حرفًا لكل منها. وتظهر الحملة في التقارير |
recovery_url |
رابط اختياري يبدأ بـhttps:// يستطيع العميل منه دفع طلب غير مدفوع |
يستخدم طلب العرض الحقول نفسها تحت المفتاح quote. ومبلغ فرصته هو مجموع بنوده، أو المجموع الكلي إن لم تكن فيه بنود.
الحالات
paid وprocessing وcompleted وdelivered تُحسب مبيعات، وأول واحدة منها تحوّل العميل المحتمل إلى عميل. أي حالة أخرى تُحفظ كما هي ولا تُحسب. استخدم cancelled أو refunded لإخراج طلب من المبيعات.
حقول المنتج
{"event": "product.upserted", "product": {"id": "P-77", "name": "Espresso machine", "sku": "M-1", "price": "1250.50", "currency": "SAR", "active": true, "updated_at": "2026-11-06T10:00:00Z"}}
id وname مطلوبان. يُطابق المنتج بـid ثم بـsku. و"active": false يؤرشفه. لا يُحفظ السعر إلا مع عملة. والتحديث الأقدم مما حُفظ يُتجاهل.
الردود
| الرد | المعنى |
|---|---|
200 {"status": "received"} |
حُفظ، أو كان تكرارًا لما حُفظ |
200 {"status": "paused"} |
الشركة أو باقتها لا تقبل أحداث المتاجر الآن، ولم يُحفظ شيء |
403 |
توقيع خاطئ، أو فارق وقت أكبر من 5 دقائق |
404 |
الربط غير موجود أو متوقف |
422 {"errors": [...]} |
المستند غير صالح، والقائمة تذكر الحقول. لا فائدة من إعادة إرساله دون تعديل |
يستطيع كل خادم مرسل إرسال 600 طلب في الدقيقة على الأكثر.
اختبر الربط
- أرسل
order.updatedبحالةpaidوحملة فيattribution. - في رُتبة CRM تأكد من وجود جهة الاتصال، ومن ظهور الطلب في سجلها، ومن ظهور آخر حدث: في بطاقة المتجر.
- أرسل الطلب نفسه بحالة
cancelledوupdated_atأحدث. في التقارير يخرج الطلب من المبيعات وينقص مجموع الحملة.
معلومات مفيدة
- التكرار آمن. تحديث الطلب الأقدم مما حُفظ أو المطابق له يُتجاهل، وطلب العرض بـ
idسبق وصوله يُتجاهل. - مطابقة العميل: البريد أولًا، والهاتف يلتحق فقط بجهة لا تحمل بريدًا آخر، ولا يُكتب فوق بيانات جهة موجودة.
- استبدال السر في بطاقة المتجر يعطي سرًا جديدًا فورًا ويتوقف القديم، فحدّث إعدادات متجرك مباشرة.
آخر تحديث 2026-11-08