مرجع API
زمینهی فراخوان امضاشده
یک فراخوان پیکربندیشده با ارسال زمینه یک payload امضا شده به آدرس خروجی خود اضافه میکند تا سایت مقصد بتواند بازدیدکننده را بدون نیاز به پرسیدن دوباره هویت او شناسایی کند. payload بهصورت سه پارامتر رشته جستجو کدگذاری شده و با یک کلید مخفی HMAC-SHA256 که در فضای کاری ذخیره شده است، امضا میشود.
قوانین رفتار و فراخوانها ← یک فراخوان link_with_context انتخاب یا ایجاد کنید. ارسال زمینه را فعال کنید و انتخاب کنید که سایت مقصد چه فیلدهایی را دریافت کند.
شکل آدرس خروجی
زمانی که ارسال فعال باشد، Pitchbar سه پارامتر را به آدرس پایهای که روی فراخوان پیکربندی کردهاید اضافه میکند:
{base-url}?pitchbar_ctx=<base64url-json>
&pitchbar_ts=<unix-seconds>
&pitchbar_sig=<hex-hmac-sha256>
pitchbar_ctx— JSON کدگذاریشده base64url از فیلدهای لیست سفیدی که انتخاب کردهاید ارسال شوند.pitchbar_ts— زمانمهر یونیکس در زمان ایجاد آدرس؛ برای محافظت در برابر پخش مجدد استفاده میشود.pitchbar_sig— هگز HMAC-SHA256 از"{pitchbar_ctx}.{pitchbar_ts}"با استفاده ازcta_context_secretفضای کاری.
یک فراخوان بدون فیلدهای ارسال انتخابشده، آدرس را بهصورت کامل منتشر میکند — پارامترهای اضافی فقط زمانی ظاهر میشوند که اپراتور انتخاب کرده باشد.
فیلدهای لیست سفید
Pitchbar فقط فیلدهایی را ارسال میکند که اپراتور بهطور صریح برای هر فراخوان فعال کرده است، که از این لیست سفید انتخاب میشوند:
| فیلد | منبع |
|---|---|
conversation_id | ردیف مکالمه فعال |
agent_id | دستیار فروش مالک |
page_url | صفحهای که بازدیدکننده در زمان باز شدن چت در آن بود |
visitor_email | آخرین Lead.email جذبشده |
visitor_name | آخرین Lead.name جذبشده |
captured_fields | JSON Lead.fields به جز کلیدهای password/token/secret/api_key |
کلیدهای فیلد سفارشی که حساس به نظر میرسند (هر چیزی که شامل password، pwd، secret، token، api_key، apikey یا private باشد) قبل از امضا از captured_fields حذف میشوند — دفاع عمیق.
پیدا کردن کلید مخفی فضای کاری
کلید مخفی امضا در ردیف فضای کاری بهعنوان cta_context_secret ذخیره میشود. Pitchbar بهطور خودکار اولین بار که یک فراخوان یک آدرس امضا شده منتشر میکند، یکی را ایجاد میکند. میتوانید آن را از تنظیمات → توکنهای API (کارت زمینه فراخوان امضا شده) کپی کرده و زمانی که نیاز به لغو اعتماد در سایتهای دریافتکننده دارید، آن را تغییر دهید.
پنجره پخش مجدد
Pitchbar یک پنجره پخش مجدد ۵ دقیقهای (300s) را با رد تأییدهایی که pitchbar_ts آنها بیش از این مقدار از زمان فعلی فاصله دارد، اعمال میکند. تأییدکننده در سمت شما باید همان بررسی را اعمال کند — بدون آن، مهاجمی که آدرس را از لاگ referer استخراج کند، میتواند آن را برای همیشه پخش کند.
تأیید امضا
الگو در همه زبانها یکسان است: HMAC را روی رشته دقیق ctx.ts با کلید مخفی فضای کاری خود بازسازی کنید، با pitchbar_sig ورودی با استفاده از یک بررسی زمانثابت مقایسه کنید و تنها پس از آن pitchbar_ctx را رمزگشایی کنید تا payload را بخوانید.
PHP
$ctx = (string) ($_GET['pitchbar_ctx'] ?? '');
$ts = (string) ($_GET['pitchbar_ts'] ?? '');
$sig = (string) ($_GET['pitchbar_sig'] ?? '');
$secret = getenv('PITCHBAR_CTA_SECRET');
if ($ctx === '' || $ts === '' || $sig === '' || $secret === '') {
http_response_code(401);
exit;
}
// پنجره پخش مجدد — ۵ دقیقه در هر جهت.
if (abs(time() - (int) $ts) > 300) {
http_response_code(401);
exit;
}
$expected = hash_hmac('sha256', $ctx . '.' . $ts, $secret);
if (! hash_equals($expected, $sig)) {
http_response_code(401);
exit;
}
// امضا معتبر است — payload را رمزگشایی کنید. توجه: base64url، نه base64 استاندارد.
$padded = $ctx . str_repeat('=', (4 - strlen($ctx) % 4) % 4);
$json = base64_decode(strtr($padded, '-_', '+/'), true);
$payload = $json === false ? null : json_decode($json, true);
// $payload اکنون شامل فیلدهای لیست سفیدی است که اپراتور ارسال کرده است.
Node.js
const crypto = require('crypto');
function verifyCtaContext(query, secret) {
const ctx = String(query.pitchbar_ctx || '');
const ts = String(query.pitchbar_ts || '');
const sig = String(query.pitchbar_sig || '');
if (!ctx || !ts || !sig) {
return null;
}
// پنجره پخش مجدد.
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return null;
}
const expected = crypto
.createHmac('sha256', secret)
.update(`${ctx}.${ts}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) {
return null;
}
const padded = ctx + '='.repeat((4 - (ctx.length % 4)) % 4);
const json = Buffer
.from(padded.replace(/-/g, '+').replace(/_/g, '/'), 'base64')
.toString('utf8');
try {
return JSON.parse(json);
} catch {
return null;
}
}
Python
import base64, hmac, hashlib, json, time
def verify_cta_context(query, secret: str):
ctx = query.get('pitchbar_ctx', '')
ts = query.get('pitchbar_ts', '')
sig = query.get('pitchbar_sig', '')
if not ctx or not ts or not sig:
return None
try:
if abs(time.time() - int(ts)) > 300:
return None
except ValueError:
return None
expected = hmac.new(
secret.encode(),
f"{ctx}.{ts}".encode(),
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, sig):
return None
padded = ctx + '=' * ((4 - len(ctx) % 4) % 4)
raw = base64.urlsafe_b64decode(padded.encode())
try:
return json.loads(raw)
except json.JSONDecodeError:
return None
نمونه payload
یک فراخوان پیکربندیشده برای ارسال conversation_id، visitor_email و page_url موارد زیر را ارسال میکند:
{
"conversation_id": "01JRX4D8YQ8KEXP3F5VZ8MEXAM",
"visitor_email": "jane@example.com",
"page_url": "https://customer-site.com/pricing"
}
بهصورت base64url در pitchbar_ctx کدگذاری شده، با pitchbar_ts فعلی جفت شده و با کلید مخفی شما امضا شده است.
چرا وبهوک خروجی نه؟
اشتراک وبهوک رونوشت کامل مکالمه را بهصورت ناهمگام تحویل میدهد — برای تحلیلها یا ارسال به CRM عالی است، اما زمانی که بازدیدکننده روی یک فراخوان کلیک میکند و شما میخواهید قبل از اتمام هر کار پسزمینه، آنها را به یک صفحه شخصیسازیشده هدایت کنید، بیفایده است. زمینه فراخوان امضا شده برای آن مسیر سریع وجود دارد: با کلیک حرکت کرده و با درخواست میرسد.
همچنان از وبهوکها برای هر چیزی که به بدنه کامل نیاز دارد، یا برای مشتریانی که میخواهید به چندین سیستم پاییندستی ارسال کنید، استفاده کنید. آنها مکمل یکدیگر هستند، نه اضافی.