در یکی از پروژه‌های فروشگاهی که برای یک برند پوشاک پیاده کرده بودم، صبح یک‌شنبه سه سفارش ناموفق روی میز پشتیبانی بود: پول از حساب مشتری کم شده، اما هیچ ردیفی در لیست سفارش‌های ووکامرس نبود. تیم پشتیبانی فکر می‌کرد مشکل از درگاه بانک است؛ بانک می‌گفت تراکنش با موفقیت تأیید شده. در واقع مسئله در یک نقطه نامرئی بود: هوکی که بعد از payment_complete اجرا می‌شد و به‌دلیل یک باگ ظریف، اجرای خود را قبل از ذخیره وضعیت سفارش متوقف می‌کرد. آن روز یاد گرفتم «عدم ثبت سفارش» تقریباً هرگز یک مسئله تک‌لایه نیست. این مقاله، تجربه همین مسیر عیب‌یابی است.

چرخه حیات سفارش در ووکامرس از کلیک تا انتشار

برای اینکه بتوانید «چرا سفارش ثبت نمی‌شود» را دقیق پاسخ دهید، باید بدانید ووکامرس در لایه زیرین چه می‌کند. وقتی مشتری روی دکمه پرداخت می‌زند، حتی قبل از اینکه به درگاه برود، ووکامرس یک «پیش‌نویس سفارش» می‌سازد. این پیش‌نویس در جدول سفارش‌ها با وضعیت checkout-draft ذخیره می‌شود و صرفاً یک نگه‌داری موقت است تا اگر کاربر به هر دلیل اتصال را قطع کرد، سرنخ سفارش گم نشود. بعد از پرداخت موفق، این پیش‌نویس به وضعیت pending یا processing ارتقا می‌یابد و تراکنش تأیید می‌شود.

در سمت کد، ترتیب اجرای توابع به این شکل است: WC_Checkout::process_checkout() → WC_Checkout::create_order() → wc_create_order() → $order->payment_complete() → هوک woocommerce_payment_complete. اگر در هر یک از این مراحل، یک افزونه یا قالب با یک exception، با یک return نابه‌جا یا با یک exit جریان را بشکند، سفارش هرگز به مرحله بعد نمی‌رسد. مشتری هم پیام موفقیت نمی‌گیرد. توضیح گسترده‌تر این چرخه در مدیریت سفارش‌ها در ووکامرس آمده و برای درک معماری کلی، ووکامرس چیست پیش‌نیاز مفیدی است.

سفارش در ووکامرس، یک ردیف ساده در دیتابیس نیست؛ یک ماشین حالت (State Machine) است که هر انتقال در آن باید با اعتبارسنجی و هوک انجام شود. شکست در هر انتقال، سفارش را در هوا معلق می‌کند.

وضعیت‌های سفارش و آنچه هرکدام می‌گویند

وضعیتمعنانشانه خطا
checkout-draftپیش‌نویس موقت قبل از پرداختزیاد ماندن این وضعیت یعنی کاربر رها کرده، یا create_order شکست خورده
pendingسفارش ثبت شده، منتظر تأیید پرداختماندگاری طولانی یعنی verify درگاه موفق نشده
failedپرداخت ناموفقاگر پول کم شده اما failed است، خطای verify یا callback
processingپرداخت تأیید، آماده ارسالوضعیت سالم پرداخت‌های موفق
on-holdدر انتظار بررسی دستیدر بعضی درگاه‌های اقساطی معمول است

ساختار داده سفارش: از postmeta تا HPOS

یکی از بزرگ‌ترین تغییرات ووکامرس در سال‌های اخیر، معرفی HPOS (High-Performance Order Storage) است. در معماری قدیمی، هر سفارش یک ردیف در wp_posts با post_type = shop_order بود و جزئیاتش در wp_postmeta ذخیره می‌شد. این ساختار در فروشگاه‌های بزرگ، به گلوگاه مقیاس‌پذیری تبدیل شد. HPOS این ساختار را به جداول اختصاصی wc_orders، wc_order_addresses، wc_order_operational_data و wc_orders_meta منتقل کرد.

چرا این نکته برای عیب‌یابی حیاتی است؟ چون افزونه‌های قدیمی که مستقیم روی wp_postmeta کوئری می‌زنند، بعد از فعال شدن HPOS، نمی‌توانند سفارش‌ها را بخوانند. نتیجه ظاهری: «سفارش ثبت نمی‌شود» در حالی که سفارش هست، اما افزونه آن را نمی‌بیند. اگر سایت شما HPOS را فعال کرده و افزونه‌ای دارید که در پشتیبانی خود صریحاً از سازگاری HPOS حرف نزده، احتمال خطا بالاست. مقایسه ساختار و رفتار سفارش‌ها بین دو معماری در مدیریت سفارش‌ها در ووکامرس شرح داده شده.

دو نشانه دقیق که HPOS مقصر است:

  • سفارش‌ها در پیشخوان ووکامرس دیده می‌شوند اما در گزارش‌های افزونه سوم‌شخص غایب‌اند.
  • افزونه‌ای که در حالت legacy کار می‌کرد، بلافاصله بعد از مهاجرت به HPOS شکست خورده.

راه‌حل: یا افزونه را به نسخه سازگار ارتقا دهید، یا HPOS را موقتاً غیرفعال کنید و مسیر قدیمی را برگردانید تا افزونه به‌روز شود.

شکست بازگشت از درگاه و Verify

تجربه من می‌گوید بیش از نیمی از پرونده‌های «سفارش ثبت نمی‌شود» در بازار ایران، در لایه بازگشت از درگاه رخ می‌دهد. اکثر درگاه‌های ایرانی دو مرحله‌ای هستند: ابتدا request برای گرفتن توکن و انتقال به درگاه، سپس verify برای تأیید نهایی تراکنش. اگر مرحله verify به هر دلیل شکست بخورد — timeout، خطای امضا، IP مسدود، پاسخ نامعتبر — ووکامرس سفارش را در حالت pending یا failed نگه می‌دارد، حتی اگر پول از حساب مشتری کم شده باشد.

سه دلیل شایع شکست verify:

  1. قطع اتصال به API درگاه: هاست اشتراکی با فایروال تهاجمی، درخواست خروجی به API درگاه را بلاک می‌کند. برای بررسی، از ابزار curl از داخل سرور خودتان استفاده کنید. اگر خود سرور به دامنه درگاه دسترسی نداشت، ریشه همین است.
  2. پاسخ نامعتبر درگاه: بعضی افزونه‌های ایرانی قدیمی، انتظار پاسخ JSON دارند اما درگاه XML یا متن ساده برمی‌گرداند. اگر افزونه به‌روز نشده باشد، verify بی‌صدا fail می‌شود. توضیح این سناریو در خطای درگاه پرداخت ووکامرس آمده.
  3. عدم تطابق callback URL: اگر URL بازگشت در پنل درگاه با آنچه در افزونه تنظیم شده مطابقت نداشته باشد، درگاه به مسیر اشتباهی هدایت می‌کند و اطلاعات سفارش گم می‌شود.

روش تشخیص قطعی: در پیشخوان ووکامرس، بخش «وضعیت سیستم» و لاگ درگاه. اگر ردیفی وجود دارد که در آن verify اجرا شده اما پاسخ خطا داشته، ریشه تأییدشده است. برای درک درست مراحل اتصال، مقاله اتصال ووکامرس به درگاه‌های پرداخت مسیر درست را مرحله‌به‌مرحله پوشش می‌دهد و مراحل ابتدایی‌تر در اتصال درگاه پرداخت به ووکامرس آمده است.

نانس، نشست و کوکی؛ سه گلوگاه نامرئی

ووکامرس برای حفظ امنیت فرم‌های پرداخت، از سه مکانیزم کلیدی استفاده می‌کند: nonce، session cookie و WooCommerce session handler. اگر هر یک از این‌ها شکست بخورد، کاربر در ظاهر «همه‌چیز را درست انجام می‌دهد» اما سرور درخواست را رد می‌کند و سفارش هرگز ساخته نمی‌شود.

سه علت شایع:

  • غیرفعال بودن کوکی مرورگر: اگر مشتری کوکی‌ها را در مرورگر بلاک کرده باشد، ووکامرس نمی‌تواند session سبد خرید را حفظ کند. نیازی به گفتن نیست که این سناریو بیشتر در کاربران حرفه‌ای و مرورگرهای سخت‌گیر رخ می‌دهد.
  • تضاد با افزونه‌های کش CDN: بعضی CDNها، هدر Set-Cookie را حذف می‌کنند. نتیجه: مرورگر هیچ‌وقت کوکی ووکامرس را ذخیره نمی‌کند و در مرحله ثبت سفارش، سبد خرید خالی به نظر می‌رسد.
  • مسدودسازی REST API توسط افزونه امنیتی: اگر افزونه‌ای مسیر /wp-json/ را ببندد، بعضی فرآیندهای ثبت سفارش از کار می‌افتند.

روش تشخیص قطعی: با یک مرورگر ناشناس و بدون افزونه، فرآیند خرید را تکرار کنید. اگر مشکل رفع شد، ریشه در لایه کاربر است. این سناریو در رفع خطاهای رایج ووکامرس با جزئیات بیشتر بحث شده است. تشخیص دقیق لایه کاربر با بررسی کوکی‌ها در تب Application مرورگر انجام می‌شود.

اگر نانس منقضی شده باشد، سرور بی‌صدا درخواست را رد می‌کند. تنها چیزی که در Console می‌بینید یک ۴۰۳ بی‌توضیح است — ولی ریشه، ساعت داخلی سرور یا اختلاف زمانی است.

موجودی، قیمت و اعتبارسنجی سبد

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

سه الگوی تکرارشونده در این لایه:

  • محصولات virtual و download: بعضی افزونه‌های مدیریت موجودی، روی محصولات مجازی هم چک موجودی اعمال می‌کنند که اشتباه است و باعث لغو سفارش می‌شود.
  • محصولات متغیر: اگر واریانت انتخاب‌شده در لحظه پرداخت موجودی صفر داشته باشد، سفارش لغو می‌شود. مدیریت درست این ساختار در ساخت محصول متغیر در ووکامرس توضیح داده شده.
  • ناهمزمانی بین سبد و دیتابیس: اگر ووکامرس از کش آبجکت استفاده می‌کند و کش قدیمی است، ممکن است سفارش با قیمت اشتباه ثبت شود و در ادامه verify به مشکل بخورد.

روش تشخیص: لاگ ووکامرس معمولاً پیام دقیق «out of stock» یا «invalid product» را ثبت می‌کند. در غیر این صورت، در تب Network لحظه‌ای که ووکامرس wc-ajax=checkout را صدا می‌زند، پاسخ JSON را بخوانید. اگر result روی failure بود و messages خالی بود، احتمالاً یک افزونه پیام را مخفی کرده.

ایمیل و اطلاع‌رسانی سفارش

سناریوی فریبنده: سفارش در واقع ثبت شده، اما مشتری و ادمین هیچ ایمیلی دریافت نمی‌کنند و فکر می‌کنند سفارش ثبت نشده است. این سناریو در بیش از یک پرونده واقعی، منجر به تماس‌های اضطراری مشتری شده. اگر ارسال ایمیل با تأخیر یا با شکست انجام شود، ماجرا بدتر می‌شود چون همه فرض می‌کنند سفارش ثبت نشده در حالی که هست.

سه ریشه شایع:

  • عدم پیکربندی SMTP: تابع wp_mail() به‌تنهایی روی اکثر هاست‌ها غیرقابل‌اتکا است. تنظیم SMTP یا استفاده از سرویس تراکنشی الزامی است. راهنمای رفع خطا در خطای ارسال ایمیل در وردپرس آمده.
  • اسپم شدن ایمیل‌ها: اگر SPF و DKIM دامنه تنظیم نشده باشد، ایمیل‌های ووکامرس مستقیم به پوشه اسپم می‌روند. مسئله در سطح دامنه و DNS است نه در ووکامرس.
  • تضاد افزونه: بعضی افزونه‌های SMTP، قالب‌های ایمیل ووکامرس را ناسازگار می‌کنند. اگر بعد از تغییر افزونه SMTP، ایمیل‌ها متوقف شدند، ریشه همین است.

سناریوی دقیق‌تر این لایه و روش رفع در رفع خطای ایمیل سفارش ووکامرس شرح داده شده است.

هوک‌های حیاتی و ترتیب اجرا

در ووکامرس، هر مرحله ثبت سفارش با هوک‌ها علامت‌گذاری شده. اگر یک افزونه یا قالب، در یکی از این هوک‌ها کد سنگین یا کد خطادار داشته باشد، جریان ثبت سفارش متوقف می‌شود. مهم‌ترین هوک‌های این مسیر عبارتند از:

  1. woocommerce_checkout_create_order — در لحظه ساخت سفارش.
  2. woocommerce_checkout_update_order_meta — بعد از ذخیره متادیتای سفارش.
  3. woocommerce_checkout_order_processed — بعد از پردازش کامل سفارش.
  4. woocommerce_payment_complete — بعد از تأیید پرداخت موفق.
  5. woocommerce_order_status_changed — در هر تغییر وضعیت سفارش.

اگر افزونه‌ای در woocommerce_checkout_order_processed تابعی داشته باشد که به یک API خارجی وصل می‌شود و آن API پاسخ نمی‌دهد، با timeout می‌تواند ثبت سفارش را عقب بیندازد. اگر این timeout از max_execution_time سرور بیشتر شود، درخواست fail می‌شود و کاربر پیام موفقیت نمی‌گیرد. باید این افزونه‌ها را روی محیط استجینگ با تاخیر شبکه تست کنید.

برای درک معماری درست این لایه، هوک‌های ووکامرس نقطه شروع مفیدی است. اگر با مفهوم hook و filter آشنایی ندارید، هوک‌های وردپرس پیش‌نیاز مناسب است.

دیتابیس، جداول و خطاهای تراکنش

در لایه دیتابیس، سفارش ووکامرس با یک تراکنش SQL ثبت می‌شود. اگر این تراکنش به هر دلیل rollback شود، سفارش هرگز در دیتابیس نمی‌ماند. سه علت کلاسیک:

  • قفل جدول: اگر گزارش‌گیری سنگین همزمان روی همان جدول اجرا شود، ممکن است تراکنش ثبت سفارش به قفل برخورد کند. این حالت در جداول HPOS (مثل wc_orders) شایع‌تر است چون نوشتن‌ها متمرکزند.
  • جدول corrupt: اگر جدول سفارش‌ها به هر دلیل crash کرده باشد، درج ردیف جدید شکست می‌خورد. نشانه: سایر بخش‌های سایت سالم، فقط ثبت سفارش fail می‌شود.
  • پرشدن فضای دیسک: اگر سرور به محدودیت فضای دیسک رسیده باشد، MySQL نمی‌تواند ردیف جدید ثبت کند. این سناریو کم‌تر دیده می‌شود اما وقتی رخ می‌دهد، اغلب تشخیص داده نمی‌شود.

روش تشخیص: از طریق phpMyAdmin در cPanel وارد شوید، جدول سفارش‌ها را بررسی کنید و در صورت امکان REPAIR TABLE اجرا کنید. رفع دقیق خطاهای دیتابیس در رفع خطای اتصال به دیتابیس شرح داده شده است.

عیب‌یابی گام‌به‌گام و لاگ‌گیری

حالا ترتیب عملی عیب‌یابی، از کم‌ریسک‌ترین به پرریسک‌ترین:

  1. بازتولید دقیق روی استجینگ: قبل از هر چیز، باید خطا را در محیطی جدا از سایت زنده بازتولید کنید.
  2. فعال‌سازی لاگ ووکامرس: در پیشخوان ووکامرس، بخش WooCommerce → Status → Logs. هر سفارش ناموفق، معمولاً ردیفی در این لاگ دارد.
  3. فعال‌سازی WP_DEBUG_LOG: در محیط استجینگ، wp-config.php را طوری تنظیم کنید که خطاها در wp-content/debug.log ذخیره شوند.
  4. بررسی تب Network مرورگر: پاسخ دقیق wc-ajax=checkout را بخوانید. اگر پیام خطا داشت، همان پیام، کلید حل مسئله است.
  5. غیرفعال‌سازی افزونه‌ها به روش نصف‌سازی: روی استجینگ، نیمی از افزونه‌ها را خاموش کنید و تست بگیرید. این روش سریع‌ترین راه شناسایی مقصر است. پروتکل کامل در رفع تضاد افزونه‌ها آمده.
  6. تغییر موقت قالب: اگر با افزونه‌های غیرفعال هم مشکل باقی ماند، قالب مقصر است.
  7. بررسی درگاه بانک: اگر تا اینجا خطایی ندیدید، ریشه در درگاه و callback است.

مراحل دقیق پیدا کردن خطا در لاگ‌ها را در پیدا کردن خطاهای ووکامرس در لاگ‌ها و روش کلی عیب‌یابی را در عیب‌یابی خطاهای ووکامرس آورده‌ام. برای خطاهای پرتکرار در ووکامرس، رفع خطاهای رایج ووکامرس نقطه شروع سریعی است.

در فرآیند ثبت سفارش، هر ثانیه تأخیر در لایه‌ای که سرور روی آن تسلط ندارد، یک احتمال از دست دادن مشتری است. لاگ دقیق، تنها راه بازگرداندن زمان از دست رفته است.

اشتباهات پرهزینه در تشخیص

در پرونده‌های پشتیبانی، پنج اشتباه بیشتر از همه تکرار می‌شود:

  • متهم کردن درگاه بدون بررسی سایت: در ۷۰٪ پرونده‌ها، درگاه سالم بوده اما سایت، پاسخ callback را درست مدیریت نکرده.
  • پاک کردن سفارش‌های pending: بعضی ادمین‌ها برای «تمیزکاری» سفارش‌های pending را حذف می‌کنند، اما این کار اطلاعات تراکنش بانکی را از دست می‌دهد و حل اختلاف با بانک را سخت می‌کند.
  • ویرایش مستقیم دیتابیس: گاهی برای «تعمیر» یک سفارش، مستقیم در جدول‌ها دست می‌برند. این کار می‌تواند زنجیره‌ای از داده‌های ناهمگون بسازد که بعداً غیرقابل‌ترمیم می‌شود.
  • نادیده گرفتن HPOS: افزونه‌های قدیمی ممکن است هنوز به جداول legacy وابسته باشند. فعال بودن HPOS بدون بررسی سازگاری، ریسک جدی است.
  • بازنویسی قالب ایمیل درون هسته: بعضی برای تغییر ظاهر ایمیل، مستقیم در فایل‌های ووکامرس دست می‌برند. راه درست، override در قالب است نه ویرایش پلاگین.

پرسش‌های پرتکرار درباره عدم ثبت سفارش

چرا پول از حساب مشتری کم شده اما سفارش ثبت نشده؟ این سناریو تقریباً همیشه به شکست مرحله verify درگاه اشاره دارد. ابتدا لاگ درگاه را بررسی کنید، سپس در پنل بانک تراکنش را ببینید و در صورت لزوم دستی سفارش بسازید و مبلغ را برگردانید.

سفارش‌ها در حالت pending گیر کرده‌اند، چه کنم؟ ریشه معمولاً در بازگشت از درگاه است. اگر مشتری به سایت بازگشته اما وضعیت pending مانده، احتمالاً callback URL اشتباه است یا verify انجام نمی‌شود. ترتیب رخدادها را در لاگ درگاه بررسی کنید.

آیا HPOS می‌تواند باعث عدم ثبت سفارش شود؟ بله. اگر افزونه‌ای با HPOS سازگار نباشد، می‌تواند سفارش‌ها را نبیند یا نتواند متادیتا اضافه کند. ابتدا سازگاری همه افزونه‌های مرتبط را تأیید کنید.

چرا مشتری پیام موفقیت نمی‌گیرد ولی سفارش ثبت شده؟ ریشه در قالب یا افزونه ترجمه است که پیام‌های ووکامرس را بازنویسی می‌کنند. مقایسه پیام‌های پیش‌فرض ووکامرس با پیام‌های فعلی سایت، سریع‌ترین راه تشخیص است.

آیا افزودن افزونه جدید می‌تواند ثبت سفارش را بشکند؟ بله، هر افزونه‌ای که با هوک‌های ثبت سفارش کار کند، می‌تواند جریان را تغییر دهد. اگر خطا بعد از نصب یک افزونه ظاهر شد، همان افزونه مقصر اول است.

چرا سفارش‌های تکراری ثبت می‌شوند؟ این سناریو معکوس مسئله است اما ریشه مشترکی دارد: تکرار درخواست callback از سمت درگاه، بدون idempotency check. درگاه‌هایی که retry می‌کنند، اگر افزونه شما برای هر بار یک سفارش جدید بسازد، نتیجه سفارش تکراری است.

درس‌های میدانی و مسیر پیشگیری

اگر بخواهم چکیده این مسیر را در چند جمله بگویم: «عدم ثبت سفارش» معمولاً یک مسئله لایه‌ای است، نه تک‌علتی. در تجربه من، سه کار پیشگیرانه بیشترین اثر را دارند:

  1. پایش سفارش‌های pending و failed: یک گزارش هفتگی بسازید. اگر روند صعودی دیدید، پیش از بحران ریشه را پیدا کنید. الگوی رخداد، بهترین سرنخ است.
  2. محیط استجینگ با داده واقعی: روی استجینگ، فرآیند پرداخت را با درگاه تست انجام دهید. محیط استجینگ با داده واقعی، تفاوت‌های پنهان را آشکار می‌کند. راه‌اندازی بکاپ و استجینگ را در بکاپ گرفتن از فروشگاه ووکامرس توضیح داده‌ام.
  3. پایش عملکرد درگاه و هاست: اگر TTFB و پاسخ درگاه در ساعات اوج کند می‌شود، پیش از فاجعه، منابع را ارتقا دهید. توضیح این لایه در افزایش سرعت فروشگاه ووکامرس آمده و مبانی سنجش در افزایش سرعت وردپرس.

اگر شما هم در پروژه‌ای با «عدم ثبت سفارش» دست‌وپنجه نرم کرده‌اید، دوست دارم بدانم ریشه در کدام لایه بود: درگاه، هوک‌ها، HPOS، یا لایه دیتابیس؟ تجربه‌تان را در دیدگاه‌ها بنویسید؛ مخصوصاً اگر نشانه‌ای کشف کرده‌اید که در این فهرست نبوده. ثبت دقیق این پرونده‌ها، ارزشمندترین سرمایه‌ای است که یک فروشگاه می‌تواند در بلندمدت بسازد. 🧾