ডকুমেন্টেশন

পরিচয় যাচাই

সাইন ইন করা ব্যক্তিকে চিনে নিন এবং আপনার backend-এর নিয়ন্ত্রণে থাকা একটি স্বাক্ষরের সাহায্যে বিভিন্ন ডিভাইসে তাঁর কথোপকথনের ইতিহাস ফিরিয়ে আনুন।

কেন যাচাই করবেন#

ডিফল্টভাবে SDK বেনামি: এটি একটি স্থির visitor_id তৈরি করে এবং প্ল্যাটফর্মের কী-স্টোরে রেখে দেয়। একটি ডিভাইসে একটি কথোপকথনের জন্য এটুকুই যথেষ্ট। কিন্তু নির্দিষ্ট ব্যবহারকারীকে চেনা, আবার লগইন করলে বা অন্য ডিভাইসে ইতিহাস ফিরিয়ে আনা এবং কথোপকথনকে নির্ভরযোগ্যভাবে কোনো কন্ট্যাক্ট প্রোফাইলের সঙ্গে বাঁধার জন্য backend-এর প্রমাণ দরকার যে ক্লায়েন্ট সত্যিই সে-ই, যার পরিচয় সে দিচ্ছে। SDK যদি শুধু “আমি ব্যবহারকারী 42” পাঠাত, তাহলে যে কেউ অন্যের id নকল করে অন্যের চ্যাট পড়ে ফেলতে পারত — তাই Respondo একটি ক্রিপ্টোগ্রাফিক স্বাক্ষর, userHash চায়, যা কেবল আপনার backend তৈরি করতে পারে।

identity secret সংগ্রহ করা#

identity_secret হলো আপনার এজেন্টের (যে AI কর্মীর সঙ্গে আপনার উইজেট চ্যানেল যুক্ত) সঙ্গে বাঁধা একটি গোপন স্ট্রিং। এটি ড্যাশবোর্ডে এখানে তৈরি করুন: Channels → Widget → Identity verification। যেহেতু এটি এজেন্টের উপর থাকে, সেই এজেন্টে চলা প্রতিটি চ্যানেল — ওয়েব উইজেট ও মোবাইল SDK দুই-ই — একই secret ব্যবহার করে। এটি পরিচয়ে স্বাক্ষর করার অধিকার দেয়, তাই এটি কেবল আপনার backend-এ থাকতে হবে এবং কখনোই অ্যাপের ভিতরে পাঠানো যাবে না।

userHash-এর সূত্র#

userHash হলো একটিমাত্র স্বাক্ষরিত পরিচয়-স্ট্রিংয়ের উপর HMAC-SHA256, যা লোয়ারকেস hex হিসেবে এনকোড করা হয়:

সূত্রtext
userHash = HMAC_SHA256( identity_secret, payload )

payload = userId          // যদি userId সেট করা থাকে
        = email           // নইলে, যদি email সেট করা থাকে
        = (invalid)       // দুটোই খালি হলে স্বাক্ষর করার মতো কিছুই নেই
  • secret হলো HMAC-এর কী; পরিচয়-স্ট্রিংটি হলো বার্তা — উল্টোটা নয়।
  • ঠিক একটি স্ট্রিংয়েই স্বাক্ষর করুন — কাঁচা userId (বা ইমেল), কোনো সল্ট বা JSON মোড়ক ছাড়াই।
  • আপনি যদি userId ও ইমেল দুটোই পাঠান, তবে userId-এ স্বাক্ষর করুন (এটিই অগ্রাধিকার পায়)।
  • ফলাফল hex (SHA-256-এর জন্য 64টি অক্ষর), base64 নয়।

backend-এর উদাহরণ#

স্বাক্ষরটি আপনার backend-এ হিসাব করুন এবং তৈরি userHash অ্যাপকে দিন।

Gogo
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
)

// HMAC_SHA256(identity_secret, userId), লোয়ারকেস hex হিসেবে।
func ComputeUserHash(identitySecret, userID string) string {
    mac := hmac.New(sha256.New, []byte(identitySecret))
    mac.Write([]byte(userID))
    return hex.EncodeToString(mac.Sum(nil))
}
Node.jsjavascript
const crypto = require("crypto");

// মোবাইল ক্লায়েন্টে Respondo.identify-তে পাঠানোর userHash ফেরত দেয়।
function computeUserHash(identitySecret, userId) {
  return crypto
    .createHmac("sha256", identitySecret)
    .update(userId, "utf8")
    .digest("hex");
}
Pythonpython
import hmac
import hashlib

# মোবাইল ক্লায়েন্টে Respondo.identify-তে পাঠানোর userHash ফেরত দেয়।
def compute_user_hash(identity_secret: str, user_id: str) -> str:
    return hmac.new(
        identity_secret.encode(),
        user_id.encode(),
        hashlib.sha256,
    ).hexdigest()
PHPphp
<?php
// মোবাইল ক্লায়েন্টে Respondo.identify-তে পাঠানোর userHash ফেরত দেয়।
function computeUserHash(string $identitySecret, string $userId): string {
    return hash_hmac('sha256', $userId, $identitySecret);
}

হ্যাশ কীভাবে Respondo পর্যন্ত পৌঁছায়#

Respondo-র আলাদা কোনো identity এন্ডপয়েন্ট নেই। কল করার মতো কোনো /identity রুট নেই, রেজিস্টার করারও কিছু নেই। userHash একটি ফিল্ড, যা SDK-র নিজের করা রিকোয়েস্টগুলোর সঙ্গেই যায়।

দুটি ধাপ, আর তার প্রথমটিই কেবল আপনাকে বানাতে হয়:

  1. আপনার backend → আপনার অ্যাপ। হ্যাশটি আপনি যেভাবে খুশি পৌঁছে দিতে পারেন। সবচেয়ে সাশ্রয়ী উপায় হলো লগইন বা বুটস্ট্র্যাপ রেসপন্সে, যা আপনি এমনিতেই ফেরত দেন, একটি বাড়তি ফিল্ড যোগ করা — আলাদা কোনো রাউন্ড ট্রিপ লাগে না। আপনার নিজের backend-এ আলাদা এন্ডপয়েন্টও (ধরুন POST /myapp/identity যা ফেরত দেয় { userId, userHash }) সমান কাজ করে। Respondo সেই এন্ডপয়েন্ট চালায় না — সেটি আপনাকেই বানাতে হবে।
  2. আপনার অ্যাপ → Respondo। এই অংশটি নিজেই হয়ে যায়। আপনি একবার identify কল করলেই SDK প্রতিটি প্রাসঙ্গিক রিকোয়েস্টে হ্যাশটি জুড়ে দেয় এবং backend প্রতিবারই সেটি আবার যাচাই করে।
SDK এটি কোথায় বসায় (তথ্যের জন্য — হাতে পাঠাতে হয় না)text
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 ফ্রেমে — 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 একা কোনো কাজে লাগে না।

আপনার backend-এ হ্যাশ পৌঁছে দেওয়ার এন্ডপয়েন্ট এখনও তৈরি না হলে আপনার অ্যাপের নিজের রিকোয়েস্টই 404 দেয়, identify কখনও কল হয় না, আর চ্যাট বেনামিভাবেই চলে। এটি প্রত্যাশিত আচরণ, Respondo-র ত্রুটি নয় — নিজের পথে 404 মানে আপনার দিকের কাজ বাকি, ভাঙা ইন্টিগ্রেশন নয়।

SDK-তে পরিচয় পাঠানো#

আপনার backend থেকে স্বাক্ষরিত পরিচয়টি আনুন, তারপর যেকোনো প্ল্যাটফর্মে userHash-কে identify-তে পাঠিয়ে দিন:

Kotlinkotlin
Respondo.identify(
    RespondoIdentity(userId = "42", email = "user@example.com", userHash = hash),
)
Swiftswift
Respondo.identify(
    RespondoIdentity(userId: "42", email: "user@example.com", userHash: hash)
)
Dartdart
Respondo.identify(RespondoIdentity(
  userId: '42', email: 'user@example.com', userHash: hash,
));

ভুল userHash হলে কী হয়#

এজেন্টে যাচাই চালু থাকা অবস্থায় স্বাক্ষর না থাকলে বা ভুল হলে backend নীরবে বেনামিতে নামিয়ে দেয়: চ্যাট তবুও চলে, visitor_id রয়ে যায় এবং কথোপকথনটি বেনামি কন্ট্যাক্টের সঙ্গে বাঁধা থাকে — কিন্তু প্রোফাইলের সঙ্গে কোনো যোগ থাকে না, ডিভাইসের মধ্যেকার ইতিহাসও থাকে না। কোনো ব্যবহারকারীকে “চেনা যাচ্ছে না” হলে প্রায় সবসময়ই কারণ স্বাক্ষর: দেখে নিন আপনি userId-এ স্বাক্ষর করেছেন কি না (ইমেল বা JSON নয়), সঠিক identity_secret ব্যবহার করেছেন কি না এবং লোয়ারকেস hex দিয়েছেন কি না। এজেন্টের identity_secret খালি থাকলে যাচাই বন্ধ থাকে এবং userId / ইমেল যেমন আছে তেমনই গ্রহণ করা হয়।

identity_secret বদলানো মানে কার্যত এক ধাক্কায় পুরো বদল: পুরোনো secret দিয়ে বানানো প্রতিটি হ্যাশ সঙ্গে সঙ্গে যাচাই হওয়া বন্ধ করে দেয়, তাই ইতিমধ্যে সাইন ইন করা ব্যবহারকারীরা নীরবে বেনামিতে নেমে যান — যতক্ষণ না আপনার backend নতুন secret দিয়ে তাঁদের userHash আবার হিসাব করে সরবরাহ করে। secret তখনই বদলান, যখন একই সময়ের মধ্যে স্বাক্ষর করার দিকটিও হালনাগাদ করতে পারবেন।