التحقق من الهوية
تعرّف على شخص مسجّل الدخول واستعِد سجل محادثته عبر الأجهزة، باستخدام توقيع تتحكم فيه خلفيتك.
لماذا التحقق#
افتراضياً تكون حزمة SDK مجهولة: فهي تولّد visitor_id ثابتاً وتحتفظ به في مخزن مفاتيح المنصة. وهذا يكفي لمحادثة واحدة على جهاز واحد. أما للتعرّف على مستخدم بعينه، واستعادة السجل عند إعادة تسجيل الدخول أو على جهاز آخر، وربط محادثة بملف جهة اتصال بشكل موثوق، فتحتاج الخلفية إلى إثبات أن العميل هو من يدّعي أنه هو. لو أن حزمة SDK أرسلت ببساطة «أنا المستخدم 42»، لأمكن لأي أحد انتحال معرّف آخر وقراءة محادثة شخص آخر — لذا يشترط Respondo توقيعاً تعموياً، userHash، لا يمكن أن تنتجه سوى خلفيتك.
الحصول على identity_secret#
الـ identity_secret هو سلسلة سرية مرتبطة بـوكيلك (العامل الذكي المتصل به قناة الأداة لديك). ولّده من لوحة التحكّم عبر القنوات ← الأداة ← التحقق من الهوية. وبما أنه يقيم على الوكيل، فإن كل قناة يقف خلفها ذلك الوكيل — أداة الويب وحزمة SDK للجوال على حد سواء — تتشارك السر نفسه. وهو يمنح الحق في توقيع الهويات، لذا يجب أن يبقى على خلفيتك فقط ويجب ألا يُشحن أبداً في التطبيق.
صيغة userHash#
الـ userHash هو HMAC-SHA256 على سلسلة هوية موقّعة واحدة، مُرمَّزة كنظام ست عشري بأحرف صغيرة:
userHash = HMAC_SHA256( identity_secret, payload )
payload = userId // إذا كان userId مضبوطاً
= email // وإلا، إذا كان email مضبوطاً
= (غير صالح) // إذا كان كلاهما فارغاً، فلا شيء لتوقيعه- السر هو مفتاح HMAC؛ وسلسلة الهوية هي الرسالة — لا العكس.
- وقّع سلسلة واحدة بالضبط — قيمة
userIdالخام (أو البريد الإلكتروني)، بلا مِلح ولا غلاف JSON. - إذا مرّرت كلًّا من
userIdوالبريد الإلكتروني، فوقّعuserId(له الأولوية). - الخرج ست عشري (64 حرفاً لـ SHA-256)، وليس base64.
أمثلة الخلفية (backend)#
احسب التوقيع على خلفيتك وسلّم userHash الجاهز إلى التطبيق.
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
// HMAC_SHA256(identity_secret, userId) كنظام ست عشري بأحرف صغيرة.
func ComputeUserHash(identitySecret, userID string) string {
mac := hmac.New(sha256.New, []byte(identitySecret))
mac.Write([]byte(userID))
return hex.EncodeToString(mac.Sum(nil))
}const crypto = require("crypto");
// يعيد userHash لتمريره إلى Respondo.identify على عميل الجوال.
function computeUserHash(identitySecret, userId) {
return crypto
.createHmac("sha256", identitySecret)
.update(userId, "utf8")
.digest("hex");
}import hmac
import hashlib
# يعيد userHash لتمريره إلى Respondo.identify على عميل الجوال.
def compute_user_hash(identity_secret: str, user_id: str) -> str:
return hmac.new(
identity_secret.encode(),
user_id.encode(),
hashlib.sha256,
).hexdigest()<?php
// يعيد userHash لتمريره إلى Respondo.identify على عميل الجوال.
function computeUserHash(string $identitySecret, string $userId): string {
return hash_hmac('sha256', $userId, $identitySecret);
}كيف يصل الهاش إلى Respondo#
/identity لاستدعائه ولا شيء لتسجيله. الـ userHash هو حقل يركب مع الطلبات التي ترسلها حزمة SDK أصلاً.قفزتان، والأولى وحدها هي ما عليك بناؤه:
- خلفيتك ← تطبيقك. توصِّل الهاش بالطريقة التي تناسبك. وأرخص خيار هو حقل إضافي في استجابة تسجيل الدخول/الإقلاع التي تعيدها أصلاً — بلا رحلة ذهاب وإياب إضافية. وتصلح كذلك نقطة نهاية مخصصة على خلفيتك أنت (مثل
POST /myapp/identityتعيد{ userId, userHash }). لا يستضيف Respondo تلك النقطة — أنت من ينفّذها. - تطبيقك ← Respondo. يتكفّل به النظام نيابة عنك. فبمجرد استدعاء
identify، ترفق حزمة SDK الهاش بكل طلب ذي صلة وتعيد الخلفية التحقق منه في كل مرة.
POST /api/v1/chat body identity.userHash
GET /api/v1/chat/resume query user_hash
GET /api/v1/chat/history query user_hash
GET /api/v1/chat/ws frames user_hash (subscribe/identify JSON frames after connect — not in the handshake URL)
GET /api/v1/widget/tours query user_hash
GET /api/v1/widget/checklists query user_hash
POST /api/v1/widget/push/register body user_hashيُعاد التحقق من الهاش في كل طلب، ولا يُستبدل مرة واحدة بجلسة — وهذا ما يجعل userId المسروق عديم الفائدة بمفرده.
identify أبداً، وستعمل المحادثة بشكل مجهول. هذا سلوك متوقع لا خطأ من Respondo — فالـ 404 على مسارك الخاص مهمة معلّقة لديك، لا تكاملاً معطوباً.تمرير الهوية إلى SDK#
اجلب الهوية الموقّعة من خلفيتك، ثم مرّر userHash إلى identify على أي منصة:
Respondo.identify(
RespondoIdentity(userId = "42", email = "user@example.com", userHash = hash),
)Respondo.identify(
RespondoIdentity(userId: "42", email: "user@example.com", userHash: hash)
)Respondo.identify(RespondoIdentity(
userId: '42', email: 'user@example.com', userHash: hash,
));سلوك userHash غير الصالح#
عند تفعيل التحقق على الوكيل وكون التوقيع مفقوداً أو خاطئاً، تُجري الخلفية تخفيضاً صامتاً إلى مجهول: تظل المحادثة تعمل، ويُحتفظ بـ visitor_id، وتُربط المحادثة بجهة الاتصال المجهولة — لكن لا رابط بالملف ولا سجل عبر الأجهزة. إذا «لم يُتعرَّف» على مستخدم، فالسبب دائماً تقريباً هو التوقيع: تحقّق من أنك وقّعت userId (لا البريد الإلكتروني أو JSON)، واستخدمت identity_secret الصحيح، وأصدرت نظاماً ست عشرياً بأحرف صغيرة. وإذا كان identity_secret الخاص بالوكيل فارغاً، فالتحقق معطّل ويُقبل userId / البريد الإلكتروني كما هما.
تدوير identity_secret يُعد فعلياً تحوّلاً قاطعاً: إذ يتوقف كل تجزئة أُنتجت بالسر القديم عن التحقق فوراً، فيهبط المستخدمون المسجّلون بالفعل بصمت إلى مجهول حتى تُعيد خلفيتك حساب userHash الخاص بهم وتزوّدهم به من جديد بالسر الجديد. لا تُدوّر السر إلا حين تستطيع تحديث جانب التوقيع في النافذة نفسها.