WP Manifestindependent plugin directory
manifest / ecommerce / basalamhub

باسلام‌هاب – همگام‌سازی ووکامرس و باسلام

فروشگاه ووکامرس و غرفه‌ی باسلام را دوطرفه همگام نگه می‌دارد: محصول یک بار ثبت می‌شود، در دو جا فروخته می‌شود و هیچ سفارشی گم نمی‌شود.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/tahakarami-dev/basalamhub/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

باسلام‌هاب – همگام‌سازی ووکامرس و باسلام

افزونه‌ی وردپرسی که فروشگاه ووکامرس و غرفه‌ی باسلام را دوطرفه همگام نگه می‌دارد. سند فیچرها: «باسلام‌هاب — سند فیچرهای نسخه ۱». سیستم طراحی: Design System باسلام‌هاب (کلاس‌های bsh-).

وضعیت فازها

فاز (هفته) خروجی وضعیت
۱ هسته، اتصال، صفحه‌ی سلامت، ارسال محصول ساده، لاگ ✅ انجام شد (v0.1.0)
۲ ارسال گروهی، نگاشت دسته، قوانین قیمت، تصاویر ✅ انجام شد (v0.2.0)
۳ محصولات متغیر، اتصال محصولات موجود غرفه ✅ انجام شد (v0.4.0)
۴ سفارش‌ها، موجودی دوطرفه، موجودی احتیاطی ✅ انجام شد (v0.5.0)
۵ ایمپورت کل غرفه، تطبیق شبانه، اعلان‌ها ✅ انجام شد (v0.6.0)
۶ تست فشار، رفع باگ، آماده‌سازی انتشار ✅ انجام شد (v0.7.0) — تأیید روی غرفه‌ی واقعی باقی است

فاز ۱ — چه چیزی تحویل شد

اتصال و پایه

  • اتصال با توکن شخصی باسلام؛ توکن با libsodium (یا AES-256-GCM) رمزنگاری می‌شود و فقط ۴ کاراکتر آخرش نمایش داده می‌شود.
  • دکمه‌ی «تست اتصال»: نام و شناسه‌ی غرفه یا خطای فارسی قابل‌فهم.
  • صفحه‌ی داشبورد/سلامت: وضعیت توکن، آخرین همگام‌سازی، صف، رمزنگاری، PHP، ووکامرس، واحد پول، ۱۰ خطای اخیر، و هشدار WP-Cron خاموش.
  • صف پس‌زمینه روی Action Scheduler (همراه ووکامرس): هیچ درخواست API از بارگذاری صفحه نمی‌رود، فقط یک کار باسلام‌هاب در هر لحظه اجرا می‌شود (قفل اتمیک روی جدول options)، بعد از قطعی ادامه می‌دهد، و خطاهای موقت (شبکه، 5xx، 429) با فاصله‌ی ۱، ۵، ۱۵، ۶۰ و ۱۸۰ دقیقه خودکار تکرار می‌شوند. هر ساعت، محصولی که «در صف» مانده ولی کاری برایش منتظر نیست دوباره در صف قرار می‌گیرد.

ارسال محصول ساده

  • دکمه‌ی «ارسال به باسلام» در صفحه‌ی ویرایش محصول (وضعیت زنده بدون رفرش).
  • به‌روزرسانی خودکار بعد از ذخیره‌ی محصول یا تغییر موجودی ناشی از سفارش؛ فقط همان محصول در صف می‌رود.
  • انتخاب فیلدهای همگام: اگر فقط «قیمت و موجودی» تیک بخورد، فقط همان‌ها PATCH می‌شوند.
  • ضدتکرار: جدول اتصال‌ها؛ اگر پاسخ ساخت محصول گم شود (Timeout)، قبل از ساخت دوباره با SKU جستجو می‌شود. محصول بدون SKU، SKU ثابت BSH-{id} می‌گیرد.
  • محصولی که تغییری نکرده دوباره ارسال نمی‌شود (هش payload).
  • محافظ قیمت: قیمت صفر یا منفی هرگز ارسال نمی‌شود.
  • تصویر هر فایل فقط یک بار آپلود می‌شود مگر خود فایل عوض شود.
  • ستون وضعیت «باسلام» در لیست محصولات با چهار وضعیت ثابت.

لاگ فارسی

  • هر رویداد: چه چیزی، چه شد، چرا، چه کار کنی؛ پاسخ خام API فقط در «جزئیات فنی».
  • تلاش مجدد تکی و گروهی، فیلتر و جستجو، حذف خودکار لاگ‌های قدیمی. توکن هرگز در لاگ نوشته نمی‌شود.

فاز ۲ — چه چیزی تحویل شد

ارسال گروهی

  • صفحه‌ی «ارسال گروهی»: انتخاب «فقط ارسال‌نشده‌ها» یا «همه» و فیلتر دسته، با تعداد دقیق قبل از تأیید.
  • از لیست محصولات ووکامرس هم: کارهای دسته‌جمعی › «ارسال به باسلام».
  • درخواست مرورگر فقط یک «برنامه‌ریز» در صف می‌گذارد؛ برنامه‌ریز ۱۰۰ تا ۱۰۰ محصول را در پس‌زمینه به صف اضافه می‌کند. مرورگر می‌تواند بسته شود.
  • نوار پیشرفت زنده (موفق، خطا، در صف)، خلاصه در لاگ، دکمه‌ی توقف. فقط یک ارسال گروهی هم‌زمان.
  • محدودیت درخواست (429): کل صف یک بار مکث می‌کند و از همان‌جا ادامه می‌دهد؛ تلاش‌های محصول مصرف نمی‌شود و لاگ پر از هشدار تکراری نمی‌شود.

نگاشت دسته‌ها

  • دریافت درخت دسته‌های باسلام و جستجو با نام («خوراکی › عسل (1287)»). فقط دسته‌ی آخر (بدون زیرمجموعه) پذیرفته می‌شود.
  • زیردسته از نگاشت دسته‌ی والد ارث می‌برد. ترتیب: دسته‌ی خود محصول › نگاشت عمیق‌ترین دسته › دسته‌ی پیش‌فرض.
  • ویژگی‌های اجباری دسته‌ی باسلام (ریسک سند): مقدار پیش‌فرض برای هر نگاشت؛ اگر محصول ویژگی ووکامرسی هم‌نام داشته باشد مقدار خود محصول استفاده می‌شود. محصولی که ویژگی اجباری ندارد، قبل از تماس با API با نام ویژگی‌ها متوقف می‌شود.
  • هشدار دسته‌های نگاشت‌نشده در داشبورد، صفحه‌ی ارسال گروهی و لاگ (با نام دسته‌ی ووکامرس).

قوانین قیمت

  • قانون سراسری و قانون جدا برای هر دسته (درصدی یا مبلغ ثابت تومانی، افزایش یا کاهش)؛ قانون دسته اولویت دارد و زیردسته‌ها ارث می‌برند.
  • گردکردن به ۱۰۰، ۱٬۰۰۰ یا ۱۰٬۰۰۰ تومان (رو به بالا، نزدیک‌ترین، رو به پایین).
  • پیش‌نمایش قیمت سایت در برابر قیمت باسلام. قیمت صفر یا منفی هرگز ارسال نمی‌شود.

تصاویر

  • تصویر بزرگ‌تر از ۲۰۴۸ پیکسل یا ۲ مگابایت روی یک کپی کوچک و فشرده می‌شود؛ WebP/AVIF به JPEG تبدیل می‌شود. فایل اصلی سایت دست نمی‌خورد و کپی بلافاصله پاک می‌شود.
  • حداکثر ۱۰ تصویر برای هر محصول. محدودیت‌ها با فیلتر bsh_image_limits قابل تغییرند (باید روی غرفه‌ی واقعی تأیید شوند).

فیچرهای v0.9.0 — برای ارائه

«امروز چی شد» (بالای داشبورد)

  • یک جمله‌ی فارسی از وضع امروز: «امروز تا این لحظه ۵ سفارش (۳ از باسلام) به ارزش ۲٫۱ میلیون تومان ثبت شده؛ ۲ کالای باسلام رو به اتمام است.» به‌همراه سفارش امروز، فروش امروز و سهم باسلام. رنگ کارت با وضع روز عوض می‌شود. سلام بالای صفحه به وقت سایت است («صبح بخیر»…).

امتیاز سلامت فروشگاه از ۱۰۰

  • از ۱۰۰ شروع می‌شود و هر مشکل امتیاز کم می‌کند: ردیف قرمز سلامت سیستم ۲۰، ردیف زرد ۸، هر خطای باز ۲۴ ساعت ۲ (حداکثر ۱۰)، هر سفارش جاافتاده ۱۰ (حداکثر ۲۰)، هر محصول خطادار ۱ (حداکثر ۱۰).
  • ۹۰ به بالا «عالی» (سبز)، ۷۰ تا ۸۹ «خوب» (زرد)، کمتر «نیاز به توجه» (قرمز). دلیل هر کسر با لینک رفعش زیر عدد نوشته می‌شود؛ یعنی امتیاز هیچ‌وقت راز نیست.

اعلان زنده‌ی سفارش

  • وقتی پنل باز است، هر ۱۵ ثانیه (فقط اگر تب دیده می‌شود) سفارش‌های تازه‌ی باسلام بررسی می‌شوند؛ هر سفارش تازه یک پیغام کوچک با شماره، مبلغ، تعداد قلم و شهر و دکمه‌ی «مشاهده» نشان می‌دهد. با باز کردن پنل سفارش‌های قدیمی دوباره نمایش داده نمی‌شوند. در داشبورد، فروش و سفارش‌ها عددها همان لحظه تازه می‌شوند.

حالت نمایشی

  • برای معرفی افزونه بدون غرفه‌ی واقعی: ۸ محصول نمونه، حدود ۳۵ روز سفارش در دو کانال، دو کالای رو به اتمام و چند رویداد لاگ. دکمه‌ی «شبیه‌سازی سفارش باسلام» یک سفارش تازه می‌سازد تا اعلان زنده (و اگر روشن است، پیام بله/تلگرام) را جلوی مخاطب ببینی.
  • امنیت داده: هر چیز نمایشی نشانه‌ی _bsh_demo دارد. محصول نمایشی هرگز در صف ارسال نمی‌رود، تغییر وضعیت سفارش نمایشی به باسلام نمی‌رود، کسر موجودی و به‌روزرسانی وضعیت هم آن‌ها را رد می‌کنند. حین ساخت و پاک کردن هیچ ایمیل ووکامرس و هیچ پیام بله/تلگرامی فرستاده نمی‌شود. «پاک کردن داده‌ی نمایشی» فقط چیزهای نشانه‌دار را پاک می‌کند و وضعیت تطبیق شبانه را برمی‌گرداند. حذف افزونه هم داده‌ی نمایشی باقی‌مانده را پاک می‌کند.

فیچرهای v0.8.0 — فروش، هشدار موجودی، گزارش هفتگی

داشبورد «فروش دوکاناله» (صفحه‌ی «فروش»)

  • فروش سایت و باسلام کنار هم برای ۷، ۳۰ یا ۹۰ روز: مبلغ، تعداد سفارش، تغییر نسبت به دوره‌ی قبل، سهم باسلام از کل فروش و میانگین سفارش.
  • سود باسلام پس از کمیسیون: درصد کمیسیون را وارد می‌کنی؛ روی مبلغ کالاها (نه هزینه‌ی ارسال) حساب می‌شود. عدد تخمینی است.
  • نمودار ستونی انباشته‌ی روزانه با همان رنگ‌های آزموده برای کوررنگی، tooltip، و جدول داده برای دسترس‌پذیری؛ پرفروش‌های هر کانال.
  • مستقیم از جدول‌های سفارش (HPOS یا قدیمی) خوانده می‌شود، پس به فعال‌بودن WooCommerce Analytics وابسته نیست؛ نتیجه ۱۰ دقیقه کش می‌شود و هر سفارش تازه کش را تازه می‌کند. سفارش باسلام = سفارشی که باسلام‌هاب ساخته.
  • حساب می‌شوند: در حال انجام، تکمیل‌شده، در انتظار. استرداد جزئی کسر نمی‌شود.

هشدار کمبود موجودی

  • وقتی موجودی کالایی که در باسلام است به حد هشدار (پیش‌فرض ۳، یا «آستانه‌ی کمبود» خود محصول در ووکامرس) برسد یا تمام شود: هشدار فارسی در لاگ و پیام بله/تلگرام.
  • فقط عبور از حد هشدار پیام می‌دهد؛ ماندن در کمبود تکرار نمی‌شود و با شارژ موجودی از نو فعال می‌شود. محصولاتی که در باسلام نیستند هشدار نمی‌دهند.
  • فهرست کالاهای رو به اتمام در صفحه‌ی فروش و یک ردیف در سلامت داشبورد.

گزارش هفتگی

  • شنبه‌ها ساعت ۹ صبح (به وقت سایت): فروش دو کانال با تغییر نسبت به هفته‌ی قبل، سهم باسلام، سود پس از کمیسیون، پرفروش باسلام، سفارش جاافتاده، خطاها و کالاهای رو به اتمام؛ در لاگ و بله/تلگرام.
  • دکمه‌ی «ساخت و ارسال الان» در صفحه‌ی اعلان‌ها با پیش‌نمایش متن.

فاز ۶ — تست فشار، رفع باگ، آماده‌سازی انتشار (v0.7.0)

تغییر کامل نام به «باسلام‌هاب»: نامک basalamhub، فایل اصلی basalamhub.php، پیشوند کد و دیتابیس bsh_. نصب‌های قبلی (سلام‌هاب) خودکار منتقل می‌شوند: جدول‌ها، تنظیمات، متای محصول و سفارش (HPOS هم)، کارهای صف، دکمه‌های تلاش مجدد لاگ و توکن‌های رمزنگاری‌شده. افزونه‌ی قدیمی غیرفعال می‌شود تا دو نسخه هم‌زمان همگام نکنند؛ حذفش بعداً بی‌خطر است. آدرس وب‌هوک قدیمی و SKU ساختگی قدیمی (SLH-{id}) همچنان کار می‌کنند. روی یک نصب واقعی نسخه‌ی قبلی هم امتحان شد.

تست فشار (tests/stress/stress.php، روی سرور ساختگی با حالت «آشوب»: 429، خطای 5xx، تأخیر و پاسخ گم‌شده‌ی ساخت محصول):

سناریو نتیجه
ارسال گروهی ۱۰۰۰ محصول (API سالم) هر ۱۰۰۰ همگام، بدون تکرار؛ کلیک دکمه ۸ میلی‌ثانیه؛ میانگین هر کار ۳۰ ms، کندترین ۰٫۵۴ ثانیه (سقف هاست اشتراکی معمولاً ۳۰ ثانیه)؛ عکس مشترک فقط یک بار آپلود شد
همان با آشوب (۱۵٪ 429، ۸٪ 5xx، ۵٪ پاسخ ساختِ گم‌شده، ۴۰ ms تأخیر) — ۵۰۰ محصول ۴۹۹ در دور اول، آخری با «تلاش مجدد همه»؛ صفر محصول تکراری با وجود ۳۱ پاسخ گم‌شده؛ هیچ محصولی بی‌صدا گم نشد
ایمپورت غرفه‌ی ۱۰۰۰ محصولی (۲۰٪ متغیر با ۳ تنوع، ۱۰٪ با عکس) هر ۱۰۰۰ ساخته شد؛ میانگین ۱۷۷ ms، کندترین ۰٫۵ ثانیه برای هر محصول؛ اجرای دوباره: صفر محصول جدید
تطبیق شبانه ۵۰۰ سفارش ۷ روز اخیر در ۲٫۸ ثانیه بررسی شد؛ در اجرای ۳۰۰تایی همه‌ی جاافتاده‌ها ثبت شدند و دور دوم صفر جاافتاده
صفحه‌های مدیریت با ۲۰ هزار ردیف لاگ و چند هزار محصول داشبورد ۶۷ ms، محصولات ۱۳۳ ms، لاگ ۱۵ ms، سفارش‌ها ۲۶ ms؛ پاک‌سازی ۲۰ هزار لاگ ۰٫۰۱ ثانیه

اعداد مال سرور ساختگی روی همین کانتینر است (PHP 8.3، SQLite)؛ روی هاست واقعی با تأخیر شبکه تا باسلام کندتر خواهد بود، ولی هر کار جدا و کوچک است و مرورگر هیچ‌وقت منتظر نمی‌ماند. سقف واقعی Rate limit باسلام هنوز نامعلوم است؛ افزونه 429 را با مکث سراسری و Retry-After مدیریت می‌کند.

باگ‌هایی که پیدا و رفع شد

  • ایمپورت غرفه یکی‌درمیان جا می‌انداخت وقتی «به‌روزرسانی محصولات متصل» خاموش بود (پیمایش با offset روی فهرستی که حین کار کوچک می‌شد). حالا با شناسه‌ی ردیف پیمایش می‌شود؛ تست رگرسیون اضافه شد. فقط با غرفه‌ی بزرگ دیده می‌شد.
  • نام ویژگی سراسری محصول وقتی کش ویژگی‌های ووکامرس کهنه بود به‌صورت slug (pa_…) ارسال می‌شد؛ حالا مستقیم از دیتابیس خوانده می‌شود.
  • انتقال جدول‌ها روی لایه‌هایی که RENAME TABLE ندارند، با کپی ردیف‌ها انجام می‌شود.

کیفیت و امنیت

  • سازگاری PHP 7.4 به بالا با PHPCompatibility: بدون ایراد.
  • قواعد امنیتی WordPress Coding Standards (escape، nonce، sanitize، prepare): همه‌ی موارد بررسی شد؛ هر درخواست AJAX و فرم nonce و دسترسی را چک می‌کند و SQL پویا فقط بخش‌های ثابت و عدد صحیح دارد.
  • قالب‌بندی کد طبق استاندارد وردپرس.

آماده‌سازی انتشار

  • readme.txt کامل برای مخزن وردپرس: توضیحات، نصب، پرسش‌های رایج، تصاویر، یادداشت ارتقا، و بخش External services (API باسلام، فایل‌های تصویر باسلام، Bot API بله و تلگرام) که مخزن وردپرس الزام می‌کند.
  • فایل ترجمه‌ی languages/basalamhub.pot (۷۹۳ رشته).
  • سربرگ «WC tested up to».

پیش از انتشار عمومی باید انجام شود (کار من به‌تنهایی کافی نیست):

  1. تأیید روی غرفه‌ی واقعی با توکن تست: واحد قیمت و وزن، شکل پاسخ سفارش‌ها، محدودیت تصاویر، رفتار PATCH تنوع‌ها، و سقف واقعی Rate limit.
  2. مجوز نام «باسلام‌هاب» از باسلام (مخزن وردپرس افزونه‌ای را که نامش با برند دیگری شروع شود معمولاً رد می‌کند).
  3. رشته‌های منبع فارسی‌اند؛ برای ترجمه‌ی جامعه در translate.wordpress.org رشته‌ی منبع انگلیسی استاندارد است. برای بازار ایران مشکلی نیست، ولی اگر انتشار بین‌المللی هدف است باید منبع انگلیسی و فایل fa_IR جدا شود.

فاز ۵ — چه چیزی تحویل شد (v0.6.0)

ایمپورت کل غرفه به ووکامرس (صفحه‌ی «ایمپورت غرفه»)

  • روی همان فهرست غرفه‌ای که «اتصال محصولات غرفه» می‌سازد کار می‌کند و پیش‌نمایش دارد: «ساخته می‌شود» (بدون جفت)، «به‌روز می‌شود» (متصل)، «منتظر بررسی تو» (قطعی/مشکوک: احتمالاً در سایت هستند، پس ساخته نمی‌شوند تا تکراری نشوند).
  • هر محصول با نام، توضیحات (به پاراگراف)، خلاصه، SKU، قیمت (ریال ← واحد فروشگاه؛ تخفیف باسلام = قیمت حراج)، موجودی (+ موجودی اطمینان)، وزن (گرم ← واحد فروشگاه)، ابعاد، زمان آماده‌سازی، عکس اصلی و گالری، دسته و تنوع‌ها (ویژگی‌ها، قیمت، موجودی و SKU هر تنوع) ساخته می‌شود؛ منتشرشده یا پیش‌نویس.
  • ضدتکرار: هر محصول بلافاصله به محصول باسلام وصل می‌شود (و نگاشت تنوع‌ها و شناسه‌ی فایل عکس‌ها ذخیره می‌شود). اجرای دوباره فقط به‌روز می‌کند؛ SKUای که در سایت هست ساخته نمی‌شود. بعد از ایمپورت هیچ‌چیز به باسلام برگردانده نمی‌شود و عکس‌ها دوباره آپلود نمی‌شوند.
  • دسته: دسته‌ی نگاشت‌شده؛ اگر نگاشتی نیست، دسته‌ای با نام دسته‌ی باسلام ساخته و به «نگاشت دسته‌ها» اضافه می‌شود.
  • با قانون قیمت فعال، قیمت محصولات متصل در به‌روزرسانی دست نمی‌خورد (وگرنه قانون دو بار اعمال می‌شد) و هشدار داده می‌شود.
  • یک محصول در هر کار پس‌زمینه؛ نوار پیشرفت، توقف، تلاش مجدد خودکار برای خطای موقت و دکمه‌ی «تلاش مجدد» برای بقیه. عکس خراب محصول را متوقف نمی‌کند (هشدار). با ارسال گروهی و اتصال هم‌زمان اجرا نمی‌شود.

تطبیق شبانه‌ی سفارش‌ها (پیام فروش «سفارش گم‌نشدنی»)

  • هر شب حدود ساعت ۳ به وقت سایت، همه‌ی سفارش‌های ۷ روز اخیر باسلام با ووکامرس مقایسه می‌شوند؛ هر سفارش جاافتاده (نه لغوشده) در صف ثبت قرار می‌گیرد و با شماره‌هایش در لاگ و اعلان گزارش می‌شود.
  • نتیجه‌ی آخرین اجرا در صفحه‌ی «سفارش‌ها» و سلامت داشبورد؛ اگر خطا داد یا بیش از دو روز اجرا نشد (WP-Cron خاموش)، قرمز/زرد می‌شود. دکمه‌ی «تطبیق الان».

اعلان بله و تلگرام (صفحه‌ی «اعلان‌ها»)

  • سفارش جدید باسلام (اقلام، مبلغ، گیرنده، لینک سفارش)، خطاهای مهم (با راه‌حل)، و سفارش‌های پیدا‌شده در تطبیق شبانه؛ هر رویداد و هر پیام‌رسان جدا خاموش‌شدنی.
  • توکن ربات رمزنگاری‌شده؛ «پیدا کردن شناسه» شناسه‌ی گفتگو را خودش از آخرین پیام به ربات برمی‌دارد؛ «پیام آزمایشی» نتیجه را همان لحظه نشان می‌دهد.
  • ارسال از صف پس‌زمینه با تلاش مجدد؛ هر خطا حداکثر هر ۶ ساعت یک بار و حداکثر ۱۰ پیام خطا در ساعت؛ شکست اعلان هیچ‌وقت اعلان دیگری نمی‌سازد.
  • تلگرام روی بیشتر هاست‌های ایران در دسترس نیست؛ پیام خطا همین را می‌گوید و بله را پیشنهاد می‌دهد. برای تلگرام آدرس واسط (relay) قابل تنظیم است.

باید روی غرفه‌ی واقعی تأیید شود: اینکه GET /v1/products/{id} برای محصولات خود غرفه (حتی منتشرنشده) همه‌ی فیلدها (توضیحات، عکس‌ها، تنوع‌ها، ابعاد) را برمی‌گرداند؛ واحد net_weight (گرم فرض شده)؛ و اینکه آدرس عکس‌های statics.basalam.com از هاست سایت قابل دانلود است.

فاز ۴ — چه چیزی تحویل شد (v0.5.0)

سفارش‌های باسلام → ووکامرس (صفحه‌ی «سفارش‌ها»)

  • منبع حقیقت، Polling است (پیش‌فرض هر ۵ دقیقه، قابل تنظیم ۲ تا ۶۰): جدیدترین محموله‌ها (/v1/vendor-parcels) با یک روز هم‌پوشانی دوباره خوانده می‌شوند، پس سفارشی که هنگام قطعی هاست جا مانده، دور بعد گرفته می‌شود. اولین بار سفارش‌های X روز گذشته (پیش‌فرض ۳) وارد می‌شوند.
  • وب‌هوک اختیاری (/wp-json/basalamhub/v1/basalam-webhook?key=…) فقط دریافت را جلو می‌اندازد؛ محتوایش باور نمی‌شود و جزئیات همیشه از API خوانده می‌شود.
  • هیچ سفارشی دوبار ثبت نمی‌شود: جدول اتصال (object_type=order) + متای _bsh_parcel_id روی خود سفارش + قفل جدا برای هر محموله داخل صف تک‌کارگره. حتی اگر ردیف اتصال پاک شود، متای سفارش جلوی تکرار را می‌گیرد و ردیف را بازسازی می‌کند.
  • سفارش با created_via=basalamhub، شماره‌ی محموله و سفارش باسلام، مبدأ «basalam» در Order attribution، نام/موبایل/آدرس/کدپستی/شهر و استان گیرنده، هزینه‌ی ارسال با نام روش ارسال، و تاریخ پرداخت ساخته می‌شود. مبالغ ریالی به واحد فروشگاه تبدیل می‌شوند.
  • اقلام از طریق اتصال محصولات به محصول (و برای محصول متغیر، به همان تنوع) وصل می‌شوند و موجودی سایت یک بار کم می‌شود. قلمی که در سایت پیدا نشود، بی‌اتصال ثبت می‌شود و هشدار فارسی با نام محصول و راه‌حل می‌آید؛ سفارش هیچ‌وقت به‌خاطرش گم نمی‌شود.
  • «سفارش جاافتاده»: محموله‌ای که ثبتش شکست بخورد (خطای غیرموقت) شمرده می‌شود؛ در داشبورد، منو و صفحه‌ی سفارش‌ها با دلیل و دکمه‌ی «تلاش مجدد». خطای موقت (5xx، شبکه) خودکار با backoff تکرار می‌شود؛ 429 کل صف را مکث می‌دهد.
  • محموله‌ای که از اول لغوشده دیده شود، سفارش نمی‌سازد و دوباره خوانده نمی‌شود.
  • تشخیص قیمت واحد یا سطر: معنای فیلد price اقلام در مستندات صریح نیست؛ با مقایسه با total_items_price خودکار تشخیص داده می‌شود.

وضعیت دوطرفه

  • باسلام → سایت: وضعیت سفارش‌های باز در هر دور با ids خوانده می‌شود. جدید/آماده‌سازی ← «در حال انجام»، ارسال‌شده/رضایت ← «تکمیل‌شده»، لغو ← «لغوشده»، مرجوعی ← «مسترد»، مشکل/درخواست لغو/تحویل‌نشده/کد رهگیری نادرست ← «در انتظار» + هشدار. فیلتر bsh_order_status برای وضعیت‌های سفارشی.
  • سایت → باسلام: «تأیید سفارش در باسلام» (set-preparation) و «ثبت ارسال در باسلام» با روش ارسال (۱۶ روش رسمی) و کد رهگیری (set-posted)، در کادر باسلام‌هاب سفارش (HPOS و قدیمی). «تکمیل‌شده» کردن سفارش هم ارسال را ثبت می‌کند؛ اگر روش ارسال انتخاب نشده باشد، یادداشت سفارش می‌گوید چه کنی. تأیید خودکار سفارش‌های جدید اختیاری است.
  • لغو از سمت غرفه‌دار در API باسلام وجود ندارد؛ لغو در سایت یادداشت و هشدار «در پنل باسلام درخواست لغو بده» می‌سازد.
  • ستون «باسلام» در فهرست سفارش‌های ووکامرس.

موجودی دوطرفه و موجودی اطمینان

  • مرجع «سایت» (پیش‌فرض): هر تغییر موجودی سایت (فروش سایت، ویرایش دستی، سفارش باسلامِ واردشده) به باسلام فرستاده می‌شود.
  • مرجع «باسلام»: موجودی در به‌روزرسانی‌ها فرستاده نمی‌شود؛ هر ساعت موجودی باسلام (محصول و هر تنوع) در سایت نوشته می‌شود؛ فروش سایت از عدد فعلی باسلام کم می‌شود (خواندن ← کم کردن ← نوشتن)، نه این‌که رویش بازنویسی شود. سفارش باسلام دوبار کم نمی‌شود.
  • موجودی اطمینان: N عدد از هر کالا در باسلام نشان داده نمی‌شود (سراسری در تنظیمات، قابل تغییر برای هر محصول و هر تنوع در تب «انبار»). هیچ‌وقت منفی نمی‌شود؛ روی محصولات بدون مدیریت موجودی اعمال نمی‌شود.

باید روی غرفه‌ی واقعی تأیید شود: شکل دقیق پاسخ vendor-parcels و معنای price اقلام، قالب cursor، اینکه آیا set-preparation برای همه‌ی سفارش‌های جدید لازم است، نام رویدادهای وب‌هوک، و دامنه‌ی دسترسی (scope) توکن برای سفارش‌ها.

فاز ۳ — چه چیزی تحویل شد (v0.4.0)

محصولات متغیر

  • هر تنوع فعال یک variant باسلام با قیمت (بعد از قوانین قیمت) و موجودی مستقل؛ نام ویژگی و مقدار به فارسی (برای ویژگی سراسری، نام term نه slug).
  • ضدتکرار تنوع: نگاشت «تنوع ووکامرس ← شناسه‌ی variant باسلام» در متای محصول. تغییر قیمت یا موجودی یک تنوع فقط همان variant را PATCH می‌کند؛ فهرست کامل فقط وقتی فرستاده می‌شود که تنوعی اضافه یا حذف شود یا ویژگی‌هایش عوض شود.
  • بعد از هر ارسال ساختاری، محصول از باسلام خوانده و تنوع‌ها با SKU و بعد با ویژگی‌ها دوباره جفت می‌شوند. رفتار دقیق باسلام هنگام PATCH فهرست تنوع (جایگزینی یا افزودن) مستند نیست؛ اگر تکراری ایجاد شود، هشدار فارسی ثبت و فقط جدیدترین تنوع هر ردیف به‌روز می‌شود.
  • تنوع «هرکدام»، تنوع بدون قیمت و دو تنوع یکسان قبل از ارسال با پیام فارسی متوقف می‌شوند. تنوع غیرفعال ارسال نمی‌شود. عکس تنوع‌ها به گالری اضافه می‌شود.
  • ویرایش یا حذف یک تنوع و تغییر موجودی آن از سفارش، محصول والد را در صف می‌گذارد.

اتصال محصولات موجود غرفه (صفحه‌ی «اتصال محصولات غرفه»)

  • همه‌ی محصولات غرفه صفحه‌به‌صفحه در پس‌زمینه دریافت و در جدول bsh_remote_products نگه داشته می‌شوند (پایه‌ی ایمپورت فاز ۵).
  • تطبیق: قطعی = SKU یکسان (SKU خود محصول، SKU تنوع‌ها، یا SKU ساختگی BSH-{id})؛ مشکوک = نام یکسان یا شبیه (۷۰٪+)، یا تعارض (دو محصول باسلام با یک SKU، محصول سایتی که قبلاً به محصول دیگری وصل است)؛ بدون جفت. اختلاف عدد در نام («۱ کیلویی» / «۲ کیلویی») امتیاز را پایین می‌آورد تا اشتباهی پیشنهاد نشود.
  • تا تأیید کاربر هیچ اتصالی ثبت نمی‌شود. «تأیید همه‌ی قطعی‌ها» یا انتخاب ردیفی؛ در مشکوک‌ها می‌شود بین گزینه‌ها انتخاب کرد. هنگام تأیید هر جفت دوباره اعتبارسنجی می‌شود.
  • اتصال به‌تنهایی چیزی در باسلام عوض نمی‌کند، مگر گزینه‌ی «بعد از اتصال، اطلاعات سایت فرستاده شود» تیک بخورد. اولین همگام‌سازی محصول متصل، همان محصول باسلام را به‌روز می‌کند (بدون ساخت محصول یا تنوع تازه).

ظاهر به سبک باسلام (v0.4.1)

رنگ‌ها و اندازه‌ها از پیکسل‌های اسکرین‌شات basalam.com خوانده شده‌اند: نارنجی #FF5C35 (زمینه‌ی دکمه‌ی اصلی و حالت فعال)، متن #252438، متن فرعی #565564، خط #E7E7E9، زمینه‌ی پرشده‌ی جستجو و فیلد #F3F3F4، سبز #128747، دکمه‌های ۴۰ تا ۴۴ پیکسلی با گوشه‌ی ۸. دو انحراف عمدی برای خوانایی (WCAG AA): متن نارنجی کوچک با #C93A15 و متن کم‌رنگ با #6B6A78. لوگو و دارایی‌های رسمی باسلام استفاده نشده؛ نام و نشان «باسلام‌هاب» است. سیستم طراحی هم با همین مقدارها به‌روز شده.

پنل SaaS (v0.3.0)

صفحه‌های باسلام‌هاب یک فضای کار تمام‌صفحه دارند، جدا از ظاهر پیشخوان وردپرس:

  • پوسته‌ی اپ: منوی کناری (فروشگاه / همگام‌سازی / سیستم) با شمارنده‌ی خطا و درصد ارسال گروهی، نوار بالا با مسیر صفحه، جستجوی محصول، وضعیت اتصال و آواتار حرفی (بدون Gravatar که در ایران کند یا فیلتر است). روی موبایل منو کشویی است.
  • پوسته‌ی روشن، تیره و خودکار از توکن‌های تیره‌ی همان سیستم طراحی؛ انتخاب کاربر در مرورگرش می‌ماند.
  • جابه‌جایی بدون رفرش: فقط محتوای صفحه عوض می‌شود؛ دکمه‌ی برگشت مرورگر و لینک مستقیم هم کار می‌کنند. هر خطایی در این مسیر به ناوبری معمولی برمی‌گردد، پس افزونه هیچ‌وقت به این اسکریپت وابسته نیست. صفحه‌ها همچنان با PHP رندر می‌شوند.
  • داشبورد: چهار کارت خلاصه، نمودار ستونی ۱۴ روزه‌ی «ارسال موفق / خطا» با منطقه‌ی زمانی سایت، راهنما، tooltip، جدول داده برای دسترس‌پذیری، و رنگ‌های آزموده‌شده برای کوررنگی در هر دو پوسته (فیروزه‌ای/نارنجی، نه سبز/قرمز)، به‌اضافه‌ی آخرین رویدادها و سلامت سیستم.
  • صفحه‌ی محصولات: همه‌ی محصولات با وضعیت باسلام، تب‌های همه / همگام / در صف / همگام نیست / خطا / ارسال‌نشده با شمارنده، جستجو با نام یا SKU، ارسال تکی و انتخاب چندتایی (به‌صورت یک ارسال گروهی).

یافته‌ها درباره‌ی API باسلام (پاسخ به سؤال‌های باز سند)

از روی OpenAPI رسمی باسلام (openapi.basalam.com، همان منبعی که SDKهای رسمی از آن ساخته شده‌اند):

سؤال پاسخ
محصولات متغیر پشتیبانی می‌شود؟ بله. فیلد variants در ساخت/ویرایش محصول و PATCH /v1/products/{id}/variations/{variation_id} وجود دارد. نامعلوم: PATCH با variants جایگزین می‌کند یا اضافه؛ افزونه هر دو حالت را تشخیص می‌دهد.
سفارش با Webhook یا Polling؟ هر دو ممکن است. سرویس Webhook (/v1/webhooks, /v1/customers/webhooks) هست؛ سفارش‌ها از /v1/vendor-parcels خوانده می‌شوند. پیشنهاد: Webhook برای سرعت + Polling/تطبیق شبانه برای اطمینان.
تغییر وضعیت سفارش POST /v1/vendor-parcels/{id}/set-preparation (تأیید) و set-posted (ارسال).
تصاویر POST /v1/files با file_type=product.photo؛ شناسه‌ی فایل در photo/photos محصول. محدودیت ابعاد و حجم در مستندات نیامده؛ باید روی غرفه‌ی تست سنجیده شود.
Rate limit در OpenAPI مشخص نشده. افزونه 429 و Retry-After را مدیریت می‌کند.

فرض‌هایی که باید روی غرفه‌ی تست تأیید شوند: قیمت به ریال، وزن به گرم، ابعاد به سانتی‌متر، و آدرس صفحه‌ی محصول basalam.com/{identifier}/product/{id}.

چرا SDK رسمی PHP را مستقیم استفاده نکردیم؟ آن SDK به Guzzle وابسته است؛ دو افزونه با نسخه‌های مختلف Guzzle روی یک سایت وردپرسی باعث خطای مرگبار می‌شوند. کلاینت باسلام‌هاب همان endpointها را با HTTP API خود وردپرس صدا می‌زند.

ساختار کد

basalamhub.php                    بوت‌استرپ
includes/
  class-bsh-plugin.php          سیم‌کشی هوک‌ها
  class-bsh-installer.php       جدول‌های bsh_links و bsh_logs
  class-bsh-settings.php        تنظیمات، توکن رمزنگاری‌شده، وضعیت اتصال
  class-bsh-crypto.php          رمزنگاری
  class-bsh-queue.php           صف، backoff، self-heal، آمار
  class-bsh-lock.php            قفل اتمیک بین پردازه‌ها
  class-bsh-links.php           جدول اتصال‌ها (پایه‌ی ضدتکرار)
  class-bsh-bulk.php            ارسال گروهی و پیشرفت
  class-bsh-categories.php      درخت دسته‌های باسلام، نگاشت، ویژگی‌ها
  class-bsh-price-rules.php     قوانین قیمت و گردکردن
  class-bsh-linker.php          دریافت محصولات غرفه، تطبیق، تأیید اتصال
  class-bsh-logger.php          مرکز لاگ
  class-bsh-inventory.php       مرجع موجودی، دریافت ساعتی، کم‌کردن از باسلام، موجودی اطمینان
  class-bsh-importer.php        ایمپورت کل غرفه به ووکامرس
  class-bsh-notifier.php        اعلان بله و تلگرام
  class-bsh-sales.php           فروش دوکاناله (صفحه‌ی فروش و گزارش هفتگی)
  class-bsh-stock-alerts.php    هشدار کمبود موجودی کالاهای باسلام
  class-bsh-report.php          گزارش هفتگی
  class-bsh-insights.php        «امروز چی شد»، امتیاز سلامت، اعلان زنده
  class-bsh-demo.php            حالت نمایشی (ساخت، شبیه‌سازی سفارش، پاک کردن)
  orders/                       سفارش‌های باسلام: دریافت، ضدتکرار، وضعیت دوطرفه، وب‌هوک، تطبیق شبانه
  api/                          کلاینت API و ترجمه‌ی خطا به فارسی
  sync/                         نگاشت محصول، تصاویر، موتور همگام‌سازی
  admin/                        پوسته‌ی اپ (class-bsh-app.php)، صفحه‌ها، کادر محصول و سفارش، ستون‌های لیست
assets/                         CSS از سیستم طراحی، JS بدون وابستگی، فونت وزیرمتن (محلی)
tests/                          سرور ساختگی باسلام و سناریوهای end-to-end

نقاط اتصال فازهای بعد (filter): bsh_basalam_price (قوانین قیمت)، bsh_basalam_category (نگاشت دسته)، bsh_basalam_stock (موجودی احتیاطی)، bsh_image_upload_path (تغییر ابعاد تصویر)، bsh_product_payload، و اکشن bsh_logged (اعلان تلگرام/بله).

نصب و تست

  1. فایل zip را از «افزونه‌ها › افزودن › بارگذاری» نصب و فعال کن (ووکامرس لازم است، PHP 7.4+).
  2. باسلام‌هاب › تنظیمات: توکن شخصی (با دسترسی محصولات و سفارش‌های غرفه) از پنل توسعه‌دهندگان باسلام → «ذخیره و تست اتصال».
  3. شناسه‌ی دسته‌ی پیش‌فرض باسلام را وارد کن.
  4. در یک محصول ساده «ارسال به باسلام» را بزن.

تست‌های خودکار

BSH_MOCK_STATE=/tmp/bsh.json php -S 127.0.0.1:8099 tests/mock-basalam/router.php &
# در wp-config.php:  define( 'BSH_API_BASE', 'http://127.0.0.1:8099' );
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/run.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/phase2.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/app.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/phase3.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/phase4.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/phase5.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/migrate.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/features.php
BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/e2e/presentation.php
# تست فشار (چند دقیقه):
BSH_STRESS_N=1000 BSH_MOCK_STATE=/tmp/bsh.json wp eval-file tests/stress/stress.php

run.php (فاز ۱، ۶۶ سناریو)، phase2.php (فاز ۲، ۴۹ سناریو)، app.php (پنل، ۲۶ سناریو)، phase3.php (فاز ۳، ۵۵ سناریو)، phase4.php (فاز ۴، ۷۹ سناریو)، phase5.php (فاز ۵، ۸۲ سناریو)، migrate.php (انتقال از نسخه‌ی قدیمی، ۲۰ سناریو) ، features.php (فروش، هشدار موجودی، گزارش هفتگی، ۳۷ سناریو) و presentation.php (امتیاز سلامت، امروز، اعلان زنده، حالت نمایشی، ۶۳ سناریو) — در مجموع ۴۷۷ روی وردپرس ۶.۸ + ووکامرس ۱۰.۲ واقعی: اتصال، رمزنگاری، payload، ضدتکرار، بازیابی پاسخ گم‌شده، 404/422/429، قفل، self-heal، نگاشت و ویژگی‌ها، قوانین قیمت، پردازش تصویر و ارسال گروهی، ثبت سفارش بدون تکرار، وضعیت دوطرفه، موجودی دوطرفه، ایمپورت غرفه، تطبیق شبانه و اعلان‌ها. سرور ساختگی، Bot API بله/تلگرام و فایل عکس را هم شبیه‌سازی می‌کند.

ساخت zip

bin/build-zip.sh   # → dist/basalamhub-<version>.zip