سیستم مدیریت و سفارشگیر یکپارچه کافه روشن بر بستر Cloudflare Workers، دیتابیس Cloudflare D1 (SQLite)، فضای ذخیرهسازی Cloudflare KV، و ربات مدیریت تلگرام.
- Backend / Edge Runtime: پیادهسازی شده با Cloudflare Workers (ماژولهای استاندارد ES) جهت پاسخدهی بلادرنگ با حداقل تاخیر در Edge.
- Database (D1): پایگاه داده SQLite ابری برای نگهداری محصولات (
products)، دستهبندیها (categories)، تنظیمات سایت (site_settings)، سفارشها (orders) و وضعیت نشستهای ربات و تلاشهای ناموفق ورود ادمین (bot_state). - Object / Blob Storage (KV): ذخیرهسازی فایل تصاویر و کشینگ ساختار منو.
- Static Assets: رابط کاربری عمومی مشتریان و پنل مدیریت ادمین در پوشه
public/به صورت داراییهای ایستا سرو میشوند. - Telegram Bot: اعلان آنی سفارشهای ثبتشده به مدیران کافه و امکان تایید/رد دوطرفه، مدیریت منو و آپلود تصویر مستقیماً از تلگرام.
- Node.js: نسخه
22یا بالاتر (node -v >= 22). - Wrangler: ابزار رسمی Cloudflare Workers (نسخه موجود در
devDependencies).
npm install
# یا در محیطهای CI:
npm ciتستها با استفاده از node:test داخلی نود اجرا میشوند و نیازی به ابزارهای جانبی ندارند (شامل بیش از ۱۶۰ تست جامع برای اعتبارسنجی، سفارشها، ادمین و ربات تلگرام):
npm test
# اجرای اختصاصی تستهای تلگرام:
node --test test/telegram.test.jsnpm run db:migrate:localnpm run devفایل wrangler.jsonc ساختار منابع ابری را مشخص میکند:
- دیتابیس D1 با بایندینگ
DB - فضای KV با بایندینگ
PRODUCTS_KV - داراییهای استاتیک با بایندینگ
ASSETS
برای محیط پروداکشن، این متغیرها را با دستور wrangler secret put <NAME> تنظیم کنید:
| نام متغیر | نوع | توضیحات |
|---|---|---|
JWT_SECRET |
Secret | کلید محرمانه برای امضا و اعتبارسنجی توکنهای ادمین (HMAC-SHA256). |
ADMIN_PASSWORD |
Secret | رمز عبور ورود به پنل مدیریت وب. |
TOKEN_VERSION |
Variable/Secret | نسخه توکنهای ادمین (پیشفرض "1"). در صورت نیاز به باطلسازی تمام نشستها مقدار آن افزایش مییابد. |
TELEGRAM_BOT_TOKEN |
Secret | توکن ربات تلگرام کافه دریافتی از BotFather. |
ADMIN_IDS |
Secret / Var | لیست آیدیهای عددی تلگرام مدیران (جداشده با کاما، مثلاً 1234567,8901234). |
WEBHOOK_SECRET |
Secret | رشته تصادفی و امن برای اعتبارسنجی وبهوکهای دریافتی از تلگرام. |
TABLE_SIGNING_SECRET |
Secret | توصیهشده برای پروداکشن (اختیاری در توسعه). کلید محرمانه جهت امضای شماره میز در کدهای QR (/?t=X&sig=...) با HMAC-SHA256 برای جلوگیری از ثبت سفارشهای جعلی خارج از کافه. سکرت فقط کلید امضاست و روشن/خاموش بودن الزام امضا از پنل وب (تب «تصاویر و تنظیمات») یا ربات (دکمه «🔐 امضای QR میزها») کنترل میشود (پیشفرض هنگام ست بودن سکرت و ثبت نشدن تنظیم: روشن). |
IP_HASH_SECRET |
Secret | توصیهشده. کلید محرمانه جهت هش کردن IP مشتریان با HMAC-SHA256 (جلوگیری از حملات rainbow table/brute-force روی آدرسهای IPv4). در صورت تنظیم نشدن، از JWT_SECRET به عنوان کلید پیشفرض استفاده میشود. |
ENFORCE_ORDER_HOURS |
Variable | اختیاری. اگر "0" باشد، ساعت کاری برای ثبت سفارش چک نمیشود (مثلاً برای تست شبانه). پیشفرض: فعال. |
SITE_URL |
Variable | اختیاری. آدرس پایه سایت (مثلاً https://cafe-roshan.ir) جهت تولید لینکهای sitemap.xml، robots.txt و تگهای canonical. در صورت خالی بودن از Host هدر درخواست استفاده میشود. |
مایگریشنها در پوشه migrations/ نگهداری میشوند:
0001_init.sql: جداول پایه دستهبندیها و محصولات0002_add_original_price.sql: پشتیبانی از تخفیف و قیمت اولیه0003_clear_dead_image_paths.sql: پاکسازی مسیرهای منقضی تصویر0004_add_available_column.sql: فیلد موجود/ناموجود بودن محصول0005_add_orders_table.sql: جدول ثبت سفارشها0006_orders_hardening.sql: فیلدهای ضدتکرار، هش آیپی و پیامهای تلگرام0007_site_settings.sql: جدول تنظیمات سایت برای ذخیره لوگو، تصویر کاور و تعداد میزها (logo,cover,tableCount)0008_orders_summary_index.sql: ایندکس ترکیبی برای خلاصهسازی سفارشهای در انتظار0009_orders_table_pending_index.sql: ایندکس بهینهسازی بررسی سقف سفارش در انتظار هر میز0010_bot_state.sql: جدول نگهداری سشنهای چندمرحلهای ربات تلگرام، پیامهای قبلی و قفل ورود ادمین با پشتیبانی از TTL/انقضا0011_normalize_image_paths.sql: یکسانسازی مسیر تصاویر به فرمت/images/<filename>0012_add_order_public_id.sql: افزودن شناسه عمومی تصادفی (public_id) به سفارشها برای استعلام عمومی وضعیت سفارش
npm run db:migrate:remoteپس از دیپلوی ورکر، آدرس وبهوک تلگرام (/tg-webhook) را به همراه سکرت توکن ست کنید:
curl -F "url=https://your-domain.workers.dev/tg-webhook" \
-F "secret_token=YOUR_WEBHOOK_SECRET" \
https://api.telegram.org/bot<YOUR_TELEGRAM_BOT_TOKEN>/setWebhook(مقدار secret_token باید دقیقاً با مقدار secret متغیر WEBHOOK_SECRET همخوانی داشته باشد).
- اعتبارسنجی فایلهای آپلودی: بررسی بایتهای جادویی (Magic bytes) برای فرمتهای JPEG، PNG، WebP و GIF جهت جلوگیری از آپلود بدافزار یا فایلهای متنی با پسوند جعلی.
- مقاومت در برابر حملات زمانبندی (Timing-Safe Compare): استفاده از مقایسه با زمان ثابت در بررسی رمز عبور، سکرت وبهوک و توکنها.
- محدودیت نرخ و قفل حساب ادمین: قفل تدریجی آیپی و محدودسازی پس از ۱۵ تلاش ناموفق برای ورود. (پیشنهاد میشود برای محافظت در لبه شبکه، یک Cloudflare Rate Limiting Rule برای مسیر
/admin/api/loginتنظیم گردد تا از حملات توزیعشده جلوگیری شود). - کنترل نرخ سفارشات و هانیپات: محدودیت ۱۰ سفارش در هر ۱۰ دقیقه برای هر آیپی (با ذخیره هش امن SHA-256 و بدون ذخیره آیپی خام)، و محدودیت ۳ سفارش در انتظار برای هر میز.
- جلوگیری از سفارش تکراری (Idempotency): پشتیبانی از کلید یکتا برای هر سفارش جهت مقابله با ارسال مجدد در صورت قطع و وصل شبکه مشتری.
- تایید دوطرفه سفارش (Two-Way Sync): هماهنگی کامل تغییر وضعیت سفارشها بین تلگرام و پنل وب همراه با بروزرسانی پیامهای ثبتشده در کانالهای ادمین.
- محاسبات فروش بر مبنای افق زمانی تهران: محاسبه دقیق آمار فروش امروز/هفته/ماه با در نظر گرفتن مبدا شنبه و منطقه زمانی رسمی ایران (
+03:30).
در wrangler.jsonc برنامه زمانی * * * * * (اجرا در هر دقیقه) تنظیم شده است که عملیات زیر را به صورت خودکار انجام میدهد:
۱. تلاش مجدد برای اعلان سفارشهای در انتظار: سفارشهایی که بین ۱ دقیقه تا ۲ ساعت گذشته ثبت شدهاند اما اعلان تلگرامی آنها ارسال نشده (tg_notified = 0) را بازیابی کرده و مجدداً برای ادمینها میفرستد.
۲. پاکسازی وضعیتهای منقضی: ردیفهای منقضیشده از جدول bot_state (از جمله سشنهای پیشین ربات تلگرام و شمارندههای موقت خطا) به صورت خودکار حذف میشوند.
ساعت کاری فقط در OPENING_HOURS داخل src/config.js تعریف میشود. نوار وضعیت سایت، لیست ساعات کاری، قفل دکمهی ثبت سفارش و رد سفارش در سرور همه از همین مقدار استفاده میکنند. برای تغییر، همانجا را عوض کنید و دیپلوی کنید.
برای انتشار نسخه جدید بر روی کلودفلر:
npm run deploy- عدم کارکرد Cache API و ابزار تغییر اندازه تصاویر (
cf.image) روی*.workers.dev: در سرویس Cloudflare Workers، قابلیت ریسایز تصویر بر بسترcf.imageو رابطcaches.default(کش لبه) روی دامنههای رایگان*.workers.devغیرفعال است؛ در نتیجه مسیرهای بندانگشتی (/images/thumb/*) به تصویر اصلی با هدر کش fallback میکنند و هر بار درخواست تصویر به یک خواندن از KV (KV Read) تبدیل میشود که سهمیه پلن رایگان را مصرف میکند. برای حل این موضوع و برخورداری از مزایای کش کامل و ریسایز لبه، اتصال دامنه اختصاصی (Custom Domain) یا استفاده از Cloudflare R2 توصیه میشود.
پس از هر دیپلوی، دسترسی مسیرهای کلیدی را با دستورات curl زیر بررسی کنید تا از هدایت صحیح آنها به Worker (از طریق run_worker_first) اطمینان حاصل شود:
# ۱. وبهوک تلگرام (باید توسط ورکر هندل شود، نه صفحه ۴۰۴ استاتیک)
curl -sI -X POST https://<domain>/tg-webhook | grep -i "HTTP/"
# ۲. اندپوینت ثبت و پیگیری سفارشها
curl -sI -X POST https://<domain>/api/orders | grep -i "HTTP/"
# ۳. اندپوینت API ادمین (درخواست بدون توکن باید ۴۰۱ ورکر بدهد)
curl -sI https://<domain>/admin/api/me | grep -i "HTTP/"
# ۴. هندلر تصاویر
curl -sI https://<domain>/images/placeholder.jpg | grep -i "HTTP/"
# ۵. دادههای پویا، robots و sitemap
curl -sI https://<domain>/data/products.json | grep -i "HTTP/"
curl -sI https://<domain>/data/site.json | grep -i "HTTP/"
curl -sI https://<domain>/robots.txt | grep -i "HTTP/"
curl -sI https://<domain>/sitemap.xml | grep -i "HTTP/"
# ۶. هدرهای امنیتی و CSP پنل ادمین (هدایت از طریق run_worker_first)
curl -sI https://<domain>/admin/ | grep -i -E "content-security|x-frame"