Webhook'larni SDK bilan qabul qilish
Webhook endpoint uchta ishni bajaradi: so'rov haqiqiyligini tekshiradi, tezda 200 qaytaradi va og'ir ishni navbatga qo'yadi. Meta va TikTok tanani HMAC-SHA256 bilan imzolaydi, shuning uchun imzo xom baytlar bo'yicha tekshiriladi; Telegram tanani imzolamaydi, faqat X-Telegram-Bot-Api-Secret-Token sarlavhasini yuboradi. socialift.webhooks modulida uchala holat uchun tayyor funksiyalar bor.
Yangilangan:
Qisqacha: webhook endpoint nima qilishi kerak?
Meta uchun: GET so'rovda verify_challenge() bilan hub.challenge ni oddiy matn sifatida qaytaring; POST so'rovda xom tanani o'qing, verify_request() bilan X-Hub-Signature-256 ni tekshiring, parse_events() bilan hodisalarga ajrating, navbatga qo'ying va 200 qaytaring. TikTok uchun — verify_tiktok_request() va parse_tiktok_event(), Telegram bot uchun — verify_telegram_request(). Takroriy yetkazishni dedupe_key() yoki event.key bilan filtrlang.
Bu sahifa — texnik yo'riqnoma. Socialift webhook imkoniyatlarining umumiy tavsifi «Webhook integratsiyasi» sahifasida.
Platformalar webhook'ni qanday imzolaydi?
| Platforma | Sarlavha | Tekshiruv | Qayta yetkazish | SDK funksiyalari |
|---|---|---|---|---|
| Meta (Facebook, Instagram) | X-Hub-Signature-256: sha256=<hex> | HMAC-SHA256: kalit — App Secret, xabar — xom tana | Darhol, keyin 36 soat davomida kamayib boruvchi chastotada | verify_challenge, verify_request, parse_events, dedupe_key |
| TikTok | Tiktok-Signature: t=<unix>,s=<hex> | HMAC-SHA256: kalit — Client Secret, xabar — <t>.<xom tana> | 72 soatgacha, eksponensial backoff bilan | verify_tiktok_request, parse_tiktok_event |
| Telegram Bot API | X-Telegram-Bot-Api-Secret-Token | Imzo yo'q: setWebhook da berilgan secret_token bilan solishtirish | Javob 2XX bo'lmasa qayta yuboradi, oqilona urinishlardan keyin to'xtaydi | verify_telegram_request |
Qayta yetkazish qoidalari platformalar hujjatidan olingan va o'zgarishi mumkin — manbalar sahifa oxirida.
FastAPI: Meta webhook — tasdiqlash va hodisalar
import asyncio
import json
import os
from fastapi import FastAPI, Request, Response
from socialift.webhooks import parse_events, verify_challenge, verify_request
app = FastAPI()
events: asyncio.Queue = asyncio.Queue() # prod'da: Redis, RQ, Celery va h.k.
@app.get("/webhooks/meta")
async def meta_verify(request: Request):
challenge = verify_challenge(dict(request.query_params), os.environ["META_VERIFY_TOKEN"])
if challenge is None:
return Response(status_code=403)
return Response(challenge, media_type="text/plain") # JSON emas, aynan satr
@app.post("/webhooks/meta")
async def meta_receive(request: Request):
body = await request.body() # xom baytlar
if not verify_request(os.environ["FACEBOOK_APP_SECRET"], body, request.headers):
return Response(status_code=403)
for event in parse_events(json.loads(body)):
events.put_nowait(event)
return Response(status_code=200)verify_challenge() hub.mode=subscribe va hub.verify_token mos kelsa hub.challenge ni, aks holda None ni qaytaradi. Javob aynan challenge satri bo'lishi kerak.
verify_request() ga freymvork tanani parse qilishidan oldingi xom baytlar kerak — qayta serializatsiya qilingan JSON imzoni buzadi. Sarlavha yo'q yoki bo'sh bo'lsa natija False; taqqoslash hmac.compare_digest bilan.
request.headers katta-kichik harfga sezgir emas. Oddiy dict bersangiz, kalit X-Hub-Signature-256 yoki x-hub-signature-256 bo'lishi kerak.
Har bir Page alohida obuna qilinadi: await fb.subscribe_page(page_id, page_token, fields=['leadgen', 'feed']). Meta buning uchun pages_manage_metadata va pages_show_list ruxsatlarini talab qiladi; obunasiz app darajasida sozlangan webhook ham hodisa bermaydi.
WebhookEvent: parse_events() nima qaytaradi?
Meta ikki formatda yuboradi: changes (leadgen, feed, comments) va messaging (masalan, Instagram Direct xabarlari). parse_events() ikkalasini bir xil WebhookEvent oqimiga aylantiradi.
object_type- Payload'dagi
object: masalan,pageyokiinstagram. fieldchangesuchunfieldqiymati (leadgen,comments,feedva h.k.);messagingyozuvlari uchunmessages,standbyuchunmessages_standby.object_idvatimeentry.id(odatda Page yoki Instagram akkaunt ID si) vaentry.time(unix).value- Hodisaning o'zi:
changes[].valueyokimessaging[]elementi. leadgen_id,form_id,page_id- Lead Ads hodisalari uchun qulay xususiyatlar;
valuedapage_idbo'lmasa,object_idqaytadi. key- Takroriy yetkazishni ushlash uchun barqaror kalit —
dedupe_key(event)bilan bir xil.
FastAPI: TikTok webhook
import json
import os
from fastapi import FastAPI, Request, Response
from socialift.webhooks import parse_tiktok_event, verify_tiktok_request
app = FastAPI()
@app.post("/webhooks/tiktok")
async def tiktok_receive(request: Request):
body = await request.body()
if not verify_tiktok_request(os.environ["TIKTOK_CLIENT_SECRET"], body, request.headers):
return Response(status_code=403)
event = parse_tiktok_event(json.loads(body))
if event.event == "authorization.removed":
print("Ruxsat bekor qilindi:", event.user_openid) # tokenlarini o'chiring
return Response(status_code=200)TikTok bitta so'rovda bitta hodisa yuboradi: event.event — hodisa nomi, event.user_openid — foydalanuvchi, event.create_time — unix vaqt. TikTok content maydonini JSON satr sifatida yuboradi; SDK uni event.content lug'atiga ochadi, buzuq bo'lsa xom satrni {'raw': ...} ichida qoldiradi.
tolerance (standart 300 soniya): vaqt tamg'asi hozirgi vaqtdan shuncha soniyadan ko'proq farq qilsa, so'rov rad etiladi — bu eski so'rovni qayta yuborishdan himoya. Server soati sinxron bo'lsin; tolerance=0 tekshiruvni o'chiradi va tavsiya etilmaydi.
TikTok hujjatida sarlavha Tiktok-Signature deb yozilgan. request.headers bilan muammo yo'q; oddiy dict bersangiz, SDK TikTok-Signature yoki tiktok-signature kalitini qidiradi.
event.key — publish_id, video_id yoki comment_id bo'yicha, ular bo'lmasa tana hash'i bo'yicha dedupe kaliti.
FastAPI: Telegram bot webhook
import os
from fastapi import FastAPI, Request, Response
from socialift import Telegram
from socialift.webhooks import verify_telegram_request
app = FastAPI()
SECRET = os.environ["TELEGRAM_WEBHOOK_SECRET"] # 1–256 belgi: A-Z, a-z, 0-9, _ va -
async def register_webhook(): # deploy paytida bir marta
async with Telegram.from_env() as bot:
await bot.set_webhook("https://example.uz/webhooks/telegram",
secret_token=SECRET, allowed_updates=["message"])
@app.post("/webhooks/telegram")
async def telegram_receive(request: Request):
if not verify_telegram_request(request.headers, SECRET):
return Response(status_code=403)
update = await request.json()
print(update.get("message", {}).get("text")) # navbatga qo'ying
return Response(status_code=200)Argumentlar tartibi Meta'dan farq qiladi: verify_telegram_request(headers, secret_token). secret_token bo'sh bo'lsa funksiya doim False qaytaradi — webhook sirsiz ochiq qolmasligi uchun.
Telegram tanani imzolamaydi, shuning uchun sir — yagona himoya: usiz manzilni bilgan har kim soxta update yubora oladi. Taqqoslash doimiy vaqtda (compare_digest) bajariladi.
Webhook o'rnatilgach get_updates() ishlamaydi. Update'lar kelmasa, await bot.get_webhook_info() dagi last_error_message va pending_update_count ga qarang.
Nega 200 ni tez qaytarish va ishni navbatga qo'yish kerak?
Platformalar yetkazishni qayta urinadi. Meta muvaffaqiyatsiz yetkazishni darhol, keyin 36 soat davomida kamayib boruvchi chastotada takrorlaydi. TikTok 72 soatgacha eksponensial backoff bilan qayta urinadi va bitta hodisa bir necha marta kelishi mumkinligini ochiq yozadi. Telegram 2XX bo'lmagan javobdan keyin so'rovni takrorlaydi.
Handler ichida CRM'ga yozish, fayl yuklash yoki sekin API chaqirish javobni kechiktiradi; platforma buni muvaffaqiyatsizlik deb hisoblasa, qayta yuboradi va dubllar ko'payadi. To'g'ri tartib: imzoni tekshirish → hodisani navbatga (Redis, RQ, Celery yoki bazadagi jadval) yozish → darhol 200. Qayta ishlashni alohida worker bajaradi.
Meta bir so'rovda bir nechta hodisani (1000 tagacha) jamlab yuborishi mumkin, lekin buni kafolatlamaydi — har bir hodisani alohida ishlang.
Idempotentlik: har hodisani bir marta qayta ishlash
import asyncio
from socialift.webhooks import WebhookEvent, dedupe_key
seen: set[str] = set() # prod'da: bazadagi UNIQUE ustun yoki Redis SET NX
async def worker(events: asyncio.Queue):
while True:
event: WebhookEvent = await events.get()
key = dedupe_key(event) # event.key bilan bir xil
if key not in seen:
seen.add(key)
if event.field == "leadgen" and event.leadgen_id:
print("Yangi lead:", event.leadgen_id, "forma:", event.form_id)
events.task_done()Meta hodisa ID bermaydi, shuning uchun dedupe_key() kalitni mazmundan yig'adi: leadgen_id, mid, comment_id, media_id yoki post_id bo'lsa — shu bo'yicha, bo'lmasa value hash'i, object_id va vaqt bo'yicha. Meta aynan bir xil tanani qayta yuborgani uchun zaxira variant ham dublni ushlaydi.
Xotiradagi set jarayon qayta ishga tushganda tozalanadi va bir nechta worker orasida bo'linmaydi. Production'da kalitni UNIQUE ustunli jadvalga yozing (INSERT ... ON CONFLICT DO NOTHING) va faqat yozuv muvaffaqiyatli bo'lganda qayta ishlang.
Production uchun tekshiruv ro'yxati
- Endpoint faqat HTTPS orqali ochiq bo'lsin — TikTok callback URL uchun HTTPS'ni talab qiladi.
- Imzoni tanani parse qilishdan oldin, xom baytlar bo'yicha tekshiring; yaroqsiz imzoga 403 qaytaring va log'ga yozing.
- App Secret, Client Secret, verify token va Telegram sirini muhit o'zgaruvchilarida saqlang.
- 200 ni darhol qaytaring, qayta ishlashni navbatga qo'ying.
- Dedupe kalitini bazadagi UNIQUE ustunda saqlang.
- Meta'da har bir Page'ni
subscribe_page()bilan obuna qiling. - Meta data deletion callback'i
X-Hub-Signature-256bilan emas, POST dagisigned_requestbilan keladi — unisocialift.crypto.parse_signed_request(signed_request, app_secret)bilan oching;Noneqaytsa 400 bering.
Socialift kabinetidagi webhook manzillari
Akkauntlarni Socialift kabineti orqali ulasangiz va «Kalitlar» bo'limida o'z Meta yoki TikTok app'ingizni qo'shsangiz, kabinet kalit saqlangandan keyin shu app uchun alohida Webhook URL va verify token ko'rsatadi — ularni platforma konsoliga ko'chirasiz.
Har bir app'ga alohida manzil beriladi, chunki Meta va TikTok hodisani aynan o'sha app'ning secret'i bilan imzolaydi. Webhook'larni o'z serveringizda SDK bilan qabul qilsangiz, shu sahifadagi namunalar yetarli.
Ko'p so'raladigan savollar
Meta webhook imzosi mos kelmayapti — sababi nima?
Odatda uchta sabab bo'ladi: tana xom emas (freymvork JSON'ni parse qilib qayta yig'gan), boshqa app'ning App Secret'i ishlatilgan yoki proksi tanani o'zgartirgan. verify_request() ga await request.body() natijasini va webhook sozlangan app'ning secret'ini bering.
Meta «The URL couldn't be validated» deyapti. Nima qilish kerak?
GET javobi aynan hub.challenge satri bo'lishi kerak — JSON emas, text/plain. hub.verify_token konsoldagi qiymat bilan bir xil ekanini va endpoint HTTPS orqali ochiqligini tekshiring. verify_challenge() mos kelmasa None qaytaradi — shunda 403 bering.
TikTok imzosi to'g'ri, lekin verify_tiktok_request() False qaytaryapti. Nega?
Eng ko'p uchraydigan sabab — soat farqi: server vaqti TikTok vaqt tamg'asidan 300 soniyadan ko'proq farq qilsa, so'rov rad etiladi. Soatni NTP bilan sinxronlang. Shuningdek, client_secret bo'sh emasligini tekshiring va sarlavhalarni request.headers sifatida bering.
Telegram webhook'ini qanday himoyalash kerak?
set_webhook() ga secret_token bering va har so'rovda verify_telegram_request(request.headers, secret) bilan tekshiring. Telegram bu satrni X-Telegram-Bot-Api-Secret-Token sarlavhasida qaytaradi. Sir 1–256 belgidan iborat va faqat A-Z, a-z, 0-9, _ hamda - belgilaridan tuziladi.
Bir hodisa ikki marta keldi — bu xatomi?
Yo'q, bu kutilgan holat: Meta, TikTok va Telegram yetkazishni qayta urinadi. Hodisani dedupe_key() yoki event.key bo'yicha bir marta qayta ishlang va javobni tez qaytaring.
Webhook so'rovlari Socialift «Statistika» sida sanaladimi?
Yo'q. Webhook'larni platformalar chaqiradi, shuning uchun ular hech bir kalitning ishlatilishiga yozilmaydi. SDK yordamchilari (socialift.webhooks) esa tarmoqqa umuman chiqmaydi — ular faqat sizning serveringizda ishlaydi.