خطافات الويب
نظرة عامة
تتيح لك خطافات الويب تلقي إشعارات في الوقت الفعلي عند اكتمال عمليات الاستخراج أو فشلها. بدلاً من الاستعلام المتكرر عن API، يرسل DocMap طلب POST إلى نقطة النهاية الخاصة بك مع نتيجة الاستخراج بمجرد تغيير الحالة.
حقائق أساسية:
- حد أقصى 10 خطافات ويب نشطة لكل حساب
- الحمولات موقعة بـ HMAC-SHA256 حتى تتمكن من التحقق من الأصالة
- مهلة التسليم هي 10 ثوانٍ لكل خطاف ويب
- التسليم من نوع أطلق وانسَ -- فشل خطاف ويب واحد لا يمنع الآخرين
إنشاء خطاف ويب
من لوحة التحكم
- انتقل إلى خطافات الويب في لوحة تحكم DocMap الخاصة بك
- انقر على إنشاء خطاف ويب
- أدخل عنوان URL لنقطة النهاية الخاصة بك (يجب أن يكون HTTPS في الإنتاج)
- اختر الأحداث التي تريد الاشتراك فيها
- انسخ سر التوقيع فوراً -- لن يُعرض مرة أخرى
من API
curl -X POST https://api.docmap.io/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/docmap",
"events": ["extraction.completed", "extraction.failed"]
}'const response = await fetch("https://api.docmap.io/v1/webhooks", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://your-app.com/webhooks/docmap",
events: ["extraction.completed", "extraction.failed"],
}),
});
const { data } = await response.json();
// Store this immediately -- it will never be shown again
console.log("Signing Secret:", data.secret);
console.log("Webhook ID:", data.webhook.id);import requests
response = requests.post(
"https://api.docmap.io/v1/webhooks",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={
"url": "https://your-app.com/webhooks/docmap",
"events": ["extraction.completed", "extraction.failed"],
},
)
data = response.json()["data"]
# Store this immediately -- it will never be shown again
print("Signing Secret:", data["secret"])
print("Webhook ID:", data["webhook"]["id"])WARNING
يُرجع سر التوقيع مرة واحدة فقط عند إنشاء خطاف الويب. خزّنه بشكل آمن في متغير بيئة أو مدير أسرار.
تنسيق الحمولة
عند حدوث حدث، يرسل DocMap طلب POST إلى عنوان URL لخطاف الويب الخاص بك بالبنية التالية:
{
"event": "extraction.completed",
"data": {
"id": "extract-abc123",
"userId": "uid_xyz789",
"templateId": "tpl_inv001",
"templateName": "Standard Invoice",
"fileName": "invoice-march.pdf",
"status": "completed",
"extractedData": {
"vendor_name": "Acme Corp",
"invoice_number": "INV-2024-003",
"total_amount": 4750.00
},
"error": null,
"variables": [...],
"source": "api",
"runId": null,
"processingTimeMs": 3842,
"createdAt": "2024-11-20T14:30:00.000Z"
},
"timestamp": "2024-11-20T14:30:04.000Z"
}الترويسات
يتضمن كل طلب خطاف ويب هذه الترويسات:
| الترويسة | الوصف |
|---|---|
Content-Type | application/json |
X-DocMap-Signature | توقيع HMAC-SHA256: sha256={hex_digest} |
X-DocMap-Event | اسم الحدث (مثال: extraction.completed) |
التحقق من التوقيعات
تحقق دائماً من ترويسة X-DocMap-Signature للتأكد من أن الطلب جاء من DocMap. التوقيع هو تجزئة HMAC-SHA256 لجسم الطلب الخام، باستخدام سر التوقيع كمفتاح.
import { createHmac, timingSafeEqual } from 'node:crypto'
function verifyWebhookSignature(
body: string,
signature: string,
secret: string,
): boolean {
const expected = createHmac('sha256', secret)
.update(body)
.digest('hex')
const received = signature.replace('sha256=', '')
return timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(received, 'hex'),
)
}
// Express example
app.post('/webhooks/docmap', (req, res) => {
const signature = req.headers['x-docmap-signature'] as string
const body = JSON.stringify(req.body)
if (!verifyWebhookSignature(body, signature, process.env.DOCMAP_WEBHOOK_SECRET!)) {
return res.status(401).send('Invalid signature')
}
const { event, data } = req.body
console.log(`Received ${event} for extraction ${data.id}`)
// Process the webhook...
res.status(200).send('OK')
})import hmac
import hashlib
def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode('utf-8'),
body,
hashlib.sha256,
).hexdigest()
received = signature.replace('sha256=', '')
return hmac.compare_digest(expected, received)
# Flask example
from flask import Flask, request
app = Flask(__name__)
@app.post('/webhooks/docmap')
def handle_webhook():
signature = request.headers.get('X-DocMap-Signature', '')
body = request.get_data()
if not verify_webhook_signature(body, signature, WEBHOOK_SECRET):
return 'Invalid signature', 401
payload = request.get_json()
event = payload['event']
data = payload['data']
print(f"Received {event} for extraction {data['id']}")
# Process the webhook...
return 'OK', 200TIP
استخدم دائماً مقارنة ثابتة الوقت (مثل timingSafeEqual أو hmac.compare_digest) لمنع هجمات التوقيت.
مرجع الأحداث
| الحدث | المحفز |
|---|---|
extraction.completed | اكتمل الاستخراج بنجاح. data.status هو "completed" وdata.extractedData يحتوي على النتائج. |
extraction.failed | فشل الاستخراج. data.status هو "failed" وdata.error يحتوي على رسالة الخطأ. |
أفضل الممارسات
استخدم HTTPS. استخدم دائماً نقطة نهاية HTTPS لعنوان URL لخطاف الويب الخاص بك. قد تُرفض نقاط نهاية HTTP في الإنتاج.
تحقق من التوقيعات. تحقق دائماً من ترويسة
X-DocMap-Signatureقبل معالجة خطاف الويب. هذا يؤكد أن الطلب من DocMap ولم يتم التلاعب به.استجب بسرعة. أرجع رمز حالة 2xx في غضون ثوانٍ قليلة. ينتظر DocMap حتى 10 ثوانٍ للحصول على استجابة. إذا استغرقت معالجتك وقتاً أطول، اعترف بخطاف الويب فوراً وعالجه بشكل غير متزامن.
تعامل مع التكرارات. في حالات نادرة، قد يُسلّم خطاف الويب أكثر من مرة. استخدم معرّف الاستخراج
idلإلغاء التكرار عند الحاجة.خزّن السر بأمان. احتفظ بسر التوقيع في متغير بيئة أو مدير أسرار. لا تكتبه مباشرة في الكود المصدري أو ترفعه إلى نظام التحكم بالإصدارات.
راقب حالات الفشل. إذا كانت نقطة النهاية الخاصة بك تفشل باستمرار، فكّر في فحص سجلات خادمك. يسجّل DocMap حالات فشل التسليم لكنه لا يعيد المحاولة.
