واجهة تسجيل الحضور POST /api/checkin
المسار: تطوير نظام إدارة الأعراس ودعوات QR الوحدة: واجهات API والبنية الخلفية
مدخل إلى الدرس: واجهة تسجيل الحضور POST /api/checkin
واجهة تسجيل الحضور POST /api/checkin — نظام إدارة الأعراس والمناسبات ودعوات QR | Next.js وPrisma | أديب الصلوي
طريقة الدراسة: اقرأ التعريف، تتبّع المثال في الشرح، نفّذه بنفسك، ثم اختبر النتيجة والحالات الاستثنائية قبل الانتقال.
أهداف هذا الدرس
- تنفيذ قراءة QR → استخراج token وإثبات صحته.
- تسجيل حضور بمنع التكرار عبر إنشاء CheckIn.
- تغذية الاستجابة المولّدة للواجهة (اسم، حالات).
مثال
// app/api/checkin/route.ts
import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { tokenHashOf, verifySignature } from "@/lib/tsign";
export async function POST(req: Request) {
const { token, sig, eventId } = await req.json();
if (!token || !sig || !eventId) {
return NextResponse.json({ ok: false, error: "معطيات ناقصة" }, { status: 400 });
}
// 1) التحقق من التوقيع قبل أي بحث
if (!verifySignature(token, sig)) {
return NextResponse.json({ ok: false, error: "توقيع غير صالح" }, { status: 403 });
}
// 2) العثور على الضيف بالهاش
const guest = await prisma.guest.findUnique({
where: { tokenHash: tokenHashOf(token) },
});
if (!guest) {
return NextResponse.json({ ok: false, error: "ضيف غير موجود" }, { status: 404 });
}
if (guest.eventId !== eventId) {
return NextResponse.json({ ok: false, error: "رمز لمناسبة أخرى" }, { status: 409 });
}
// 3) منع الحضور المزدوج
const existing = await prisma.checkIn.findFirst({
where: { guestId: guest.id, eventId },
});
if (existing) {
return NextResponse.json(
{ ok: false, error: "سبق تسجيل هذا الضيف", firstSeen: existing.checkedInAt },
{ status: 409 }
);
}
const checkIn = await prisma.checkIn.create({
data: { guestId: guest.id, eventId },
});
return NextResponse.json({ ok: true, data: { guest: guest.name, checkIn } }, { status: 201 });
}المخطط: مسار قراءة الـ QR في البوابة (فرزة)
flowchart TD
A["جهاز الفرزة (كاميرا)
مسح → token, sig, eventId"] --> V{"تحقق التوقيع"}
V -->|فشل| E403["403 توقيع غير صالح"]
V -->|نجح| GH{"جلب بالـ hash"}
GH -->|لا ضيف| E404["404"]
GH -->|موجود| CH{"CheckIn مسبق؟"}
CH -->|نعم| E409["409 أول حضور في: ..."]
CH -->|لا| OK["create CheckIn"] --> OK2["201 { guest }"]
الفضائل الأمنية
الترتيب مهم: نرفض التوقيع قبل أي جلب (لا نكشف وجود ضيف)، ونرفض تكرار الحضور قبل الكتابة بنفس الطلب حتى لو ضغط الموظف مرتين متتاليتين.
تمرين تطبيقي: أضف شرطاً يمنع المسح قبل وقت الحفل أو بعده (بالمقارنة مع event.date) وأعد رسالة خطأ مناسبة — سترى الفرق يجعل التجربة واقعية.
أخطاء شائعة يجب تفاديها
- تسجيل الحضور قبل التحقق من التوقيع — باب مفتوح للتزوير.
- السماح للمسح المزدوج بالكتابة twice مع كسر UNIQUE.
- كشف تفاصيل قدرة الضيف (كم عدد ضيوفه) في ردّ الخطأ.
معجم مصطلحات الدرس
- CheckIn
- سطر حضور: ضيف + مناسبة + لحظة دخول.
- تحقق توقيع
- إثبات أن محتوى الرمز لم يُعدَّل من طرف غير الخادم.
- منع مزدوج
- رفض كتابة حضور ثاني لنفس الضيف/المناسبة.
مراجعة وتمرين تثبيت المهارة
اختبار سريع: اشرح بعبارتك معنى «واجهة تسجيل الحضور POST /api/checkin»، ثم بيّن أين ستستخدمه داخل نظام تسجيل حضور دعوات مناسبة عبر رمز QR، وما الخطأ الذي يجب اختباره قبل الاعتماد على الحل.
تحدٍّ إضافي: غيّر شرطًا واحدًا في التطبيق، وتوقع النتيجة، ثم نفّذ الاختبار وفسّر الاختلاف.
الدرس التالي: التحقق من المدخلات ومعالجة الأخطاء. من الأفضل إنهاء التجربة الحالية قبل متابعة الدرس التالي.