چطور با وبهوک (Webhook) ووکامرس، فروشگاهت رو به سیستمهای خارجی متصل کنی؟
- امین زاهد
- مطالعه در 57 دقیقه
- آبان 3, 1404
- بدون دیدگاه
-
افزودنی دیجیتس ورود و ثبت نام سریع با یک کلیک Digits One Click Login/Signup ۴۷۰,۰۰۰ تومان
-
افزونه وردپرس یوست سئو پرمیوم Yoast SEO Premium ۴۷۰,۰۰۰ تومان
-
پکیج پلاتینیوم وردپرس برای آژانسهای دیجیتال مارکتینگ| 12 محصول + 53٪ تخفیف
۴,۶۸۰,۰۰۰ تومانقیمت اصلی: ۴,۶۸۰,۰۰۰ تومان بود.۲,۴۷۹,۰۰۰ تومانقیمت فعلی: ۲,۴۷۹,۰۰۰ تومان. -
افزونه بهینه سازی صفحات و افزایش سرعت در وردپرس | Asset CleanUp Page Speed Booster
نمره 5.00 از 5۴۷۰,۰۰۰ تومان
آیا تا به حال احساس کردهاید که فروشگاه اینترنتی شما مثل یک جزیره تنها کار میکند؟ 🏝️ سفارشی ثبت میشود، اما شما باید «دستی» آن را در سیستم حسابداری وارد کنید. مشتری جدیدی میآید، اما اطلاعاتش خودکار به CRM منتقل نمیشود. موجودی انبار در نرمافزارتان کم میشود، اما سایت شما همچنان آن کالا را «موجود» نشان میدهد و میفروشد! اینها همگی نشانههای یک کسبوکار غیرمتصل و ناکارآمد هستند.
اما راهحل چیست؟ چطور میتوانید بدون نیاز به رفرش کردن مداوم صفحات یا استخدام نیروی انسانی برای ورود داده، تمام بخشهای کسبوکارتان را به هم بدوزید؟
پاسخ کوتاه و قدرتمند: وبهوک (Webhook).
وبهوکها، پیامرسانهای خودکار و هوشمند فروشگاه شما هستند. آنها به محض وقوع یک اتفاق (مثل «سفارش جدید»)، بلافاصله سیستمهای دیگر (مثل انبار، CRM یا پنل پیامک) را «خبر» میکنند. در این مقاله از دسته آموزش ووکامرس از وردپرس نیاز، بهعنوان یک متخصص هک رشد و مدیر فروش آنلاین، قرار است به شما بهصورت پروژهمحور و عملی، آموزش Webhook وردپرس را از صفر تا صد، با مثالهای واقعی که خودم در پروژههای مختلف اجرا کردهام، نشان دهم. آمادهاید فروشگاهتان را اتوماتیک کنید؟ 🚀
Webhook در ووکامرس دقیقاً چیست و چرا بدون آن فروشگاهت ناقص است؟
اگر بخواهم خیلی ساده بگویم، Webhook یک «زنگ اخبار» دیجیتال است. 🔔 تصور کنید فروشگاه شما یک خانه است. هر اتفاقی که در آن میافتد (سفارش جدید، ثبتنام مشتری، آپدیت محصول)، مثل این است که کسی زنگ در را میزند. Webhook همان سیستمی است که به محض زده شدن زنگ، به شما (یا هر سیستم دیگری که مشخص کردهاید) اطلاع میدهد.
در دنیای فنی، Webhook یک مکانیزم اطلاعرسانی خودکار (Push) مبتنی بر رویداد (Event-driven) است. بهجای اینکه شما هر دقیقه از سیستم انبار بپرسید: “سفارش جدید اومد؟” (کاری که API معمولی انجام میدهد)، خودِ ووکامرس به محض ثبت سفارش، یک پیام (شامل تمام جزئیات سفارش) به آدرس اینترنتی (URL) که شما تعیین کردهاید، ارسال (POST) میکند.
فروشگاه بدون Webhook: مثل یک مغازه شلوغ است که صاحبش باید خودش حواسش به ورود مشتری، صندوق و انبار باشد. احتمال خطا بالاست و زمان زیادی تلف میشود.فروشگاه با Webhook: مثل یک کارخانه تمام اتوماتیک است. هر بخش به محض انجام وظیفهاش، بخش بعدی را مطلع میکند. همهچیز سریع، دقیق و بدون دخالت دست انجام میشود.
حالا که فهمیدیم Webhook یک سیستم اطلاعرسانی «Push» است، احتمالاً این سوال پیش میآید که پس فرقش با API که همیشه از آن حرف میزنیم چیست؟
تفاوت Webhook با API معمولی چیست و کدام برای فروشگاه بهتره؟
این یکی از رایجترین سوالاتی است که از من پرسیده میشود. بگذارید با یک مثال تفاوت این دو را برای همیشه روشن کنم:
- API (Application Programming Interface): مثل تلفن زدن است 📞. شما باید «خودتان» شماره بگیرید (درخواست بفرستید) تا اطلاعات بگیرید. مثلاً، سیستم انبار شما باید هر ۵ دقیقه یکبار به ووکامرس زنگ بزند و بپرسد: “سفارش جدید چی داری؟” به این کار “Pull” یا کشیدن داده میگویند. این کار منابع سرور را مصرف میکند و اطلاعات را «با تاخیر» به دست شما میرساند.
- Webhook: مثل دریافت پیامک (SMS) است 📲. شما کاری نمیکنید. به محض اینکه اتفاقی بیفتد (مثلاً سفارش جدید)، ووکامرس «خودش» بلافاصله یک پیامک (داده) برای شما ارسال میکند. به این کار “Push” یا هل دادن داده میگویند. این مکانیزم بلادرنگ (Real-time) و بسیار بهینهتر است.
جدول مقایسه Webhook و API:
| ویژگی | Webhook (Push) | API (Pull) |
| مکانیزم | مبتنی بر رویداد (Event-driven) | مبتنی بر درخواست (Request-driven) |
| سرعت | بلادرنگ (Real-time) | با تاخیر (وابسته به بازه زمانی درخواست) |
| مصرف منابع | بسیار کم (فقط زمان وقوع رویداد) | بالا (درخواستهای مداوم) |
| جهت داده | یکطرفه (از ووکامرس به خارج) | معمولاً دوطرفه (خواندن و نوشتن) |
| مثال | “ووکامرس به انبار: سفارش جدید ثبت شد!” | “انبار از ووکامرس: لیست سفارشات جدید رو بده.” |
نتیجهگیری: برای اطلاعرسانیهای «بلادرنگ» (مثل ثبت سفارش، کاهش موجودی، ارسال پیامک) Webhook بهترین گزینه است. برای کارهایی که نیاز به «درخواست» دارند (مثل آپدیت کردن دستی یک محصول از طریق نرمافزار خارجی) از REST API استفاده میکنیم.
حالا که میدانیم Webhook چقدر کارآمد است، بیایید ببینیم دقیقاً در چه سناریوهایی به کارمان میآید.
چه زمانی باید از Webhook استفاده کنی؟ (۵ سناریوی واقعی)
در پروژههایی که مدیریت کردهام، Webhookها ستون فقرات اتوماسیون بودهاند. اینجا ۵ سناریوی واقعی و ملموس در کسبوکارهای ایرانی را میبینید که با Webhook ووکامرس پیادهسازی شدهاند:
- اتصال به سیستم انبارداری 📦 در ووکامرس:
- سناریو: به محض ثبت «سفارش جدید» (
order.created)، یک Webhook اطلاعات سفارش (لیست محصولات و تعداد) را به نرمافزار انبارداری (مثل هلو، سپیدار یا یک سرویس ابری) ارسال میکند تا کالا از موجودی کسر شده و فاکتور صادر شود. پیشنهاد میکنیم مقاله “مدیریت انبارداری و محصولات ووکامرس” را نیز مطالعه کنید.
- سناریو: به محض ثبت «سفارش جدید» (
- ارسال پیامک خودکار به مشتری 🤳:
- سناریو: به محض تغییر وضعیت سفارش به «تکمیل شد» (
order.status.updatedبهcompleted)، یک Webhook شماره موبایل مشتری و کد رهگیری پستی را به پنل پیامک (مثل کاوه نگار یا ملی پیامک) میفرستد و پیامک اطلاعرسانی ارسال میشود.
- سناریو: به محض تغییر وضعیت سفارش به «تکمیل شد» (
- ثبت خودکار مشتری در CRM 👩💼:
- سناریو: به محض «ایجاد مشتری جدید» (
customer.created) یا حتی ثبت اولین سفارش (که مشتری ساخته میشود)، Webhook اطلاعات مشتری (نام، ایمیل، تلفن) را به CRM (مثل HubSpot, Salesforce یا دیدار) ارسال میکند تا تیم فروش پیگیریهای لازم را شروع کند.
- سناریو: به محض «ایجاد مشتری جدید» (
- همگامسازی با حسابداری ابری 🧾:
- سناریو: در پایان هر روز، یا به محض «تکمیل شدن سفارش»، Webhook اطلاعات مالی سفارش (مبلغ کل، مالیات، کد تخفیف) را به سیستم حسابداری (مثل QuickBooks یا سرویسهای ایرانی) میفرستد تا اسناد مالی خودکار ثبت شوند.
- گزارشگیری لحظهای در Google Sheets 📊:
- سناریو: (این پروژه را در ادامه کامل اجرا میکنیم) به محض ثبت هر سفارش، اطلاعات کلیدی آن (شماره سفارش، مبلغ، نام مشتری) در یک ردیف از فایل گوگل شیت شما ثبت میشود تا یک داشبورد فروش زنده داشته باشید.
اینها تنها چند مثال ساده بودند. قدرت واقعی زمانی مشخص میشود که شما این ابزار را در دست بگیرید. پس بیایید دست به کار شویم و اولین Webhook خودمان را بسازیم.
چطور Webhook رو در ووکامرس فعال و پیکربندی کنم؟ (راهنمای گامبهگام)
راهاندازی Webhook در ووکامرس بهطرز شگفتانگیزی ساده است. ووکامرس این قابلیت را بهصورت هستهای در خود دارد و نیازی به افزونه جانبی نیست. (البته برای اتوماسیونهای پیچیدهتر، افزونههایی مثل AutomateWoo که در وردپرس نیاز بهصورت اورجینال و با گارانتی بازگشت وجه موجود است، میتوانند مکمل خوبی باشند).
بیایید قدم به قدم اولین Webhook خود را بسازیم:
- ورود به بخش وبهوکها:از منوی مدیریت وردپرس به ووکامرس > پیکربندی بروید.
- تب پیشرفته:روی تب پیشرفته کلیک کنید.
- انتخاب وبهوکها:از زیرمنوهای تب پیشرفته، گزینه وبهوکها را انتخاب کنید. (اگر این گزینه را نمیبینید، مطمئن شوید ووکامرس شما بهروز است).
- افزودن وبهوک جدید:روی دکمه افزودن وبهوک کلیک کنید.
حالا شما در صفحه ساخت Webhook جدید هستید. اینجا چند فیلد مهم وجود دارد که باید پر کنید:
- نام (Name): یک نام دلخواه و با معنی انتخاب کنید (مثلاً: “ارسال سفارش به انبار”).
- وضعیت (Status): آن را روی
فعال(Active) تنظیم کنید تا کار کند. - موضوع (Topic): این مهمترین بخش است! اینجا «رویداد» (Event) را مشخص میکنید. مثلاً
سفارش ایجاد شد(Order Created). - نشانی اینترنتی تحویل (Delivery URL): این همان آدرس (Endpoint) است که میخواهید دادهها به آنجا ارسال شوند. (در بخشهای بعدی مفصل توضیح میدهیم چطور آن را بسازیم).
- کلید مخفی (Secret): یک رمز عبور قوی و منحصربهفرد. این کلید برای امنیت و تأیید اینکه دادهها واقعاً از طرف سایت شما آمدهاند، استفاده میشود. (در بخش امنیت کامل بررسی میکنیم).
به همین سادگی! اما قبل از اینکه دکمه «ذخیره» را بزنید، باید مطمئن شویم که زیرساختهای فنی لازم را داریم.
پیشنیازهای فنی راهاندازی Webhook چیست؟ (چکلیست کامل)
برای اینکه آموزش Webhook وردپرس شما به درستی کار کند و دچار مشکل نشوید، این چکلیست را حتماً بررسی کنید. اینها تجربیات من از پروژههایی است که به دلیل نقص فنی ساده، ساعتها دچار مشکل شده بودند:
- ✅ ووکامرس نسخه ۳.۴ یا بالاتر: وبهوکها از این نسخه به بعد بهصورت جدی و پایدار در دسترس قرار گرفتند.
- ✅ گواهینامه SSL معتبر: این مورد «اجباری» است. ووکامرس دادهها را فقط به آدرسهای
https://ارسال میکند. اگر سایت شما SSL ندارد، Webhook کار نخواهد کرد. - ✅ فعال بودن REST API: وبهوکها بخشی از REST API ووکامرس هستند. باید از
ووکامرس>پیکربندی>پیشرفته>REST APIمطمئن شوید که فعال است. - ✅ دسترسیهای سرور (Firewall): مطمئن شوید که فایروال سرور شما (یا سرویسهایی مثل Cloudflare) جلوی درخواستهای POST ورودی به Delivery URL شما را نمیگیرد.
- ✅
WP_DEBUGخاموش باشد: در حالتtrueبودنWP_DEBUGدر فایلwp-config.php، ممکن است هشدارهای PHP به خروجی JSON اضافه شده و آن را خراب کنند.
اگر این موارد را دارید، تقریباً آمادهاید. فقط یک قطعه پازل دیگر برای ارتباطات امنتر باقی مانده است.
کجا و چطور API Key ووکامرس رو ایجاد کنم؟
اگرچه Webhook برای «ارسال» داده نیازی به API Key ندارد (چون از Secret Key برای امضا استفاده میکند)، اما سیستمی که دادهها را «دریافت» میکند (مثلاً سیستم انبار شما)، اغلب نیاز دارد که در پاسخ، کاری روی سایت شما انجام دهد (مثلاً موجودی را آپدیت کند). در این حالت، آن سیستم به API Key نیاز دارد.
ساخت API Key بسیار ساده است:
- به
ووکامرس>پیکربندی>پیشرفته>REST APIبروید. - روی
افزودن کلیدکلیک کنید. - یک
توضیحبنویسید (مثلاً: “دسترسی سیستم انبار”). کاربررا انتخاب کنید (معمولاً مدیر کل).- سطح دسترسی را
خواندن/نوشتن(Read/Write) انتخاب کنید. - روی
تولید کلید APIکلیک کنید.
🚨 هشدار امنیتی: ووکامرس «کلید مصرفکننده» (Consumer Key) و «سکرت کی مصرفکننده» (Consumer Secret) را فقط یک بار به شما نشان میدهد. آنها را بلافاصله در یک جای امن کپی کنید. این کلیدها معادل نام کاربری و رمز عبور فروشگاه شما هستند؛ هرگز آنها را در اختیار دیگران قرار ندهید.
حالا که همهچیز آماده است، بیایید به قلب تنظیمات Webhook برگردیم و ببینیم کدام رویداد به درد ما میخورد.
تنظیمات Webhook: کدوم Event رو انتخاب کنم؟
«موضوع» یا Topic (همان Event)، مشخص میکند که ووکامرس «چه زمانی» باید Webhook را شلیک کند. انتخاب اشتباه در اینجا یعنی یا دادهای ارسال نمیشود، یا در زمان اشتباه ارسال میشود.
در اینجا پرکاربردترین Eventها و کاربرد تجربی آنها آمده است:
| موضوع (Topic) | رویداد فارسی | چه زمانی شلیک میشود؟ | مثال کاربردی |
order.created | سفارش ایجاد شد | به محض ثبت سفارش (قبل از پرداخت) | ارسال به CRM برای پیگیری سفارشات ناموفق |
order.updated | سفارش بهروزرسانی شد | با هر تغییری (مثل تغییر وضعیت) | همگامسازی وضعیت سفارش با سیستم خارجی |
order.status.updated | (توصیه شده) وضعیت سفارش آپدیت شد | فقط زمانی که وضعیت تغییر میکند | بهترین گزینه برای ارسال پیامک (مثلاً “آماده ارسال”) |
product.created | محصول ایجاد شد | وقتی محصول جدیدی اضافه میکنید | اطلاع به تیم مارکتینگ برای شروع تبلیغات |
product.updated | محصول بهروزرسانی شد | با هر تغییری (قیمت، موجودی و…) | حیاتی برای همگامسازی با انبار |
customer.created | مشتری ایجاد شد | وقتی کاربر جدیدی ثبتنام میکند | افزودن خودکار به لیست خبرنامه ایمیلی |
نکته تجربی: برای کارهای مربوط به سفارش، почти همیشه از order.status.updated یا اکشنهای خاص مثل woocommerce_order_status_completed استفاده کنید، نه order.created. چون order.created قبل از پرداخت هم شلیک میشود و ممکن است برای سیستم حسابداری یا انبار شما ایجاد مشکل کند.
خب، Event را انتخاب کردیم. حالا میرسیم به مهمترین فیلد: «نشانی اینترنتی تحویل». این آدرس چیست و از کجا بیاوریم؟
Delivery URL چیست و چطور یکی بسازم؟
Delivery URL (که به آن Endpoint هم میگوییم) آدرسی در اینترنت است که «شنونده» دادههای Webhook شماست. این آدرس باید بتواند درخواستهای HTTP POST را دریافت و پردازش کند.
این URL میتواند یکی از موارد زیر باشد:
- یک سرویس واسط (مثل Zapier یا Make): این سرویسها یک URL آماده به شما میدهند و اجازه میدهند دادهها را بدون کدنویسی به هزاران اپلیکیشن دیگر بفرستید. (عالی برای شروع).
- یک اسکریپت سفارشی روی هاست خودتان: شما یک فایل PHP (مثلاً
my-webhook-handler.php) روی هاست خود آپلود میکنید و آدرس آن را میدهید. (انعطاف کامل). - یک سرویس تست (مثل Webhook.site): این ابزارها یک URL موقت برای تست به شما میدهند تا ببینید چه دادههایی ارسال میشود. (برای دیباگ عالی است).
ساخت یک Endpoint تستی (۱۰ ثانیهای):
برای اینکه ببینید ووکامرس چه چیزی ارسال میکند، بهترین راه استفاده از Webhook.site است.
- به سایت Webhook.site بروید.
- سایت بلافاصله یک «URL منحصربهفرد» به شما میدهد (چیزی شبیه
https://webhook.site/xxxxx...). - این URL را کپی کرده و در فیلد
Delivery URLدر تنظیمات Webhook ووکامرس خود قرار دهید. - Webhook را ذخیره کنید (مثلاً روی رویداد
product.updated). - حالا به یکی از محصولات خود بروید و قیمت آن را تغییر دهید و ذخیره کنید.
- به صفحه Webhook.site برگردید… بوم! 💥 میبینید که دادهها همان لحظه دریافت شدهاند.
ساخت یک Endpoint ساده با PHP:
اگر میخواهید خودتان دادهها را پردازش کنید، یک فایل PHP ساده (مثلاً receiver.php) روی هاست خود بسازید و این کد را داخل آن قرار دهید:
<?php
// دریافت دادههای خام ارسالی از ووکامرس
$payload = file_get_contents('php://input');
// برای دیباگ: دادهها را در یک فایل متنی ذخیره کن
// (در حالت پروداکشن این خط را حذف کنید!)
file_put_contents('webhook_log.txt', $payload . "\n", FILE_APPEND);
// به ووکامرس اطلاع بده که داده دریافت شد
http_response_code(200);
echo 'Webhook Received!';
?>
حالا اگر آدرس https://yourdomain.com/receiver.php را در Delivery URL قرار دهید، هر بار که Webhook شلیک شود، محتوای آن در فایل webhook_log.txt ذخیره میشود.
حالا که میدانیم دادهها چطور ارسال و دریافت میشوند، بیایید ببینیم این «بسته داده» یا Payload اصلاً چه شکلی است.
ساختار دادههای Webhook ووکامرس چطوریه؟ (آناتومی یک Payload)
ووکامرس دادهها را در یک فرمت استاندارد و بسیار محبوب به نام JSON (JavaScript Object Notation) ارسال میکند. این فرمت برای خواندن توسط انسان و پردازش توسط ماشین بسیار ساده است. این بسته داده ارسالی را Payload مینامیم.
ساختار کلی Payload شبیه به چیزی است که از طریق WooCommerce REST API دریافت میکنید. یعنی اگر با API ووکامرس آشنا باشید، با Webhook هم راحت خواهید بود. هر رویداد (Topic)، ساختار JSON مخصوص به خود را دارد.
درک این ساختار برای پردازش دادهها حیاتی است. بیایید یک مثال واقعی از پرکاربردترین Payload، یعنی سفارش جدید را کالبدشکافی کنیم.
چطور Payload یک سفارش جدید رو بخونم و پردازش کنم؟
وقتی شما Webhook را روی رویداد order.created (یا هر رویداد مرتبط با سفارش) تنظیم میکنید، ووکامرس یک JSON عظیم شامل «تمام» اطلاعات آن سفارش را ارسال میکند.
نمونه Payload سفارش (خلاصهشده):
{
"id": 727,
"status": "processing",
"currency": "IRT",
"total": "50000",
"customer_id": 1,
"customer_note": "لطفا زود ارسال شود.",
"billing": {
"first_name": "علی",
"last_name": "رضایی",
"address_1": "خیابان آزادی",
"city": "تهران",
"postcode": "12345",
"email": "[email protected]",
"phone": "09123456789"
},
"shipping": {
"first_name": "علی",
"last_name": "رضایی",
...
},
"payment_method_title": "پرداخت آنلاین",
"line_items": [
{
"id": 31,
"name": "کلاه کپ",
"product_id": 22,
"quantity": 2,
"total": "50000",
"sku": "HAT-RED"
}
],
...
}
چطور این اطلاعات را با PHP بخوانیم؟
فرض کنید این JSON به همان فایل receiver.php ما ارسال شده است. برای استخراج نام مشتری و مبلغ کل، اینطور عمل میکنیم:
<?php
// دریافت دادههای خام
$payload = file_get_contents('php://input');
// تبدیل JSON رشتهای به آرایه PHP
$data = json_decode($payload, true);
// بررسی اینکه آیا داده معتبر است
if ($data && isset($data['id'])) {
// استخراج اطلاعات مورد نیاز
$order_id = $data['id'];
$customer_name = $data['billing']['first_name'] . ' ' . $data['billing']['last_name'];
$total_amount = $data['total'];
$phone_number = $data['billing']['phone'];
// مثال: ذخیره در لاگ
$log_message = "سفارش جدید: $order_id از $customer_name به مبلغ $total_amount با شماره $phone_number";
file_put_contents('orders_log.txt', $log_message . "\n", FILE_APPEND);
http_response_code(200); // اعلام موفقیت به ووکامرس
echo "Order $order_id processed.";
} else {
// اگر داده JSON نبود یا ساختار مورد انتظار را نداشت
http_response_code(400); // Bad Request
echo "Invalid Payload.";
}
?>
همانطور که میبینید، با تابع json_decode، کار با دادهها مثل آب خوردن میشود. حالا بیایید نگاهی به دادههای محصول بیندازیم.
فیلدهای مهم در Webhook محصول کدومن و چطور ازشون استفاده کنم؟
وقتی رویداد product.updated شلیک میشود، Payload ارسالی، آبجکت کامل محصول است. این Webhook برای همگامسازی انبار حیاتی است.
فیلدهای کلیدی در Payload محصول:
id: شناسه محصول در ووکامرس.name: نام محصول.sku(Stock Keeping Unit): مهمترین فیلد! این شناسه انبار شماست که باید بین ووکامرس و سیستم انبارداری یکسان باشد.price: قیمت فعلی.regular_price: قیمت اصلی.sale_price: قیمت فروش ویژه.stock_quantity: مهمترین فیلد! تعداد موجودی فعلی.manage_stock: آیا مدیریت موجودی فعال است (true/false).status: وضعیت محصول (مثلاًpublishیاdraft).categories: لیست دستهبندیها.variations: (برای محصولات متغیر) آرایهای از ID محصولات متغیر.
سناریوی استفاده: سیستم انبار شما یک Endpoint دارد. شما یک Webhook روی product.updated تنظیم میکنید. وقتی ادمین سایت، موجودی محصولی با SKU SHIRT-BLUE-L را از ۵ به ۳ تغییر میدهد، Webhook شلیک میشود. سیستم انبار شما Payload را دریافت، sku و stock_quantity جدید (یعنی ۳) را میخواند و موجودی آن کالا را در دیتابیس خودش آپدیت میکند.
صحبت تئوری کافیست. بیایید وارد فاز عملی شویم و اولین پروژه واقعی را (بدون حتی یک خط کدنویسی سمت سرور) اجرا کنیم.
پروژه عملی ۱: اتصال ووکامرس به Google Sheets با Webhook (بدون کد!)
این یکی از محبوبترین درخواستهاست: «چطور یک لیست زنده از سفارشاتم در یک فایل اکسل آنلاین داشته باشم؟» ما این کار را با ترکیب Webhook ووکامرس و Google Apps Script (که رایگان است) انجام میدهیم. این پروژه برای مبتدیان عالی است.
هدف: به محض ثبت هر «سفارش تکمیل شده»، اطلاعات آن (شماره سفارش، نام مشتری، مبلغ کل، ایمیل) در یک ردیف جدید در گوگل شیت ثبت شود.
اول باید گیرنده (Endpoint) خود را در گوگل بسازیم.
چطور Google Apps Script رو برای دریافت Webhook آماده کنم؟
- یک فایل Google Sheet جدید در اکانت گوگل خود بسازید. (مثلاً نام آن را “گزارش فروش” بگذارید).
- از منوی
Tools(یاابزارها) >Script editor(یاویرایشگر اسکریپت) را انتخاب کنید. - یک پروژه جدید باز میشود. کدهای پیشفرض را پاک کنید و کد زیر را دقیقاً کپی کنید:
// این تابع زمانی اجرا میشود که یک درخواست POST (از طرف ووکامرس) بیاید
function doPost(e) {
try {
// دادههای JSON ارسالی از ووکامرس را پارس میکنیم
var data = JSON.parse(e.postData.contents);
// اگر رویداد ما "سفارش آپدیت شده" بود
// (میتوانید دقیقتر هم چک کنید که status == 'completed' باشد)
if (data.id) {
// فایل شیت فعال را باز کن
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// اطلاعات مورد نیاز را استخراج کن
var orderId = data.id;
var customerName = data.billing.first_name + " " + data.billing.last_name;
var total = data.total;
var email = data.billing.email;
var status = data.status;
var date = new Date().toLocaleString("fa-IR"); // تاریخ و زمان فعلی
// یک ردیف جدید به انتهای شیت اضافه کن
sheet.appendRow([orderId, customerName, total, email, status, date]);
// به ووکامرس یک پاسخ موفقیتآمیز برگردان
return ContentService.createContent("Success").setMimeType(ContentService.MimeType.TEXT);
}
} catch (error) {
// در صورت بروز خطا، آن را در یک شیت دیگر لاگ کن (اختیاری)
Logger.log(error);
}
// اگر داده معتبر نبود
return ContentService.createContent("Error").setMimeType(ContentService.MimeType.TEXT);
}
حالا باید این اسکریپت را بهعنوان یک وباپ منتشر کنیم تا URL به ما بدهد:
- پروژه را ذخیره کنید (مثلاً “WooCommerce Webhook”).
- روی دکمه
Deploy(یااستقرار) >New deployment(یااستقرار جدید) کلیک کنید. - از منوی
Select type(چرخدنده)، گزینهWeb appرا انتخاب کنید. - در بخش
Execute as(اجرا بهعنوان)،Me(خودم) را انتخاب کنید. - مهم: در بخش
Who has access(چه کسی دسترسی دارد)، گزینهAnyone(هر کسی) را انتخاب کنید. (نگران نباشید، URL شما مخفی است). - روی
Deployکلیک کنید و دسترسیهای لازم را به گوگل بدهید (Allow کنید). - تمام! گوگل یک
Web app URLبه شما میدهد. این همان Delivery URL شماست.
آن را کپی کرده و در تنظیمات Webhook ووکامرس (مثلاً برای رویداد Order Updated) قرار دهید و ذخیره کنید.
حالا که اتصال برقرار است، باید دادهها را به ستونهای درست مپ کنیم.
نقشهبرداری فیلدهای ووکامرس به ستونهای Sheet چطور انجام میشه؟
در فایل گوگل شیت خود، ردیف اول را بهعنوان سرستون (Header) تنظیم کنید تا فایل خوانا باشد. بر اساس کدی که در مرحله قبل نوشتیم (sheet.appendRow([...]))، این ستونها باید به ترتیب باشند:
| ستون A | ستون B | ستون C | ستون D | ستون E | ستون F |
| شماره سفارش | نام مشتری | مبلغ کل | ایمیل | وضعیت | تاریخ ثبت |
کد ما (sheet.appendRow([orderId, customerName, total, email, status, date]);) دقیقاً دادهها را به همین ترتیب در ستونها میریزد.
تست نهایی: یک سفارش تستی در سایت خود ثبت کنید و وضعیت آن را به processing یا completed تغییر دهید. در عرض چند ثانیه، خواهید دید که یک ردیف جدید بهطور جادویی در گوگل شیت شما ظاهر میشود! 🪄
این پروژه قدرت آموزش Webhook وردپرس را بدون نیاز به زیرساخت پیچیده نشان داد. اما اگر بخواهیم کارهای جدیتری مثل ارسال پیامک انجام دهیم، به کمی کد PHP نیاز خواهیم داشت.
پروژه عملی ۲: ارسال خودکار پیامک به مشتری با Webhook + کد PHP
این یکی از پرتکرارترین نیازهای فروشگاههای ایرانی است. میخواهیم وقتی وضعیت سفارش به «تکمیل شد» (Completed) تغییر میکند، یک پیامک حاوی تشکر و کد سفارش برای مشتری ارسال شود.
پیشنیاز: ثبتنام در یک پنل پیامکی (مثل کاوه نگار، ملی پیامک، و…) و دریافت API Key.
ما به یک Endpoint (یک فایل PHP روی هاست خودمان) نیاز داریم تا Webhook را دریافت و به API پیامک متصل شود.
کد کامل PHP برای دریافت Webhook و ارسال پیامک چیه؟
- یک فایل به نام
sms-handler.phpروی هاست خود (مثلاً در ریشهpublic_html) بسازید. - آدرس آن (
https://yourdomain.com/sms-handler.php) را بهعنوانDelivery URLدر ووکامرس (برای رویدادOrder status updated) تنظیم کنید. - کد زیر را در فایل
sms-handler.phpقرار دهید. (این مثال بر اساس API کاوه نگار نوشته شده، برای پنلهای دیگر باید مستندات API آنها را چک کنید).
<?php
// کلید API پنل پیامک خود را اینجا قرار دهید
define('API_KEY', 'YOUR_KAVENEGAR_API_KEY_HERE');
// شماره خط اختصاصی شما
define('SENDER_LINE', '10008000XXXX');
// دریافت دادههای خام از ووکامرس
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
// --- بخش امنیتی (در بخش بعدی توضیح داده میشود) ---
// $secret = 'YOUR_SECRET_KEY'; // کلید مخفی که در ووکامرس زدید
// $signature = $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'];
// $hash = base64_encode(hash_hmac('sha256', $payload, $secret, true));
// if ($hash !== $signature) {
// http_response_code(401); // Unauthorized
// die('Invalid signature.');
// }
// --- پایان بخش امنیتی ---
// بررسی میکنیم که آیا داده معتبر است و آیا وضعیت سفارش "تکمیل شد" است
if ($data && isset($data['status']) && $data['status'] === 'completed') {
// استخراج اطلاعات لازم
$order_id = $data['id'];
$customer_name = $data['billing']['first_name'];
$phone_number = $data['billing']['phone']; // شماره موبایل مشتری
// پاکسازی شماره موبایل (برای فرمتهای ایرانی)
$phone_number = preg_replace('/^(\+98|0)/', '98', $phone_number);
// متن پیامک
$message = "سلام {$customer_name} عزیز،\nسفارش شما به شماره {$order_id} با موفقیت تکمیل و ارسال شد.\nاز خرید شما متشکریم.\nفروشگاه شما";
// تابع ارسال پیامک با کاوه نگار (استفاده از cURL)
sendKavenegarSms($phone_number, $message);
http_response_code(200);
echo "SMS Sent for Order $order_id";
} else {
// اگر وضعیت "completed" نبود، کاری نکن
http_response_code(200); // باز هم 200 برمیگردانیم تا ووکامرس دوباره تلاش نکند
echo "Ignored: Status was not 'completed'.";
}
/**
* تابع ارسال پیامک با API کاوه نگار
* @param string $receptor شماره گیرنده (مثلا 989123456789)
* @param string $message متن پیام
*/
function sendKavenegarSms($receptor, $message) {
$url = 'https://api.kavenegar.com/v1/' . API_KEY . '/sms/send.json';
$data_to_send = [
'receptor' => $receptor,
'sender' => SENDER_LINE,
'message' => $message
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data_to_send));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// (اختیاری) میتوانید پاسخ را لاگ کنید تا از ارسال موفق مطمئن شوید
// file_put_contents('sms_api_log.txt', $response . "\n", FILE_APPEND);
}
?>
حالا هر بار که سفارشی را «تکمیل» کنید، این اسکریپت اجرا شده و پیامک ارسال میشود. اما یک مشکل بزرگ وجود دارد: این Endpoint «ناامن» است!
چطور امنیت Webhook رو با Secret Key تضمین کنم؟
در حال حاضر، «هر کسی» که آدرس sms-handler.php شما را بداند، میتواند با ارسال یک JSON ساختگی، از خط شما پیامک انبوه ارسال کند! 😱
راهحل: استفاده از «کلید مخفی» (Secret Key).
- در تنظیمات Webhook در ووکامرس، یک «کلید مخفی» (Secret) قوی وارد کنید (مثلاً:
my$Super!S3cret@K3y). - ووکامرس تمام Payloadها را با استفاده از این کلید و الگوریتم
HMAC-SHA256امضا میکند و نتیجه را در هِدِرX-WC-Webhook-Signatureارسال میکند. - ما باید در اسکریپت PHP خود، این امضا را «بررسی» کنیم.
کافیست در کد PHP بالا، بخشی که کامنت شده (--- بخش امنیتی ---) را از کامنت خارج کنید و YOUR_SECRET_KEY را با کلید مخفی خودتان جایگزین کنید.
// --- بخش امنیتی (فعال شده) ---
$secret = 'my$Super!S3cret@K3y'; // کلید مخفی که در ووکامرس زدید
$payload = file_get_contents('php://input'); // این باید قبل از json_decode باشد
$signature = $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'];
// نکته: ووکامرس امضا را به صورت base64 ارسال میکند
$hash = base64_encode(hash_hmac('sha256', $payload, $secret, true));
if (!hash_equals($hash, $signature)) { // از hash_equals برای مقابله با حملات Timing Attack استفاده کنید
http_response_code(401); // Unauthorized
die('Invalid signature.');
}
// --- پایان بخش امنیتی ---
// حالا دادهها امن هستند و میتوانیم decode کنیم
$data = json_decode($payload, true);
// ... ادامه کد ...
حالا، فقط درخواستهایی که با کلید مخفی «شما» امضا شده باشند (یعنی فقط از طرف ووکامرس شما آمده باشند) پذیرفته میشوند.
این پروژه قدرت واقعی آموزش Webhook وردپرس را در اتوماسیونهای سفارشی نشان میدهد. بیایید سطح را بالاتر ببریم و به سراغ یک سناریوی پیچیدهتر، یعنی انبارداری دوطرفه برویم.
پروژه عملی ۳: همگامسازی موجودی با سیستم انبار خارجی
این سناریو، کابوس بسیاری از فروشگاههای بزرگ است: چطور موجودی انبار فیزیکی (یا نرمافزار ERP) با موجودی سایت همیشه یکسان باشد؟ راهحل، یکپارچهسازی دوطرفه است.
- مسیر ۱ (سایت به انبار): وقتی سفارشی در ووکامرس ثبت میشود (
order.status.completed)، یک Webhook به سیستم انبار شلیک میشود تا موجودی را در انبار «کم» کند. (این کار ساده است، شبیه پروژه SMS). - مسیر ۲ (انبار به سایت): وقتی کالایی در انبار فیزیکی شارژ میشود (یا به هر دلیلی تغییر میکند)، سیستم انبار باید موجودی را در ووکامرس «آپدیت» کند. این کار با REST API ووکامرس انجام میشود، نه Webhook.
چالش اصلی، ایجاد یک معماری دوطرفه و مدیریت تداخلهاست.
چطور Webhook دوطرفه بین ووکامرس و سیستم انبار بسازم؟
معماری صحیح به این شکل است:
۱. سمت ووکامرس (ارسال تغییرات به انبار):
- رویداد:
product.updated(برای تغییرات دستی موجودی توسط ادمین) - رویداد:
order.status.completed(برای کسر موجودی پس از فروش) - Delivery URL: آدرس Endpoint سیستم انبار (مثلاً
https://api.erp.com/v1/update-stock) - Payload: ووکامرس
product.updatedرا میفرستد. سیستم انبارskuوstock_quantityجدید را میخواند و دیتابیس خود را آپدیت میکند. برای سفارش، سیستم انبارline_itemsرا میخواند،skuوquantityهر آیتم را استخراج و از موجودی خود کسر میکند.
۲. سمت سیستم انبار (ارسال تغییرات به ووکامرس):
- رویداد: (در سیستم انبار) “موجودی تغییر کرد”.
- اکشن: سیستم انبار باید با REST API ووکامرس تماس بگیرد.
- Endpoint ووکامرس:
PUT /wp-json/wc/v3/products/<id>یاPUT /wp-json/wc/v3/products/batch - کد نمونه (سمت سرور انبار – PHP/cURL):
// این کد در سرور انبار اجرا میشود
function updateWooCommerceStock($product_sku, $new_stock_level) {
// ابتدا باید ID محصول را از روی SKU پیدا کنیم
// (این کار را میتوان با یک درخواست GET API انجام داد یا از قبل ذخیره کرد)
$product_id = getProductIdBySku($product_sku);
if (!$product_id) return;
$woo_url = 'https://yourdomain.com/wp-json/wc/v3/products/' . $product_id;
$consumer_key = 'YOUR_CONSUMER_KEY'; // کلید API که قبلا ساختیم
$consumer_secret = 'YOUR_CONSUMER_SECRET';
$data = [
'stock_quantity' => $new_stock_level
];
$ch = curl_init($woo_url);
curl_setopt($ch, CURLOPT_USERPWD, $consumer_key . ':' . $consumer_secret);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
// (لاگ کردن پاسخ برای دیباگ)
}
این معماری یک ارتباط دوطرفه کامل را برقرار میکند. اما یک مشکل ظریف وجود دارد: اگر همزمان هم ادمین سایت و هم انباردار موجودی را تغییر دهند چه؟
مدیریت Conflict در بهروزرسانی همزمان موجودی چطور انجام میشه؟
این مشکل (معروف به Race Condition) میتواند فاجعهبار باشد. (موجودی ۵ است، سایت یکی میفروشد میشود ۴، همزمان انباردار میبیند ۵ تاست و میگوید ۵ تا شارژ شد، موجودی را روی ۱۰ تنظیم میکند. اما چون یکی فروش رفته بود، باید ۹ میشد!)
راهکارهای عملی برای مدیریت تداخل:
- تعیین «منبع حقیقت» واحد (Single Source of Truth):
- بهترین روش: در ۹۹٪ موارد، سیستم انبار (ERP) باید منبع حقیقت باشد.
- اجرا: ووکامرس «هرگز» نباید مستقیماً موجودی را کم کند. وقتی سفارشی ثبت میشود، Webhook فقط سفارش را به انبار «اطلاع» میدهد. انبار موجودی را کم میکند و سپس با REST API به ووکامرس میگوید: “موجودی جدید فلان کالا X عدد است.”
- مزیت: موجودی سایت همیشه آینهای از انبار واقعی است و تداخل رخ نمیدهد.
- قفلگذاری (Locking):
- روش: قبل از آپدیت، سیستم انبار یک «قفل» روی رکورد محصول در ووکامرس میگذارد (مثلاً با یک متافیلد). اگر سیستم دیگری (مثل Webhook سفارش) بخواهد همزمان آپدیت کند، میبیند قفل است و منتظر میماند (یا در صف قرار میگیرد).
- ایراد: پیچیدگی فنی بالایی دارد و میتواند باعث کندی شود.
- استفاده از Timestamp (مُهر زمانی):
- روش: هر آپدیت یک مُهر زمانی دارد. سیستم فقط آپدیتی را میپذیرد که مُهر زمانی آن «جدیدتر» از آخرین آپدیت ثبت شده باشد.
- ایراد: در میلیثانیهها باز هم احتمال خطا وجود دارد.
توصیه تجربی من: همیشه از روش اول (ERP به عنوان منبع حقیقت) استفاده کنید. این کار فروشگاه شما را مقیاسپذیر و قابل اعتماد میکند.
ارتباط با انبار حیاتی است، اما ارتباط با مشتریان فعلی و بالقوه چطور؟ بیایید به سراغ CRM برویم.
پروژه عملی ۴: اتصال ووکامرس به CRM با Webhook (مثال با HubSpot)
مدیریت ارتباط با مشتری (CRM) قلب تپنده فروش و مارکتینگ است. Webhookها بهترین راه برای تغذیه خودکار CRM شما با دادههای داغ و تازه از فروشگاه هستند. میخواهیم به محض ثبتنام مشتری جدید (یا ثبت اولین سفارش)، اطلاعات او در HubSpot (یک CRM محبوب) ثبت شود.
این پروژه شبیه ارسال پیامک است: ووکامرس (با Webhook) داده را میفرستد، و یک اسکریپت واسط (Endpoint) آن را دریافت، تبدیل و به API مقصد (HubSpot) ارسال میکند.
چطور اطلاعات مشتری رو به صورت خودکار در CRM ثبت کنم؟
- دریافت API Key از HubSpot: (یا هر CRM دیگری که استفاده میکنید، مثل دیدار، Salesforce و…).
- تنظیم Webhook در ووکامرس:
- موضوع (Topic):
customer.created(اگر فقط ثبتنام مد نظر است) یاorder.created(برای گرفتن مشتریان مهمان که خرید میکنند). - Delivery URL: آدرس اسکریپت واسط خودتان (مثلاً
crm-handler.php).
- موضوع (Topic):
- کد اسکریپت واسط (
crm-handler.php):
<?php
// کلید API خصوصی HubSpot
define('HUBSPOT_API_KEY', 'YOUR_HUBSPOT_PRIVATE_APP_KEY');
// (بخش بررسی امضای Secret Key باید اینجا باشد - برای اختصار حذف شده)
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
// اطلاعات مشتری را استخراج میکنیم
// اگر از 'customer.created' استفاده میکنید:
// $email = $data['email'];
// $first_name = $data['first_name'];
// $last_name = $data['last_name'];
// $phone = $data['billing']['phone']; // ممکن است در customer.created خالی باشد
// اگر از 'order.created' استفاده میکنید (توصیه شده، چون اطلاعات کاملتر است):
if ($data && isset($data['billing']['email'])) {
$email = $data['billing']['email'];
$first_name = $data['billing']['first_name'];
$last_name = $data['billing']['last_name'];
$phone = $data['billing']['phone'];
// تابع ایجاد یا آپدیت مخاطب در HubSpot
createOrUpdateHubSpotContact($email, $first_name, $last_name, $phone);
http_response_code(200);
echo "Contact Processed.";
} else {
http_response_code(400);
echo "Invalid data.";
}
/**
* تابع ایجاد یا آپدیت مخاطب در HubSpot با API v3
*/
function createOrUpdateHubSpotContact($email, $fname, $lname, $phone) {
$url = 'https://api.hubapi.com/crm/v3/objects/contacts';
$properties = [
'email' => $email,
'firstname' => $fname,
'lastname' => $lname,
'phone' => $phone,
'lifecyclestage' => 'customer' // مرحله چرخه عمر را "مشتری" میگذاریم
];
$post_data = json_encode(['properties' => $properties]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . HUBSPOT_API_KEY
]);
$response = curl_exec($ch);
curl_close($ch);
// (لاگ کردن پاسخ برای دیباگ)
}
?>
این کد به محض اولین خرید مشتری، یک پروفایل کامل برای او در CRM شما میسازد و او را بهعنوان “مشتری” نشانهگذاری میکند. تیم فروش شما میتواند بلافاصله کار را شروع کند.
اما قدرت واقعی CRM فراتر از ثبت اطلاعات تماس است.
ردیابی مسیر خرید مشتری (Customer Journey) با Webhook چطوریه؟
این یک تکنیک «هک رشد» پیشرفته است. ما میخواهیم تمام تعاملات کلیدی مشتری را در CRM ثبت کنیم تا بفهمیم دقیقاً چه مسیری را طی کرده است.
معماری:
- Webhook
customer.created: یک “مخاطب” (Contact) جدید در CRM میسازد (مرحله: Lead). - Webhook
order.created(سفارش ناموفق/در انتظار): یک “معامله” (Deal) جدید در CRM با وضعیت “در انتظار پرداخت” میسازد و به آن مخاطب متصل میکند. - Webhook
order.status.updatedبهcompleted: همان “معامله” را در CRM به وضعیت “موفق” (Won) تغییر میدهد. - Webhook
order.status.updatedبهfailed: همان “معامله” را به وضعیت “ناموفق” (Lost) تغییر میدهد. - (پیشرفته) Webhook سفارشی برای
cart.updated: با کدنویسی سفارشی، میتوانیم حتی سبدهای خرید رها شده را بهعنوان یک “معامله” در CRM ثبت کنیم تا تیم فروش برای بازیابی آنها تماس بگیرد.
پیادهسازی این سناریو، فروشگاه شما را از یک سایت ساده به یک ماشین فروش هوشمند تبدیل میکند. اما قبل از اینکه همهچیز را به این شکل اتوماتیک کنیم، باید مطمئن شویم که همهچیز درست کار میکند.
چطور Webhook های ووکامرس رو تست و دیباگ کنم؟
هیچچیز بدتر از یک اتوماسیون «ناقص» نیست. (مثلاً پیامک ارسال نشود، یا بدتر، «دو بار» ارسال شود). تست و دیباگ، حیاتیترین بخش آموزش Webhook وردپرس است. خوشبختانه ابزارهای عالی برای این کار وجود دارد.
تجربه من میگوید ۹۰٪ مشکلات Webhook در ۵ دقیقه اول با ابزار مناسب قابل شناسایی هستند.
بهترین ابزارهای آنلاین برای تست Webhook کدومن؟
قبل از اینکه ساعتها کد PHP خود را دیباگ کنید، ابتدا مطمئن شوید که ووکامرس «اصلاً داده را ارسال میکند» و «چه چیزی» ارسال میکند.
- Webhook.site (بهترین دوست شما):
- کاربرد: همانطور که در پروژه ۱ دیدیم، این سایت یک URL موقت به شما میدهد. آن را در Delivery URL ووکامرس کپی کنید. هر رویدادی که در سایتتان رخ دهد، Payload کامل آن را «بلافاصله» در مرورگر خود میبینید.
- مزیت: میتوانید ببینید آیا امضای (Signature) ارسالی صحیح است، چه هدرهایی ارسال شده و ساختار JSON دقیقاً چیست.
- RequestBin (مشابه Webhook.site):
- کاربرد: عملکردی دقیقاً شبیه Webhook.site دارد و یک URL برای دریافت و بازرسی درخواستهای HTTP ایجاد میکند.
- Postman (حرفهایترین):
- کاربرد: Postman برای «شبیهسازی» درخواستها عالی است. بهجای اینکه هر بار یک سفارش واقعی ثبت کنید، میتوانید Payload (JSON) که از Webhook.site گرفتهاید را کپی کرده و با Postman مستقیماً به Endpoint خودتان (مثلاً
sms-handler.php) ارسال (POST) کنید و ببینید اسکریپت شما چه پاسخی میدهد. این کار فرآیند دیباگ را ۱۰۰ برابر سریعتر میکند.
- کاربرد: Postman برای «شبیهسازی» درخواستها عالی است. بهجای اینکه هر بار یک سفارش واقعی ثبت کنید، میتوانید Payload (JSON) که از Webhook.site گرفتهاید را کپی کرده و با Postman مستقیماً به Endpoint خودتان (مثلاً
اگر این ابزارها نشان دادند که ووکامرس داده را «ارسال» میکند، اما به Endpoint شما «نمیرسد» یا «خطا» میدهد، وقت آن است که لاگهای خود ووکامرس را بررسی کنید.
لاگهای Webhook ووکامرس رو کجا و چطور بررسی کنم؟
ووکامرس تمام تلاشهای موفق و ناموفق برای ارسال Webhook را ثبت (لاگ) میکند. این گنجینهای برای عیبیابی است.
- به
ووکامرس>وضعیت(Status) بروید. - روی تب
لاگها(Logs) کلیک کنید. - از منوی کشویی، لاگ مربوط به Webhook خود را پیدا کنید. (معمولاً با
webhook-delivery-شروع میشود). - روی
نمایشکلیک کنید.
تفسیر لاگها:
شما لیستی از تلاشهای ارسال را میبینید. به دنبال این موارد باشید:
- پاسخ (Response):
Response code: 200(OK): عالی! یعنی Endpoint شما داده را دریافت کرده و پاسخ موفقیتآمیز داده است.Response code: 404(Not Found): یعنیDelivery URLشما اشتباه است یا فایل PHP در آن آدرس وجود ندارد.Response code: 500(Internal Server Error): بدترین خطا! یعنیDelivery URLشما درست است، اما اسکریپت PHP شما یک خطای مرگبار (Fatal Error) دارد (مثلاً خطای سینتکس، مشکل در اتصال به دیتابیس و…).Response code: 401(Unauthorized): آفرین! یعنی کد امنیتی شما (بررسی Signature) درست کار کرده و یک درخواست نامعتبر را رد کرده است.
- پیام خطا (Error Message):
cURL error 60: SSL certificate problem: یعنی SSL سایت مقصد (Endpoint شما) نامعتبر یا منقضی شده است.Timeout was reached: یعنی اسکریپت PHP شما آنقدر کند است (مثلاً در حال ارسال ایمیل سنگین بوده) که ووکامرس قبل از گرفتن پاسخ، قطع کرده است.
این لاگها معمولاً مستقیماً به شما میگویند که مشکل کجاست.
چرا Webhook من Failed میشه؟ (۷ دلیل رایج + راه حل)
بر اساس تجربه صدها پروژه، اینها ۷ دلیل اصلی شکست خوردن Webhookها هستند:
- مشکل SSL:
- دلیل:
Delivery URLشماhttp://است یا گواهینامه SSL آن نامعتبر است. - راه حل: مطمئن شوید URL با
https://شروع میشود و SSL معتبر (مثلاً Let’s Encrypt) دارید.
- دلیل:
- آدرس URL اشتباه (خطای 404):
- دلیل: غلط املایی در
Delivery URLیا فایل PHP در آن مسیر وجود ندارد. - راه حل: URL را کپی/پیست کنید و مطمئن شوید در مرورگر باز میشود (البته باید خطای “Invalid Payload” بدهد، نه 404).
- دلیل: غلط املایی در
- خطای سرور (خطای 500):
- دلیل: کد PHP شما باگ دارد.
- راه حل:
WP_DEBUGرا (فقط برای تست) در سرور مقصد فعال کنید یا لاگهای خطای PHP (error_log) سرور را بررسی کنید.
- مشکل فایروال یا IP Ban:
- دلیل: فایروال سرور مقصد (Endpoint)، آیپی سرور ووکامرس شما را بلاک کرده است.
- راه حل: آیپی سرور سایت خود را در لیست سفید (Whitelist) فایروال سرور مقصد قرار دهید.
- امضای (Signature) نامعتبر (خطای 401):
- دلیل:
Secret Keyدر ووکامرس و اسکریپت PHP شما «یکسان» نیست (حتی یک فاصله اضافه). - راه حل: کلید مخفی را دوباره در هر دو طرف کپی/پیست کنید.
- دلیل:
- زمانبندی (Timeout):
- دلیل: اسکریپت Endpoint شما بیش از حد طول میکشد (پیشفرض ووکامرس ۵ ثانیه است).
- راه حل: هرگز کارهای سنگین (مثل ارسال ایمیل، ساخت PDF) را مستقیماً در Endpoint انجام ندهید. داده را بگیرید،
http_response_code(200)را برگردانید و سپس کار سنگین را در پسزمینه (Background Job) انجام دهید. (به بخش صفبندی مراجعه کنید).
- فرمت نادرست پاسخ:
- دلیل: اسکریپت شما بهجای یک پاسخ کوتاه، یک صفحه HTML کامل یا یک خطای PHP برمیگرداند.
- راه حل: مطمئن شوید اسکریپت شما فقط یک کد وضعیت (مثل ۲۰۰) و یک پیام متنی ساده برمیگرداند و هیچ خروجی ناخواستهای (echo یا warning) ندارد.
عیبیابی Webhookها در فروشگاههای کوچک ساده است. اما وقتی روزی ۱۰۰۰ سفارش دارید، داستان عوض میشود.
چطور Webhook رو برای حجم بالای سفارش بهینهسازی کنم؟
وقتی فروشگاه شما بزرگ میشود (مثلاً در کمپین یلدا)، ممکن است در یک دقیقه ۱۰۰ سفارش ثبت شود. این یعنی ۱۰۰ شلیک Webhook همزمان! اگر Endpoint شما (مثلاً اسکریپت ارسال پیامک) کند باشد، سرور شما بهسرعت از کار میافتد و کل فرآیند checkout مختل میشود. 😨
مشکل: ووکامرس منتظر میماند تا Endpoint شما پاسخ 200 OK بدهد. اگر این فرآیند ۵ ثانیه طول بکشد، کاربر در صفحه تشکر از خرید ۵ ثانیه معطل میماند. این یعنی فاجعه!
راهحل: پردازش غیرهمزمان (Asynchronous) یا صفبندی (Queueing).
صفبندی (Queue) Webhook ها چیه و چرا بهش نیاز دارم؟
صفبندی یعنی Endpoint شما «هیچ» کار سنگینی انجام نمیدهد. فقط داده را میگیرد و میگوید: “متشکرم، گرفتم!” (و بلافاصله 200 OK برمیگرداند). سپس آن داده را در یک «صف» (Queue) قرار میدهد تا یک پردازشگر دیگر (Worker) در پسزمینه و سر فرصت آن را بردارد و پردازش کند (مثلاً پیامک را ارسال کند).
- Endpoint (سریع):
receiver.php- دریافت Payload.
- تأیید امضا.
- افزودن Payload به صف (مثلاً در Redis یا دیتابیس).
http_response_code(200)را برگردان. (کل فرآیند: ۵۰ میلیثانیه)
- Worker (کند – در پسزمینه):
worker.php(که با Cron Job هر دقیقه اجرا میشود)- آیا کاری در صف هست؟
- بله، Payload سفارش ۱۲۳ را بردار.
- پیامک را ارسال کن (ممکن است ۳ ثانیه طول بکشد).
- کار را از صف حذف کن.
- برو سراغ کار بعدی.
چطور پیادهسازی کنیم؟
- روش حرفهای: استفاده از سیستمهای صف مثل Redis یا RabbitMQ.
- روش ساده (وردپرسی): استفاده از Action Scheduler (که خود ووکامرس از آن استفاده میکند) یا حتی WP Cron برای ایجاد یک صف ساده در دیتابیس.
این کار باعث میشود سایت شما حتی در اوج ترافیک، مثل برق و باد کار کند. اما اگر Worker هم نتواند کار را انجام دهد (مثلاً API پیامک قطع باشد) چه؟
Retry Logic و مدیریت خطا در Webhook چطور پیادهسازی میشه؟
خود ووکامرس یک سیستم تلاش مجدد (Retry) ساده دارد. اگر Endpoint شما پاسخی غیر از 200 برگرداند (مثلاً 503 Service Unavailable)، ووکامرس ۵ بار دیگر (با فواصل زمانی افزایشی) تلاش میکند تا داده را تحویل دهد.
اما اگر شما از سیستم صف استفاده میکنید (و Endpoint شما همیشه 200 برمیگرداند)، این مسئولیت به عهده Worker شماست.
استراتژی Exponential Backoff (تلاش مجدد هوشمند):
کد Worker شما باید به این شکل باشد:
- کار را از صف بردار.
- سعی کن پیامک را ارسال کنی.
- موفق شدی؟ عالی. کار را حذف کن.
- شکست خوردی؟ (مثلاً API پیامک خطای ۵۰۰ داد)
- کار را حذف نکن!
- تعداد تلاشهای قبلی (Retry Count) این کار را +۱ کن.
- آن را به انتهای صف برگردان و زمان اجرای بعدی آن را بر اساس
تعداد تلاش * ۵ دقیقهتنظیم کن. - (بار اول: ۵ دقیقه بعد، بار دوم: ۱۰ دقیقه بعد، بار سوم: ۱۵ دقیقه بعد…)
- اگر تعداد تلاش از ۵ بیشتر شد، کار را به صف «مرده» (Dead-letter Queue) منتقل کن و به ادمین «هشدار» (Alert) بفرست!
این معماری، یک سیستم اتوماسیون ضدضربه و حرفهای میسازد. البته همه اینها به شرطی است که از اول جلوی دسترسیهای غیرمجاز را گرفته باشیم.
امنیت Webhook: چطور از سوءاستفاده جلوگیری کنم؟
یک Endpoint (Delivery URL) که بهصورت عمومی در دسترس است، یک هدف جذاب برای هکرهاست. همانطور که در پروژه SMS دیدیم، اگر Endpoint شما امن نباشد، میتواند منجر به ارسال اسپم، سرقت اطلاعات مشتریان یا از کار انداختن سرور شما شود.
ما قبلاً مهمترین روش (تأیید امضا با Secret Key) را بررسی کردیم. اما برای امنیت لایهلایه، این تکنیکها را هم به کار بگیرید:
IP Whitelisting برای Webhook ووکامرس چطور تنظیم میشه؟
این روش یعنی Endpoint شما «فقط» درخواستهایی را میپذیرد که از آدرس IP سرور ووکامرس شما آمده باشند.
- آدرس IP ثابت سرور سایت خود را پیدا کنید. (اگر هاست اشتراکی دارید یا از CDN استفاده میکنید، این IP ممکن است متغیر باشد و این روش مناسب نیست).
- در فایل
.htaccessدر پوشهای که Endpoint شما (مثلاًsms-handler.php) قرار دارد، این کد را اضافه کنید:
<Files "sms-handler.php">
Order Deny,Allow
Deny from all
Allow from YOUR_WOOCOMMERCE_SERVER_IP
</Files>
YOUR_WOOCOMMERCE_SERVER_IPرا با IP سرور خود جایگزین کنید.
ایراد: این روش شکننده است. اگر IP سرور شما تغییر کند، Webhookها از کار میافتند. استفاده از Secret Key (HMAC) همیشه ارجح است.
رمزنگاری دادههای Webhook با HMAC-SHA256 چطوریه؟
این همان روشی است که در پروژه ۲ (SMS) پیادهسازی کردیم و ارزش تکرار را دارد، چون استاندارد طلایی امنیت Webhook است.
مرور سریع پیادهسازی در PHP:
- در ووکامرس: یک Secret Key قوی تنظیم کنید.
- در Endpoint (PHP):
$secret = 'YOUR_SECRET_KEY'; // باید دقیقا با ووکامرس یکی باشد
$payload = file_get_contents('php://input'); // دادههای خام
$signature_header = $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE']; // امضای ارسالی
// امضای خودمان را بر اساس همان داده خام و کلید مخفی میسازیم
$computed_hash = base64_encode(hash_hmac('sha256', $payload, $secret, true));
// مقایسه امن برای جلوگیری از حملات Timing Attack
if (!hash_equals($computed_hash, $signature_header)) {
// امضاها مطابقت ندارند! درخواست جعلی است!
http_response_code(401);
die('Invalid Signature.');
}
// اگر کد به اینجا برسد، یعنی درخواست معتبر و از طرف ووکامرس شماست
$data = json_decode($payload, true);
// ... ادامه پردازش ...
این کد باید اولین چیزی باشد که در فایل Endpoint شما اجرا میشود.
چطور از حملات DDoS به Endpoint های Webhook محافظت کنم؟
اگر هکری تصمیم بگیرد Endpoint شما را با ارسال میلیونها درخواست در ثانیه بمباران کند (DDoS)، حتی اگر امضای شما درست کار کند، باز هم منابع سرور شما (CPU, RAM) مصرف شده و سایت از دسترس خارج میشود.
راهکارها:
- Rate Limiting (محدودسازی نرخ):
- در سطح وبسرور (Nginx/Apache): تنظیم کنید که هر آدرس IP در دقیقه فقط میتواند (مثلاً) ۶۰ درخواست به
sms-handler.phpارسال کند. - در سطح CDN: سرویسهایی مثل Cloudflare ابزارهای Rate Limiting عالی برای محافظت از Endpointها دارند.
- در سطح وبسرور (Nginx/Apache): تنظیم کنید که هر آدرس IP در دقیقه فقط میتواند (مثلاً) ۶۰ درخواست به
- استفاده از CDN و WAF (Web Application Firewall):
- سرویسهایی مثل Cloudflare یا Sucuri میتوانند ترافیک مخرب و رباتها را قبل از رسیدن به سرور شما شناسایی و مسدود کنند.
- تغییر نام Endpoint:
- از نامهای قابل حدس مثل
webhook.phpاستفاده نکنید. از یک نام طولانی و تصادفی (مثلhandler-a83nf7dn3.php) استفاده کنید تا پیدا کردن آن سختتر شود.
- از نامهای قابل حدس مثل
امنیت مهم است، اما گاهی اوقات پیچیدگی پیادهسازی این موارد باعث میشود به فکر راهحلهای آماده بیفتیم.
Webhook ووکامرس vs افزونههای اتوماسیون: کدوم بهتره؟
سوال همیشگی: “آیا باید خودم کد بنویسم (Webhook دستی) یا یک افزونه اتوماسیون (مثل Zapier، Make، یا AutomateWoo) بخرم؟”
پاسخ کوتاه: بستگی به نیاز، بودجه و مهارت شما دارد.
بهعنوان یک مدیر فروش آنلاین، من از هر دو در پروژههای مختلف استفاده کردهام.
مقایسه جامع:
| ویژگی | Webhook دستی (کدنویسی) | افزونه/سرویس اتوماسیون (Zapier, Make) |
| هزینه | رایگان (بهجز هزینه توسعهدهنده) | هزینههای اشتراک ماهانه (گران در مقیاس بالا) |
| انعطافپذیری | بینهایت. هر کاری قابل انجام است. | محدود به اکشنها و تریگرهای از پیش تعریف شده. |
| سرعت پیادهسازی | کند (نیاز به کدنویسی، تست، دیباگ) | بسیار سریع. (در عرض چند دقیقه) |
| نیاز به مهارت فنی | بالا. (نیاز به PHP، امنیت، مدیریت سرور) | بدون کد. (No-Code / Low-Code) |
| نگهداری | نیاز به مانیتورینگ و آپدیت کد دارد. | توسط سرویسدهنده انجام میشود. |
| عملکرد | در صورت بهینهسازی (Queue)، بسیار سریع. | ممکن است تاخیر چند دقیقهای داشته باشد. |
چه موقع باید افزونه بخرم و چه موقع Webhook بنویسم؟
این چکلیست تصمیمگیری به شما کمک میکند:
✅ افزونه (مانند Zapier یا AutomateWoo) بخرید اگر:
- شما برنامهنویس نیستید و نمیخواهید هزینه توسعهدهنده بدهید.
- نیاز به اتصالات «ساده و استاندارد» دارید (مثلاً: سفارش جدید -> ردیف گوگل شیت).
- میخواهید «سریع» (در کمتر از یک ساعت) اتوماسیون را راهاندازی کنید.
- تعداد تراکنشهای شما (تعداد اجرای Webhook) کم است و هزینههای ماهانه Zapier برایتان توجیهپذیر است.
🛒 توصیه ویژه:
اگر به دنبال اتوماسیونهای داخلی وردپرس و ووکامرس هستید (مثلاً ارسال ایمیل پیگیری بعد از ۷ روز، دادن کوپن به مشتریان وفادار)، افزونه AutomateWoo یک شاهکار است. ما در وردپرس نیاز، نسخه کاملاً اورجینال و سالم این افزونه را با گارانتی بازگشت وجه ارائه میدهیم. این به شما آرامش خاطر میدهد که با یک فایل نال شده و ناامن، امنیت فروشگاه خود را به خطر نمیاندازید.
✅ Webhook سفارشی (کدنویسی) بنویسید اگر:
- شما برنامهنویس هستید یا به تیم فنی دسترسی دارید.
- نیاز به یکپارچهسازی «پیچیده» و «سفارشی» با نرمافزار داخلی (مثل ERP یا CRM ایرانی) دارید.
- حجم تراکنش شما «بسیار بالا» است و هزینه سرویسهای واسط سرسامآور میشود.
- به عملکرد «بلادرنگ» (Real-time) و بدون تاخیر نیاز دارید.
- میخواهید «کنترل کامل» روی منطق پردازش، مدیریت خطا و امنیت داشته باشید.
اگر مسیر دوم را انتخاب کردید، باید بدانید که فقط به Webhookهای پیشفرض ووکامرس محدود نیستید.
چطور Webhook سفارشی برای نیازهای خاص بیزینسم بسازم؟
گاهی اوقات، رویدادهای (Topic) پیشفرض ووکامرس کافی نیستند. مثلاً ووکامرس رویدادی برای «سبد خرید رها شده» یا «تغییر وضعیت اشتراک» (از افزونه Subscriptions) ندارد.
خبر خوب این است که به لطف سیستم قلاب (Hook) وردپرس، میتوانید برای «هر» اتفاقی که در سایتتان میافتد، یک Webhook سفارشی بسازید و شلیک کنید.
کد کامل ساخت Custom Webhook با WordPress Hook ها
فرض کنید میخواهیم به محض اینکه وضعیت یک سفارش به «تکمیل شد» (Completed) تغییر کرد، «فقط» ID سفارش و ایمیل مشتری را به یک URL خاص ارسال کنیم (نه کل Payload سنگین ووکامرس).
کافیست این کد را به فایل functions.php قالب فرزند (Child Theme) خود اضافه کنید:
/**
* شلیک Webhook سفارشی زمانی که سفارش تکمیل میشود
* ما از قلاب 'woocommerce_order_status_completed' استفاده میکنیم
*/
add_action('woocommerce_order_status_completed', 'my_custom_webhook_trigger', 10, 1);
function my_custom_webhook_trigger($order_id) {
// دریافت آبجکت سفارش
$order = wc_get_order($order_id);
if (!$order) {
return;
}
// آدرس Endpoint مقصد
$target_url = 'https://api.my-service.com/custom-endpoint';
// دادههای سفارشی که میخواهیم ارسال کنیم
$custom_data = [
'order_id' => $order_id,
'customer_email' => $order->get_billing_email(),
'total' => $order->get_total(),
'event_type' => 'order_completed_simple'
];
// آمادهسازی آرگومانها برای ارسال
$args = [
'body' => json_encode($custom_data), // دادهها را JSON میکنیم
'headers' => [
'Content-Type' => 'application/json',
'X-My-Secret' => 'MY_OWN_SECRET_KEY' // یک هدر امنیتی سفارشی
],
'timeout' => 15, // افزایش زمان انتظار
'blocking' => false // **مهم:** غیربلاک کردن برای عدم تاخیر
];
// ارسال درخواست در پسزمینه
wp_remote_post($target_url, $args);
}
نکات کلیدی این کد:
woocommerce_order_status_completed: این قلاب دقیقاً در زمان مناسب اجرا میشود.$custom_data: ما دقیقاً مشخص کردیم چه فیلدهایی ارسال شوند (Payload سبک و سفارشی).'blocking' => false: این بخش طلایی است. با تنظیم این گزینه، وردپرس منتظر پاسخ Endpoint نمیماند و بلافاصله به کار خود ادامه میدهد. این یعنی اجرای Webhook «هیچ» تاثیری روی سرعت سایت شما نخواهد داشت (پردازش غیرهمزمان).
گاهی اوقات یک Webhook به تنهایی کافی نیست و باید چندین عملیات پشت سر هم انجام شوند.
چطور چند Webhook رو به صورت زنجیرهای (Chain) اجرا کنم؟
به این کار “Webhook Pipeline” یا “Chaining” میگویند. فرض کنید میخواهید:
- سفارش ثبت شود -> Webhook 1 به CRM برود.
- «بعد» از اینکه CRM تایید کرد، -> Webhook 2 به سیستم انبار برود.
- «بعد» از تایید انبار -> Webhook 3 به پنل پیامک برود.
اشتباه مهلک: تنظیم ۳ Webhook همزمان در ووکامرس. چون ممکن است پیامک قبل از ثبت در انبار ارسال شود!
معماری صحیح (Chaining):
- ووکامرس فقط Webhook 1 (CRM) را شلیک میکند.
- Endpoint مربوط به CRM داده را پردازش میکند.
- اگر پردازش موفق بود، «خودِ اسکریپت CRM» (نه ووکامرس)، درخواست بعدی را به Endpoint انبار (Webhook 2) ارسال (POST) میکند.
- Endpoint انبار پردازش میکند و در صورت موفقیت، «خودش» درخواست را به Endpoint پیامک (Webhook 3) میفرستد.
در این مدل، شما یک «زنجیره» از عملیات ساختهاید که ترتیب و وابستگیها در آن رعایت میشود. سرویسهای واسط مثل Zapier یا Make (Integromat) این کار را بهصورت گرافیکی و بسیار ساده انجام میدهند.
مدیریت این سطح از پیچیدگی، نیازمند ابزارهای نظارتی حرفهای است.
مدیریت و مانیتورینگ Webhook ها در مقیاس بزرگ چطوریه؟
وقتی دهها Webhook حیاتی (انبار، مالی، CRM) دارید که کسبوکار شما به آنها وابسته است، دیگر نمیتوانید به لاگهای متنی ووکامرس بسنده کنید. شما به مانیتورینگ بلادرنگ (Real-time) و سیستم هشدار (Alerting) نیاز دارید.
اگر یک Webhook (مثلاً کسر موجودی) برای ۱ ساعت قطع شود، ممکن است ضرر مالی سنگینی به شما وارد کند.
بهترین ابزارهای Monitoring برای Webhook کدومن؟
ابزارهای مانیتورینگ به شما داشبوردهایی میدهند که نشان میدهد کدام Webhookها موفق، کدام ناموفق و میانگین زمان پاسخدهی آنها چقدر بوده است.
- Sentry (برای مانیتورینگ خطا):
- کاربرد: Sentry یک ابزار ردیابی خطای اپلیکیشن است. شما SDK آن را در Endpoint (PHP) خود نصب میکنید. به محض وقوع هرگونه خطای PHP (خطای ۵۰۰)، Sentry آن را با جزئیات کامل (شامل Payload ورودی) برای شما ثبت و هشدار ارسال میکند.
- مزیت: قبل از اینکه مشتری شاکی شود، شما از خطا باخبر میشوید.
- New Relic یا Datadog (برای مانیتورینگ عملکرد):
- کاربرد: اینها ابزارهای APM (Application Performance Monitoring) هستند. به شما میگویند Endpoint شما چقدر طول میکشد تا اجرا شود (مثلاً ۳ ثانیه)، چقدر CPU مصرف میکند و گلوگاه کار کجاست (مثلاً اتصال به API پیامک کند است).
- مزیت: برای بهینهسازی و شناسایی کندیها عالی هستند.
- داشبورد سفارشی (با Google Sheets یا دیتابیس):
- کاربرد: همانطور که در پروژه ۱ دیدیم، میتوانید یک گوگل شیت بسازید. اما این بار، در Endpoint خود کد بگذارید که «فقط» در صورت «شکست» (Fail)، یک ردیف در شیت “خطاهای Webhook” ثبت کند.
اما مانیتورینگ بهتنهایی کافی نیست؛ شما باید بلافاصله از وقوع خطا مطلع شوید.
چطور Alert برای Failed Webhook ها تنظیم کنم؟
شما ۲۴ ساعته پای داشبورد مانیتورینگ ننشستهاید. شما نیاز دارید که در صورت بروز مشکل، سیستم به شما «خبر» بدهد.
پیادهسازی سیستم هشدار (در Endpoint خودتان):
شما میتوانید در بلوک catch (جایی که خطاها را مدیریت میکنید) در کد PHP خود، یک هشدار ارسال کنید.
<?php
// ... (دریافت داده و...) ...
try {
// تلاش برای پردازش (مثلا ارسال به CRM)
$success = sendToCrm($data);
if (!$success) {
throw new Exception("CRM API returned false.");
}
http_response_code(200);
echo "Success";
} catch (Exception $e) {
// *** اینجا بخش هشدار است! ***
// ۱. ثبت خطای داخلی
file_put_contents('FATAL_ERROR_LOG.txt', $e->getMessage() . "\n" . $payload . "\n\n", FILE_APPEND);
// ۲. ارسال هشدار فوری به ادمین (مثلا از طریق Slack یا ایمیل)
sendAlertToAdmin("FATAL Webhook Error", $e->getMessage());
// ۳. به ووکامرس خطای سرور را برگردان تا دوباره تلاش کند
http_response_code(503); // Service Unavailable
echo "Failed to process, please retry.";
}
function sendAlertToAdmin($subject, $message) {
// اینجا میتوانید از Slack API، ایمیل یا حتی API پیامک خودتان استفاده کنید
// تا به محض وقوع خطا، مدیر فنی مطلع شود.
// mail('[email protected]', $subject, $message);
}
?>
این معماری به شما اطمینان میدهد که هیچ خطای پنهانی در سیستم شما وجود نخواهد داشت.
Webhook در ووکامرس چه محدودیتهایی داره و چطور دورشون بزنم؟
Webhookها جادویی هستند، اما عصای موسی نیستند. محدودیتهای فنی و ساختاری هم دارند که اگر آنها را نشناسید، دچار مشکل خواهید شد.
درک این محدودیتها به شما کمک میکند تا معماری بهتری طراحی کنید و از راهحلهای جایگزین در جای مناسب استفاده کنید.
محدودیت تعداد Webhook در ووکامرس چیه و چطور بیشتر بسازم؟
در حالت پیشفرض، ووکامرس هیچ محدودیت «سختگیرانهای» روی تعداد Webhookهایی که میتوانید بسازید، ندارد. شما میتوانید ۱۰۰ Webhook هم بسازید.
اما مشکل جای دیگری است:
هر Webhook فعال، به یک «رویداد» (Hook وردپرس) متصل میشود. اگر شما ۲۰ Webhook داشته باشید که همگی به order.created گوش میدهند، به محض ثبت یک سفارش، وردپرس باید ۲۰ درخواست HTTP POST را (بهصورت غیرهمزمان) شلیک کند. این کار میتواند بار (Load) قابل توجهی روی سرور شما ایجاد کند، مخصوصاً اگر هاست ضعیفی داشته باشید.
راه حل (Fan-out):
بهجای ساخت ۲۰ Webhook در ووکامرس، فقط یک Webhook بسازید (مثلاً order.created). آن را به یک Endpoint «واسط» (مثلاً master-handler.php) بفرستید. سپس این اسکریپت واسط، مسئولیت شلیک ۲۰ درخواست دیگر (به CRM، انبار، پیامک و…) را در پسزمینه (با استفاده از صف) بر عهده میگیرد.
این کار بار را از روی ووکامرس برمیدارد و مدیریت را متمرکز میکند.
چرا Webhook من Timeout میشه و چطور زمان اجرا رو افزایش بدم؟
همانطور که قبلاً اشاره شد، ووکامرس بهطور پیشفرض ۵ ثانیه منتظر پاسخ Endpoint شما میماند. اگر Endpoint شما (مثلاً sms-handler.php) بیش از ۵ ثانیه طول بکشد، ووکامرس ارتباط را قطع میکند و در لاگ، خطای Timeout ثبت میکند (و احتمالاً دوباره تلاش میکند که منجر به ارسال دوباره پیامک میشود!).
راه حل اشتباه:
افزایش max_execution_time در PHP یا تنظیم timeout در خود Webhook (که در نسخههای جدیدتر ووکامرس امکانپذیر است).
- چرا اشتباه است؟ چون این کار «کاربر» را در صفحه تشکر از خرید معطل نگه میدارد و تجربه کاربری را نابود میکند.
راه حل درست (پردازش غیرهمزمان):
دوباره تکرار میکنم: Endpoint شما باید «فوقسریع» باشد.
- داده را دریافت کن.
- امضا را چک کن.
- داده را در یک صف (Queue) یا دیتابیس (با وضعیت “Pending”) ذخیره کن.
- پاسخ
200 OKرا برگردان. (کل فرآیند زیر ۱۰۰ میلیثانیه). - یک Cron Job جداگانه در پسزمینه کارهای سنگین (ارسال پیامک، اتصال به CRM) را از روی صف انجام دهد.
این «تنها» راهحل صحیح برای فروشگاههای پرترافیک است.
کیس استادی: چطور یک فروشگاه ۱۰۰۰ سفارشی با Webhook اتوماسیون کرد؟
بگذارید یک پروژه واقعی را که مدیریت کردم، برایتان تشریح کنم.مشتری: یک فروشگاه آنلاین بزرگ در زمینه کالای دیجیتال.مشکل: روزانه بیش از ۱۰۰۰ سفارش. فرآیند کاملاً دستی بود: تیم پشتیبانی سفارشات را از ووکامرس میخواند، در سیستم ERP (سفارشی) وارد میکرد، موجودی را دستی کم میکرد، سپس در پنل پیامک کد رهگیری را وارد میکرد و در نهایت در CRM (سفارشی) مشتری را ثبت میکرد. این فرآیند باعث تاخیر ۲۴ ساعته در ارسال و خطاهای انسانی فاجعهبار میشد.
معماری کامل سیستم Webhook این پروژه چطور بود؟
ما یک معماری مبتنی بر صف (Queue) با استفاده از Redis و یک میکرو-سرویس واسط (نوشته شده با Node.js، اما با PHP هم قابل انجام است) پیادهسازی کردیم.
دیاگرام جریان داده:
- ووکامرس: (رویداد:
order.status.processing– چون پرداخت تایید شده بود)- فقط ۱ Webhook فعال شد به نام
Master_Order_Processor. - Delivery URL:
https://api.intermediary.com/v1/new-order
- فقط ۱ Webhook فعال شد به نام
- سرویس واسط (Endpoint):
- بلافاصله
200 OKبه ووکامرس برمیگرداند (سرعت: ~۲۰ میلیثانیه). - Payload کامل سفارش را در صف Redis (در ۳ کانال مختلف) Push میکرد:
- کانال
erp_queue - کانال
crm_queue - کانال
sms_queue
- کانال
- بلافاصله
- پردازشگرها (Workers) – (اجرا در پسزمینه):
- Worker 1 (ERP): کارهای
erp_queueرا برمیداشت. با API سیستم ERP تماس میگرفت، فاکتور صادر میکرد و موجودی را کسر میکرد. (سنگینترین عملیات). - Worker 2 (CRM): کارهای
crm_queueرا برمیداشت و مشتری را در CRM ایجاد یا آپدیت میکرد. - Worker 3 (SMS): کارهای
sms_queueرا برمیداشت و پیامک “سفارش شما در حال پردازش است” را ارسال میکرد.
- Worker 1 (ERP): کارهای
- ارتباط بازگشتی (از ERP):
- وقتی کالا در ERP «ارسال» میشد، ERP یک Webhook به REST API ووکامرس میزد، وضعیت سفارش را به
completedتغییر میداد و «کد رهگیری» را در متافیلد سفارش ثبت میکرد. - (این تغییر وضعیت، یک Webhook دیگر در ووکامرس برای ارسال پیامک “کد رهگیری” به مشتری فعال میکرد).
- وقتی کالا در ERP «ارسال» میشد، ERP یک Webhook به REST API ووکامرس میزد، وضعیت سفارش را به
چه چالشهایی در مقیاسپذیری پیش اومد و چطور حل شد؟
- چالش (Webhook Storm): در کمپینها، در یک دقیقه ۳۰۰ سفارش میآمد (۳۰۰ Webhook همزمان). سرور واسط ما (Endpoint) دچار مشکل میشد.
- راه حل: ما Endpoint را پشت یک Load Balancer قرار دادیم و آن را روی چند سرور (Replica) اجرا کردیم تا بار پخش شود.
- چالش (از دست رفتن داده): گاهی اوقات سرور Redis (صف) ریستارت میشد و کارهای در حال پردازش از بین میرفتند.
- راه حل: ما از مکانیزم “Persistent Queue” در Redis استفاده کردیم و یک سیستم لاگ ثانویه در دیتابیس MySQL پیاده کردیم. Worker قبل از شروع کار، وضعیت را
Processingو پس از اتمامDoneثبت میکرد تا در صورت کرش کردن، کارهای نیمهتمام قابل بازیابی باشند.
- راه حل: ما از مکانیزم “Persistent Queue” در Redis استفاده کردیم و یک سیستم لاگ ثانویه در دیتابیس MySQL پیاده کردیم. Worker قبل از شروع کار، وضعیت را
- چالش (خطای API شخص ثالث): API سیستم ERP مشتری بسیار کند و ناپایدار بود و مکرراً Timeout میداد.
- راه حل: همان Retry Logic (تلاش مجدد هوشمند) که قبلاً توضیح دادم را پیاده کردیم. اگر Worker مربوط به ERP خطا دریافت میکرد، کار را به صف برمیگرداند تا ۱۰ دقیقه بعد دوباره تلاش کند.
نتیجه: فرآیند پردازش سفارش از ۲۴ ساعت به «کمتر از ۵ دقیقه» کاهش یافت و خطای انسانی به صفر رسید. این قدرت واقعی Webhook ووکامرس در مقیاس بزرگ است.
Webhook ووکامرس برای چه صنایعی کاربرد داره؟ (۸ مثال واقعی)
قدرت Webhook محدود به فروش کالای فیزیکی نیست. در هر صنعتی که از ووکامرس استفاده میکند، Webhook میتواند فرآیندها را متحول کند.
در اینجا چند مثال تخصصی از صنایع مختلف آورده شده است:
چطور فروشگاههای مد و پوشاک از Webhook برای مدیریت سایز استفاده میکنن؟
در صنعت پوشاک، مشکل اصلی «محصولات متغیر» (Variations) است. موجودی هر سایز و رنگ اهمیت دارد.
- سناریو: فروشگاهی که هم حضوری میفروشد و هم آنلاین.
- پیادهسازی:
- فروش آنلاین: Webhook
order.status.completedشلیک میشود. Endpoint،line_itemsرا بررسی میکند،variation_id(مثلاً: پیراهن آبی، سایز L) را استخراج و به API انبار میفرستد تا از موجودی کسر کند. - فروش حضوری: صندوقدار در نرمافزار انبار، همان کالا را میفروشد.
- همگامسازی: نرمافزار انبار با REST API ووکامرس، موجودی همان
variation_idرا در سایت بهروز میکند (PUT /wp-json/wc/v3/products/<product_id>/variations/<variation_id>).
- فروش آنلاین: Webhook
- نتیجه: هرگز کالایی که در فروشگاه فیزیکی تمام شده، در سایت فروخته نمیشود.
Webhook برای محصولات دیجیتال و ارسال خودکار فایل چطور کار میکنه؟
ووکامرس خودش محصولات دانلودی را مدیریت میکند، اما اگر بخواهید فایلها را در سرور دیگری (مثل Amazon S3) نگهداری کنید یا لینکهای منحصربهفرد (مثل لایسنس نرمافزار) تولید کنید، به Webhook نیاز دارید.
- سناریو: فروش دوره آموزشی یا فایلهای حجیم.
- پیادهسازی:
- Webhook
order.status.completedشلیک میشود. - Endpoint شما (مثلاً یک اسکریپت PHP) ایمیل مشتری را دریافت میکند.
- اسکریپت به Amazon S3 متصل میشود و یک «لینک دانلود زماندار» (Presigned URL) با اعتبار ۲۴ ساعت فقط برای آن مشتری تولید میکند.
- اسکریپت، لینک منحصربهفرد را برای مشتری ایمیل میکند.
- Webhook
- نتیجه: امنیت فایلها حفظ میشود و لینکها قابل اشتراکگذاری عمومی نیستند.
اینها تنها بخشی از امکانات بودند. آینده Webhookها حتی از این هم هیجانانگیزتر است.
آینده Webhook در ووکامرس چطوری خواهد بود؟
دنیای Webhookها در حال تحول است. تمرکز از ارسال «دادههای سنگین» (Heavy Payloads) به سمت اتوماسیونهای هوشمندتر، سریعتر و بهینهتر در حال حرکت است.
سه روند اصلی که باید مراقبشان باشید:
GraphQL Webhooks چیه و چه مزیتی نسبت به REST داره؟
مشکل فعلی (REST): وقتی سفارش ثبت میشود، ووکامرس «کل» آبجکت سفارش (یک JSON عظیم ۱۰ کیلوبایتی) را میفرستد، حتی اگر شما «فقط» به شماره موبایل و مبلغ کل نیاز داشته باشید. این اتلاف پهنای باند و منابع پردازشی است.
راهحل (GraphQL):
GraphQL یک زبان کوئری برای APIهاست. در آینده (که برخی پلتفرمها شروع کردهاند)، شما نهتنها Endpoint را مشخص میکنید، بلکه «دقیقاً» مشخص میکنید چه فیلدهایی را میخواهید دریافت کنید.
مثال درخواست (اشتراک) GraphQL Webhook:
subscription {
orderCompleted {
id
total
billing {
phone
}
}
}
نتیجه: Payload دریافتی شما بهجای ۱۰ کیلوبایت، فقط ۱ کیلوبایت و شامل همان ۳ فیلد درخواستی خواهد بود. این یعنی سرعت و بهینگی فوقالعاده، مخصوصاً در مقیاس بزرگ.
روندهای دیگر شامل Serverless Webhooks (اجرای Endpointها روی پلتفرمهایی مثل AWS Lambda بدون نیاز به مدیریت سرور) و AI-powered Automation (اتصال مستقیم Webhookها به مدلهای هوش مصنوعی برای تحلیل دادهها) هستند.
منابع و ابزارهای رایگان برای یادگیری بیشتر Webhook
برای تبدیل شدن به یک متخصص واقعی در آموزش Webhook وردپرس، باید فراتر از این مقاله بروید و دست به آچار شوید.
- مستندات رسمی ووکامرس (WooCommerce Docs):
- مستندات Webhook ووکامرس: بهترین مرجع برای لیست کامل رویدادها (Topics) و ساختار Payloadها.
- مستندات REST API ووکامرس: برای درک ساختار دادهها و ارتباط دوطرفه ضروری است.
- ابزارهای تست و دیباگ:
- Webhook.site: برای بازرسی آنی Payloadها.
- Postman: برای شبیهسازی و تست Endpointها.
- کتابخانهها و کامیونیتی:
- Stack Overflow (تگ woocommerce-webhook): هزاران سوال و جواب واقعی از مشکلات توسعهدهندگان.
- (اگر از PHP استفاده میکنید) مستندات
wp_remote_postوhash_hmacدر کداکس وردپرس و PHP.net.
Webhookها بهتنهایی قدرتمندند، اما وقتی با افزونههای دیگر ترکیب میشوند، قدرتشان چند برابر میشود.
چطور Webhook رو با افزونههای محبوب ووکامرس ترکیب کنم؟
قدرت Webhookها زمانی نمایان میشود که آنها را به اکوسیستم افزونههای خود متصل کنید. بسیاری از افزونههای بزرگ ووکامرس، رویدادها (Topics) و قلابهای (Hooks) مخصوص به خود را برای Webhookها ارائه میدهند.
Webhook برای اشتراکهای دورهای (Subscriptions) چطور تنظیم میشه؟
افزونه WooCommerce Subscriptions (که نسخه اورجینال آن در وردپرس نیاز موجود است) برای فروش محصولات اشتراکی (مثل هاستینگ، دورههای ماهانه، جعبههای اشتراک) استفاده میشود. مدیریت این اشتراکها حیاتی است.
رویدادهای (Topics) اختصاصی Subscriptions:
subscription.created: اشتراک جدید ایجاد شد.subscription.status.updated: (مثلاً ازactiveبهcancelledیاon-hold).subscription.renewal_payment_failed: مهم! پرداخت تمدید ناموفق بود.subscription.renewal_payment_complete: پرداخت تمدید موفق بود.
سناریوی کاربردی (Dunning):
- Webhook روی
subscription.renewal_payment_failedتنظیم میشود. - Endpoint شما شلیک میشود.
- اسکریپت شما یک ایمیل یا پیامک “پرداخت شما ناموفق بود، لطفاً اطلاعات کارت خود را آپدیت کنید” برای مشتری ارسال میکند و یک تیکت در CRM برای تیم پشتیبانی باز میکند.
یکپارچهسازی Webhook با سیستم رزرواسیون و بوکینگ چطوریه؟
افزونه WooCommerce Bookings به شما اجازه میدهد خدمات مبتنی بر زمان (مثل اتاق هتل، وقت مشاوره، اجاره تجهیزات) بفروشید.
رویدادهای (Topics) اختصاصی Bookings:
booking.created: رزرو جدید ایجاد شد (هنوز تایید نشده).booking.status.updated: (مثلاً ازpending-confirmationبهconfirmed).booking.cancelled: رزرو لغو شد.
سناریوی کاربردی (اتصال به تقویم):
- Webhook روی
booking.status.updated(بهconfirmed) تنظیم میشود. - Endpoint شما شلیک میشود.
- اسکریپت شما اطلاعات رزرو (تاریخ، ساعت، نام مشتری) را دریافت میکند.
- با استفاده از Google Calendar API، یک رویداد جدید در تقویم گوگلِ کارمند یا مشاور مربوطه ثبت میکند و برای مشتری هم یک Invite ارسال میکند.
- نتیجه: دیگر هیچ وقت مشاورهای تداخل زمانی پیدا نمیکند.
چطور با Webhook تجربه مشتری رو بهبود بدم؟
اتوماسیون فقط برای کاهش هزینهها نیست؛ بلکه ابزاری قدرتمند برای افزایش رضایت و وفاداری مشتری (CX) است. Webhookها به شما اجازه میدهند در «لحظههای کلیدی» سفر مشتری، با او در ارتباط باشید.
ارسال خودکار پیام تشکر و پیگیری بعد از خرید با Webhook
وقتی سفارشی «تکمیل» میشود، کار شما تمام نشده، بلکه «شروع» شده است.
پیادهسازی:
- Webhook روی
order.status.completedتنظیم شود. - Endpoint شما این بار بهجای ارسال به انبار، به سیستم ایمیل مارکتینگ شما (مثل Mailchimp یا یک اسکریپت سفارشی) متصل میشود.
- اکشن ۱ (فوری): ارسال یک ایمیل تشکر «شخصیسازی شده» (سلام علی عزیز، از خرید کلاه قرمز شما متشکریم…).
- اکشن ۲ (زمانبندی شده): همان Endpoint، یک «کار» (Job) در سیستم ایمیل مارکتینگ شما ایجاد میکند تا «۷ روز بعد» یک ایمیل پیگیری بفرستد: “آیا از کلاه خود راضی بودید؟ لطفاً نظر خود را ثبت کنید و ۱۰٪ تخفیف برای خرید بعدی بگیرید.”
این کار ساده، نرخ بازگشت مشتری را به شدت افزایش میدهد.
چطور با Webhook برنامه وفاداری و امتیازدهی بسازم؟
مشتریان عاشق امتیاز گرفتن هستند. شما میتوانید یک سیستم امتیازدهی ساده را با Webhook پیادهسازی کنید.
پیادهسازی (با کد سفارشی):
- Webhook روی
order.status.completedتنظیم شود. - Endpoint شما (اسکریپت PHP) شلیک میشود.
- کد PHP:
$data = json_decode($payload, true);$user_id = $data['customer_id'];$total_spent = $data['total'];- (اگر
customer_idصفر بود، یعنی مهمان است، پس خارج شو). $points_to_add = floor($total_spent / 1000);(مثلاً به ازای هر ۱۰۰۰ تومان، ۱ امتیاز).$current_points = get_user_meta($user_id, 'loyalty_points', true);$new_points = (int)$current_points + $points_to_add;update_user_meta($user_id, 'loyalty_points', $new_points);- (اختیاری) یک ایمیل به مشتری بفرستد: “تبریک! {$points_to_add} امتیاز جدید به حساب شما اضافه شد.”
این سیستم ساده و مؤثر، مشتریان را به خریدهای بیشتر تشویق میکند.
Troubleshooting: رایجترین خطاهای Webhook و راه حل قطعی
در بخش دیباگ، ۷ دلیل رایج را بررسی کردیم. اما گاهی اوقات لاگهای ووکامرس پیامهای گیجکنندهای میدهند. بیایید ۳ مورد از پرتکرارترین خطاها را که در لاگها میبینید، رمزگشایی کنیم.
خطای “Webhook delivery failed” به چه معناست و چطور حلش کنم؟
این یک خطای «عمومی» است و یعنی ووکامرس نتوانسته پاسخ 200 (یا 2xx و 3xx) از Endpoint شما دریافت کند. این خطا میتواند معانی زیادی داشته باشد:
- علت ۱: خطای 404 (Not Found):
- تشخیص: URL را در مرورگر بزنید. اگر 404 گرفتید، آدرس اشتباه است.
- راه حل:
Delivery URLرا در تنظیمات Webhook اصلاح کنید.
- علت ۲: خطای 500 (Internal Server Error):
- تشخیص: در لاگ ووکامرس،
Response code: 500را میبینید. - راه حل: لاگ خطای PHP (
error_log) سرور مقصد را چک کنید تا ببینید کدام خط از کد PHP شما باعث خطا شده است.
- تشخیص: در لاگ ووکامرس،
- علت ۳: خطای Timeout:
- تشخیص: در لاگ ووکامرس، پیامی شبیه
Timeout was reachedیاcURL error 28میبینید. - راه حل: اسکریپت Endpoint خود را بهینهسازی کنید و از پردازش غیرهمزمان (Queue) استفاده کنید. هرگز زمان Timeout را افزایش ندهید.
- تشخیص: در لاگ ووکامرس، پیامی شبیه
- علت ۴: مشکل SSL (cURL error 60):
- تشخیص: لاگ ووکامرس صراحتاً به SSL اشاره میکند.
- راه حل: SSL سرور مقصد (Endpoint) را با ابزارهایی مثل
SSL Shopperچک کنید و مطمئن شوید معتبر و کامل نصب شده است.
چرا Webhook من دادههای قدیمی ارسال میکنه؟
این یک مشکل بسیار موذیانه است! شما موجودی را به ۱۰ تغییر میدهید، اما Webhook شلیک شده، موجودی را ۹ (مقدار قبلی) ارسال میکند.
دلیل: کش (Cache)!
- کش سرور (Server-side Caching): اگر از سیستمهای کش مثل Varnish یا Redis Caching در سایت ووکامرسی خود استفاده میکنید، ممکن است آبجکت محصول (Product Object) که Webhook از آن داده برمیدارد، کش شده باشد.
- کش Endpoint: (کمتر رایج است) ممکن است پاسخ Endpoint شما توسط Cloudflare یا کش سرور مقصد کش شده باشد.
راه حل:
- مطمئن شوید که Endpoint (Delivery URL) شما از کش مستثنی (Exclude) شده است (هم در افزونه کش وردپرس و هم در Cloudflare).
- در اسکریپت سفارشی (مثل
functions.php) که Webhook را شلیک میکند، قبل از خواندن دادهها، کش مربوط به آن آبجکت را پاک کنید (مثلاًwp_cache_deleteبرای آبجکت سفارش یا محصول).
مشکل “Invalid signature” در Webhook چیه و چطور رفعش کنم؟
شما کد بررسی امضا (HMAC) را در Endpoint خود قرار دادهاید، اما لاگهای شما پر شده از خطای “Invalid Signature”، در حالی که میدانید درخواست از ووکامرس آمده است.
دلایل رایج و راهحل:
- عدم تطابق Secret Key (۹۰٪ موارد):
- علت: یک فاصله (Space) اضافه، یک حرف بزرگ/کوچک متفاوت، یا…
- راه حل: Secret Key را دوباره از ووکامرس کپی و «بدون هیچ تغییری» در کد PHP پیست کنید.
- خواندن اشتباه Payload (۹٪ موارد):
- علت: کد HMAC باید روی «داده خام» (Raw Payload) اجرا شود. اگر شما
$_POSTرا بخوانید یاjson_decodeرا «قبل» از محاسبه هش اجرا کنید، Payload دستکاری شده و امضا مطابقت نخواهد داشت. - راه حل: همیشه ابتدا
$payload = file_get_contents('php://input');را اجرا کنید و هش (Hash) را روی همین متغیر$payloadمحاسبه کنید.
- علت: کد HMAC باید روی «داده خام» (Raw Payload) اجرا شود. اگر شما
- تفاوت الگوریتم (۱٪ موارد):
- علت: ووکامرس از
hash_hmac('sha256', $payload, $secret, true)و سپسbase64_encodeاستفاده میکند. شاید شما از الگوریتم دیگری (مثل md5) یا بدونbase64استفاده میکنید. - راه حل: دقیقاً از کدی که در پروژه SMS ارائه شد، استفاده کنید.
- علت: ووکامرس از
چطور از Webhook برای تحلیل و گزارشگیری استفاده کنم؟
Webhookها یک جریان ثابت از دادههای ارزشمند (سفارشات، مشتریان، محصولات) هستند. بهجای اینکه فقط آنها را به سرویسهای دیگر بفرستید، میتوانید این دادهها را برای تحلیلهای عمیقتر «ذخیره» کنید.
پروژه گوگل شیت یک مثال ساده بود، اما برای تحلیل واقعی، به دیتابیس نیاز دارید.
ساخت دیتابیس سفارشی برای ذخیره تاریخچه Webhook ها
شما میتوانید یک جدول سفارشی در دیتابیس وردپرس (یا یک دیتابیس جداگانه) بسازید تا هر رویداد Webhook را در آن ثبت کنید.
۱. ساختار جدول (SQL):
CREATE TABLE `wp_webhook_history` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`event_topic` VARCHAR(100) NOT NULL,
`status` VARCHAR(20) NOT NULL, -- (e.g., 'received', 'processed', 'failed')
`payload_snippet` TEXT, -- (فقط بخش کوچکی از Payload برای شناسایی)
`error_message` TEXT,
`received_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
۲. کد PHP در Endpoint:
در Endpoint خود (مثلاً master-handler.php)، بهجای پردازش مستقیم، ابتدا داده را در این جدول INSERT کنید:
<?php
// ... (اتصال به $wpdb وردپرس یا دیتابیس) ...
$payload = file_get_contents('php://input');
$topic = $_SERVER['HTTP_X_WC_WEBHOOK_TOPIC']; // ووکامرس تاپیک را در هدر میفرستد
try {
// (بررسی امضا ...)
// (پردازش اصلی ...)
$status = 'processed';
$error_msg = null;
} catch (Exception $e) {
$status = 'failed';
$error_msg = $e->getMessage();
}
// ثبت در دیتابیس تاریخچه
$wpdb->insert('wp_webhook_history', [
'event_topic' => $topic,
'status' => $status,
'payload_snippet' => substr($payload, 0, 500), // فقط ۵۰۰ کاراکتر اول
'error_message' => $error_msg
]);
// ... (برگرداندن پاسخ 200 یا 500) ...
?>
نتیجه: شما یک لاگ کامل، قابل جستجو و دائمی از تمام Webhookها و وضعیت پردازش آنها دارید.
چطور از دادههای Webhook برای پیشبینی فروش استفاده کنم؟
حالا که تمام تاریخچه سفارشات (از طریق Webhook order.created) را در دیتابیس سفارشی خود دارید، میتوانید کوئریهای تحلیلی قدرتمندی اجرا کنید:
- پیدا کردن ساعت اوج فروش:SQL
SELECT HOUR(received_at) AS sales_hour, COUNT(id) AS total_orders FROM wp_webhook_history WHERE event_topic = 'order.created' GROUP BY sales_hour ORDER BY total_orders DESC;(به شما میگوید مثلاً ساعت ۱۰ شب اوج فروش شماست تا کمپینهای خود را در آن ساعت اجرا کنید). - تحلیل محصولات پرفروش (با پردازش JSON):(این کار در MySQL پیچیده است و بهتر است Payload کامل را در دیتابیس NoSQL مثل MongoDB ذخیره کنید یا در PHP پردازش کنید).
این دادهها خوراک تیم Business Intelligence (BI) شما برای تصمیمسازیهای کلان هستند.
Webhook موبایل: اتصال اپلیکیشن به فروشگاه ووکامرس
اگر برای فروشگاه خود اپلیکیشن موبایل (iOS یا Android) دارید، Webhookها بهترین راه برای ارسال اعلانهای آنی (Push Notifications) به کاربران هستند.
سناریو: وقتی سفارش مشتری «ارسال» میشود (وضعیت به completed تغییر میکند)، یک نوتیفیکیشن روی گوشی او ظاهر شود.
دریافت Push Notification از Webhook در اپلیکیشن موبایل چطوریه؟
شما نمیتوانید Webhook را «مستقیماً» به گوشی کاربر بفرستید. معماری صحیح نیازمند یک واسط است (دقیقاً مثل پروژههای قبلی).
معماری کامل (با Firebase):
- ووکامرس: Webhook روی
order.status.updated(بهcompleted).- Delivery URL: آدرس سرور واسط شما (
push-handler.php).
- Delivery URL: آدرس سرور واسط شما (
- اپلیکیشن موبایل:
- کاربر در اپلیکیشن لاگین میکند.
- اپلیکیشن، توکن ثبتنام در Firebase Cloud Messaging (FCM) را دریافت میکند.
- اپلیکیشن این توکن را به همراه
user_idوردپرس، در دیتابیس شما (مثلاً درuser_meta) ذخیره میکند. (مثلاًfcm_token= ‘ABC…XYZ’).
- سرور واسط (
push-handler.php):- Webhook را دریافت میکند (Payload سفارش).
$user_id = $data['customer_id'];را استخراج میکند.- از دیتابیس،
fcm_tokenمربوط به این$user_idرا میخواند. - یک پیام (شامل عنوان و متن) آماده میکند.
- با استفاده از Firebase Admin SDK (PHP)، به API سرور FCM متصل میشود و پیام را به آن
fcm_tokenخاص «ارسال» میکند.
- Firebase (سرور گوگل):
- پیام را دریافت و بلافاصله به گوشی کاربر (iOS یا Android) تحویل میدهد.
- گوشی کاربر:
- نوتیفیکیشن ظاهر میشود: “سفارش شما ارسال شد!” 🚚
این فرآیند پیچیده به نظر میرسد، اما تنها راه استاندارد و قابل اعتماد برای ارسال نوتیفیکیشنهای هدفمند به کاربران اپلیکیشن است.
چطور Webhook رو با هوش مصنوعی ترکیب کنم؟ (کاربردهای AI)
اینجاست که آموزش Webhook وردپرس وارد سطح جدیدی میشود. Webhookها میتوانند «ماشه» (Trigger) اجرای مدلهای هوش مصنوعی باشند تا دادههای فروشگاه شما را در لحظه تحلیل کنند.
سناریو: تحلیل خودکار نظرات مشتریان برای شناسایی مشتریان شاکی.
تحلیل خودکار نظرات مشتری با AI بعد از خرید
- ووکامرس: Webhook روی
comment.created(یا رویداد ثبت نظر ووکامرس).- Delivery URL: آدرس Endpoint تحلیلگر شما (
sentiment-ai.php).
- Delivery URL: آدرس Endpoint تحلیلگر شما (
- Endpoint (
sentiment-ai.php):- Webhook را دریافت میکند.
- متن نظر (
comment_content) را استخراج میکند. - این متن را به یک API تحلیل احساسات (Sentiment Analysis) ارسال میکند (مثل Google Cloud NLP, Amazon Comprehend, یا APIهای Hugging Face).
- کد مثال (با یک API فرضی):PHP
$comment_text = $data['comment_content']; $sentiment_result = json_decode(file_get_contents('https://api.ai-nlp.com/sentiment?text=' . urlencode($comment_text))); // $sentiment_result->score (مثلا -0.9) // $sentiment_result->label (مثلا 'Negative') - تصمیمگیری (Action):
if ($sentiment_result->label === 'Negative' && $sentiment_result->score < -0.7):- اقدام فوری: یک هشدار در Slack برای «تیم پشتیبانی» ارسال کن: “هشدار! نظر بسیار منفی از مشتری X در مورد محصول Y. لطفاً فوراً پیگیری کنید.”
- یک تیکت خودکار در CRM باز کن.
نتیجه: بهجای اینکه نظرات منفی ساعتها روی سایت بمانند، تیم پشتیبانی در عرض چند ثانیه از آن مطلع شده و میتواند با مشتری تماس بگیرد و مشکل را حل کند. این یعنی تبدیل یک مشتری شاکی به یک مشتری وفادار با قدرت AI و Webhook.
۱۰ اشتباه رایج در استفاده از Webhook که باید ازشون دوری کنی
در طول این سالها، اشتباهاتی را دیدهام که باعث از دست رفتن داده، کندی سایت و مشکلات امنیتی شدهاند. از این ۱۰ مورد دوری کنید:
- استفاده از
http://: (قبلاً گفتیم) همیشه ازhttps://برای Endpoint استفاده کنید. - نادیده گرفتن Secret Key: هرگز Endpoint خود را بدون بررسی امضا، در دسترس عموم قرار ندهید.
- پردازش سنگین در Endpoint: (قبلاً گفتیم) بزرگترین اشتباه عملکردی. همیشه از صف استفاده کنید.
- برگرداندن خطای 500: اگر کد شما باگ دارد، خطای ۵۰۰ برمیگرداند. ووکامرس دوباره و دوباره تلاش میکند (Retry) و سرور شما را تحت فشار میگذارد. همیشه خطاها را
try...catchکنید. - عدم لاگبرداری: اگر لاگ نداشته باشید، در زمان بروز مشکل «کور» هستید. حداقل، شکستها (Failures) را لاگ کنید.
- استفاده از
order.createdبرای انبار: این رویداد قبل از پرداخت شلیک میشود. اگر برای کسر موجودی از آن استفاده کنید، سفارشات ناموفق هم موجودی را کم میکنند! (ازorder.status.processingیاcompletedاستفاده کنید). - کدنویسی بدون مدیریت خطا: (مثال: API پیامک قطع است) کد شما باید بتواند این شکستها را مدیریت کند (مثلاً با Retry Logic).
- URL قابل حدس: از
webhook.phpاستفاده نکنید. از نامهای تصادفی برای امنیت بیشتر (Obscurity) استفاده کنید. - عدم استفاده از
hash_equals: برای مقایسه امضا، ازif ($hash == $sig)استفاده نکنید. این در برابر حملات Timing Attack آسیبپذیر است. همیشه ازif (hash_equals($hash, $sig))استفاده کنید. - ذخیره کل Payload در لاگ: (اشتباه بعدی را توضیح میدهد).
چرا نباید از Webhook برای عملیات سنگین استفاده کرد؟
تکرار میکنم چون حیاتی است: Endpoint شما باید در کمتر از ۱ ثانیه (ایدهآل: زیر ۲۰۰ میلیثانیه) پاسخ 200 OK را برگرداند.
عملیات سنگین (که «نباید» در Endpoint انجام شوند):
- ارسال ایمیل (مخصوصاً از طریق SMTP خارجی)
- ساخت فایل PDF (مثل فاکتور)
- اتصال به APIهای کند (مثل برخی ERPهای قدیمی)
- پردازش تصویر
- اجرای کوئریهای پیچیده دیتابیس
راهحل: همه اینها باید به یک صف (Queue) منتقل شوند تا در پسزمینه (Background) اجرا شوند.
خطر ذخیره اطلاعات حساس در لاگ Webhook
وقتی در حال دیباگ هستید، وسوسه میشوید که «کل Payload» را در یک فایل لاگ (webhook_log.txt) ذخیره کنید.
خطر: Payload سفارش شامل اطلاعات کامل مشتری است: نام، آدرس، تلفن، ایمیل.
اگر این فایل لاگ شما (که معمولاً در یک پوشه قابل دسترس وب است) لو برود، شما قوانین حریم خصوصی (مثل GDPR) را نقض کردهاید و اطلاعات تمام مشتریانتان به سرقت میرود.
راهحل امنیتی:
- هرگز کل Payload را در لاگ ذخیره نکنید.
- فقط اطلاعات غیرحساس و ضروری برای دیباگ را لاگ کنید (مثلاً:
Order ID: 123, Status: ProcessedیاError: Invalid Signature). - اگر «باید» Payload کامل را لاگ کنید، آن را «خارج» از ریشه وب (
public_html) ذخیره کنید تا از طریق مرورگر قابل دسترسی نباشد.
۱۰ سوال پرتکرار درباره Webhook ووکامرس که باید جوابشو بدونی
در انتهای این آموزش Webhook وردپرس، احتمالاً سوالاتی در ذهن شما شکل گرفته که بین کاربران دیگر هم مشترک است. ما در «آکادمی فروشگاه اینترنتی وردپرس نیاز» ۱۰ مورد از پرتکرارترین این سوالات را جمعآوری کردهایم تا هیچ ابهامی برای شما باقی نماند و با اطمینان کامل، اتوماسیون فروشگاه خود را شروع کنید. 🚀
آیا برای استفاده از Webhook باید برنامهنویس باشم؟
هم بله و هم خیر! 🤓 بستگی به سطح نیاز شما دارد.
- برای اتوماسیونهای ساده: ابزارهایی مانند Zapier، Integromat (Make) یا افزونههای واسط (مثل Uncanny Automator) به شما اجازه میدهند بدون یک خط کدنویسی، Webhook ووکامرس را به صدها سرویس دیگر (مثل Google Sheets یا Trello) متصل کنید.
- برای اتوماسیونهای سفارشی: اگر بخواهید یکپارچهسازی عمیق با CRM اختصاصی شرکت، سیستم انبارداری ایرانی یا یک اپلیکیشن سفارشی داشته باشید، بله، به دانش برنامهنویسی (معمولاً PHP) برای نوشتن “Endpoint” یا همان دریافتکننده داده نیاز دارید. اما نگران نباشید، مثالهای کد این مقاله یک شروع عالی برای شما هستند.
Webhook رایگانه یا باید هزینهای پرداخت کنم؟
قابلیت Webhook ووکامرس به خودی خود رایگان است و بخشی از هسته ووکامرس محسوب میشود. 💸 اما هزینهها در جای دیگری نهفتهاند:
- سرویس مقصد: اگر از سرویسهای واسط مثل Zapier استفاده کنید، پلنهای رایگان آنها محدودیت دارد و برای استفاده حرفهای باید هزینه اشتراک بپردازید.
- سرور و توسعه: اگر خودتان Endpoint را کدنویسی میکنید، به یک سرور (حتی یک هاست ساده) برای میزبانی آن کد نیاز دارید.
- توسعهدهنده: اگر دانش فنی ندارید، هزینه استخدام یک توسعهدهنده برای پیادهسازی این اتصال، هزینه اصلی شما خواهد بود.
چند تا Webhook میتونم در ووکامرس بسازم؟
در حالت پیشفرض، ووکامرس محدودیت فنی سختی برای تعداد وبهوکها اعمال نمیکند. شما میتوانید دهها Webhook ووکامرس برای رویدادهای مختلف (Event) بسازید. اما مراقب باشید! 🚨 هر وبهوک یک درخواست HTTP به سرور مقصد ارسال میکند. اگر تعداد زیادی وبهوک برای یک رویداد (مثلاً “ایجاد سفارش”) داشته باشید، ممکن است در زمان اوج ترافیک، به سرور شما فشار بیاید. همیشه عملکرد را مانیتور کنید.
Webhook با چه سرعتی داده رو ارسال میکنه؟
بسیار سریع! ⚡️ Webhookها بر اساس رویداد (Event-driven) کار میکنند. به محض اینکه رویداد مورد نظر (مثلاً order.created) در فروشگاه شما رخ دهد، ووکامرس بلافاصله دادهها را به URL مقصد (Endpoint) ارسال میکند. تاخیر معمولاً در حد چند میلیثانیه تا نهایتاً ۱ ثانیه است که به سرعت شبکه و زمان پاسخگویی سرور مقصد بستگی دارد. این همان چیزی است که به آن “همگامسازی Real-time” میگوییم.
اگر سرور مقصد Webhook آفلاین بشه چی میشه؟
این یکی از بهترین ویژگیهای Webhook ووکامرس است. اگر سرور مقصد شما (Endpoint) در دسترس نباشد یا خطای سرور (مثل خطای 500) برگرداند، ووکامرس دادهها را از دست نمیدهد. 😌
ووکامرس یک سیستم تلاش مجدد (Retry Logic) داخلی دارد. اگر ارسال اول ناموفق باشد، چندین بار دیگر (معمولاً تا ۵ بار با فواصل زمانی افزایشی) تلاش میکند تا دادهها را ارسال کند. شما میتوانید وضعیت این تلاشها را در بخش “Logs” همان Webhook در پنل ووکامرس مشاهده کنید.
میتونم Webhook رو فقط برای محصولات خاص فعال کنم؟
مستقیماً از طریق تنظیمات پیشفرض ووکامرس، خیر. 🤷♂️ وقتی شما یک Webhook برای رویداد “بهروزرسانی محصول” میسازید، برای همه محصولات فعال میشود.
اما راهحل چیست؟ شما باید در سمت دریافتکننده (Endpoint خودتان) یک فیلتر منطقی پیادهسازی کنید. یعنی کدی بنویسید که ابتدا Payload (دادههای JSON) را دریافت کند، سپس ID محصول یا دستهبندی آن را بررسی کند و فقط اگر محصول مورد نظر شما بود، ادامه عملیات (مثلاً ارسال پیامک) را انجام دهد و در غیر این صورت، درخواست را نادیده بگیرد.
تفاوت Webhook با Cron Job چیه؟
این یک سوال کلیدی در آموزش Webhook وردپرس است.
- Webhook (مبتنی بر رویداد – Push): مثل زنگ در خانه است. به محض اینکه اتفاقی بیفتد (مشتری زنگ را بزند)، شما بلافاصله مطلع میشوید (صدای زنگ را میشنوید). Webhook منتظر وقوع رویداد است.
- Cron Job (مبتنی بر زمان – Pull): مثل این است که شما هر ۵ دقیقه یکبار از چشمی در، بیرون را نگاه کنید تا ببینید کسی آمده یا نه. Cron Job بر اساس یک زمانبندی مشخص (مثلاً هر ساعت) اجرا میشود تا بررسی کند که آیا کار جدیدی برای انجام هست یا خیر.
نتیجه: Webhook برای کارهای آنی (Real-time) مثل ارسال پیامک سفارش عالی است، اما Cron Job برای کارهای دورهای (مثل تهیه بکاپ شبانه) مناسب است.
آیا Webhook روی سرعت سایتم تأثیر منفی میذاره؟
تقریباً هیچ! 💨 این یکی از نگرانیهای رایج مدیران فروشگاه است. خوشبختانه، ووکامرس Webhookها را به صورت غیرهمزمان (Asynchronous) اجرا میکند.
این یعنی وقتی مشتری دکمه “ثبت سفارش” را میزند، لازم نیست منتظر بماند تا Webhook به سیستم انبارداری یا CRM شما ارسال شود و جواب بگیرد. سفارش مشتری ثبت میشود و پاسخ را میبیند، همزمان ووکامرس در پسزمینه (Background) فرآیند ارسال Webhook را آغاز میکند. بنابراین، Webhook ووکامرس تجربه کاربری و سرعت لود صفحه مشتری را مختل نمیکند.
چطور میفهمم Webhook من درست کار میکنه؟
بهترین راه، بررسی لاگهاست. 🔍
- لاگهای ووکامرس: به مسیر
ووکامرس > پیکربندی > پیشرفته > وبهوکهابروید. روی Webhook مورد نظر خود کلیک کنید. در پایین صفحه، تب “Logs” وجود دارد. در این بخش، تمام درخواستهای ارسالی، زمان ارسال، و پاسخ دریافتی از سرور مقصد (مثل کد 200 OK یا 404 Not Found) ثبت میشود. - ابزارهای تست: قبل از اتصال به سرویس نهایی، از ابزارهایی مثل
Webhook.siteیاRequestBinبهعنوان Delivery URL استفاده کنید. هر رویدادی در سایت شما رخ دهد، بلافاصله دادههای ارسالی را در پنل این ابزارها میبینید و میتوانید ساختار JSON را تحلیل کنید.
میتونم Webhook رو موقتاً غیرفعال کنم بدون اینکه پاکش کنم؟
بله، به راحتی. ⏸️ لازم نیست برای توقف موقت، Webhook را حذف کنید و بعداً دوباره بسازید.
در همان صفحه ویرایش Webhook (جایی که نام، URL و رویداد را تنظیم کردید)، یک فیلد به نام “وضعیت” (Status) وجود دارد. شما میتوانید وضعیت آن را از “فعال” (Active) به “متوقف” (Paused) تغییر دهید. با این کار، Webhook پاک نمیشود، اما ووکامرس دیگر برای رویدادهای جدید، دادهای به آن URL ارسال نخواهد کرد. هر زمان که سیستم مقصد شما آماده بود، میتوانید وضعیت را دوباره به “فعال” برگردانید.
جمعبندی نهایی: از فروشگاه دستی تا یک بیزینس اتوماتیک با Webhook
تبریک میگویم! شما یک سفر عمیق و پروژه محور را در دنیای شگفتانگیز Webhook ووکامرس به پایان رساندید. 🚀 ما از مفاهیم پایهای و تفاوت Webhook با API شروع کردیم، قدم به قدم اولین وبهوک شما را ساختیم، ساختار دادههای JSON را کالبدشکافی کردیم و مهمتر از همه، ۴ پروژه عملی و واقعی را با هم پیادهسازی کردیم؛ از اتصال به Google Sheets بدون کدنویسی گرفته تا ارسال خودکار پیامک، همگامسازی انبار و یکپارچهسازی با CRM.
این فقط یک مقاله تئوری نبود؛ این یک نقشه راه عملی برای تبدیل فروشگاه اینترنتی شما از یک سیستم دستی و پرخطا، به یک ماشین اتوماتیک و هوشمند بود.
فرق یک فروشگاه اینترنتی معمولی با یک بیزینس آنلاین حرفهای و مقیاسپذیر، دقیقاً در همین اتوماسیونها نهفته است. استفاده از Webhook ووکامرس دیگر یک گزینه لوکس یا یک قابلیت فنی پیچیده برای توسعهدهندگان نیست؛ بلکه یک ضرورت استراتژیک برای هر مدیر فروشگاهی است که میخواهد در زمان صرفهجویی کند، خطای انسانی را به صفر برساند و تجربهای بینقص برای مشتریان خود خلق کند.
میدانم، برخی از بخشها، بهخصوص پروژههای مبتنی بر کد PHP، مدیریت خطاها و مباحث امنیتی، ممکن است در نگاه اول دلهرهآور به نظر برسند. اما زیبایی این آموزش Webhook وردپرس که در آکادمی فروشگاه اینترنتی وردپرس نیاز مطالعه کردید، این است که شما مجبور نیستید از همان ابتدا سراغ پیچیدهترین سناریوها بروید.
قدم بعدی شما چیست؟
توصیه من به عنوان یک متخصص هک رشد و مدیر فروش آنلاین: از کوچک شروع کنید.
همین امروز، پروژه اول (اتصال به Google Sheets) را اجرا کنید. دیدن اینکه اطلاعات سفارشهایتان به صورت جادویی و آنی در یک شیت آنلاین ثبت میشود، به شما انگیزهای میدهد که به سراغ اتوماسیونهای بزرگتر بروید.
در این مسیر اتوماسیون فروشگاه اینترنتی، شما تنها نیستید. اگر برای پیادهسازی این سناریوها یا سناریوهای پیشرفتهتر به ابزارهای جانبی (مانند افزونههای اتوماسیون حرفهای، اتصال به CRMهای خاص یا سیستمهای بوکینگ) نیاز دارید، یادتان باشد که در وردپرس نیاز، ما مجموعهای از بهترین و کاملترین افزونههای اورجینال وردپرس را برای شما فراهم کردهایم. تمام افزونه های وردپرس و قالب های وردپرس با گارانتی بازگشت وجه کامل و تضمین سلامت و اصالت فایل ارائه میشوند تا شما با خیال راحت روی رشد بیزینس خود تمرکز کنید، نه درگیری با مشکلات فنی کدهای نال شده.
دنیای وبهوکها، دروازهای به سوی خلاقیت بیپایان در کسبوکار آنلاین است.
حالا نوبت شماست: اولین Webhook که میخواهید در فروشگاه خود راهاندازی کنید، کدام است؟ آیا قصد دارید سیستم انبارداری خود را متصل کنید یا یک برنامه وفاداری مشتری خلاقانه بسازید؟
تجربیات، چالشها و سوالات خود را در بخش نظرات همین مقاله با ما در میان بگذارید. من و تیم فنی وردپرس نیاز، شخصاً پاسخگوی شما خواهیم بود. 💡
- امین زاهد
- مطالعه در 15 دقیقه
- بدون دیدگاه
- امین زاهد
- 15 دقیقه
- 0
- امین زاهد
- مطالعه در 10 دقیقه
- بدون دیدگاه
- امین زاهد
- 10 دقیقه
- 0
- امین زاهد
- مطالعه در 23 دقیقه
- بدون دیدگاه
- امین زاهد
- 23 دقیقه
- 0
- امین زاهد
- مطالعه در 28 دقیقه
- بدون دیدگاه
- امین زاهد
- 28 دقیقه
- 0
- امین زاهد
- مطالعه در 18 دقیقه
- بدون دیدگاه
- امین زاهد
- 18 دقیقه
- 0
- امین زاهد
- مطالعه در 23 دقیقه
- بدون دیدگاه
- امین زاهد
- 23 دقیقه
- 0
- امین زاهد
- مطالعه در 19 دقیقه
- بدون دیدگاه
- امین زاهد
- 19 دقیقه
- 0
- امین زاهد
- مطالعه در 9 دقیقه
- بدون دیدگاه
- امین زاهد
- 9 دقیقه
- 0