লগ ইনফ্রি ট্রায়াল শুরু করুন
Meta Tech Provider

PHP ও Laravel থেকে WhatsApp মেসেজ পাঠান ও গ্রহণ করুন

মেসেজ গ্রহণের জন্য দরকার একটি Laravel রুট, যা Meta-র যাচাইকরণের GET-এর উত্তর দেয় এবং POST গ্রহণ করে। প্যারামিটারগুলো পড়তে হয় hub_mode, hub_verify_token ও hub_challenge নামে, কারণ PHP ডটকে আন্ডারস্কোরে বদলে দেয়। মেসেজ পাঠানো মানে Cloud API-র মেসেজ এন্ডপয়েন্টে নম্বরের ফোন নম্বর আইডি ও টোকেন দিয়ে একটি Http::withToken() POST। কোনো SDK লাগে না।

hub_challenge

PHP আসা ভেরিয়েবলের নামে ডটকে আন্ডারস্কোরে বদলে দেয়, তাই hub.challenge পড়তে হয় hub_challenge হিসেবে।

routes/api.php

install:api কমান্ডে তৈরি Laravel-এর স্টেটলেস API রুট /api-এর অধীনে চলে এবং web গ্রুপের CSRF সুরক্ষার বাইরে থাকে।

v25.0

Meta-র বর্তমান মেসেজ পাঠানোর উদাহরণে থাকা Graph API ভার্সন, POST /{phone-number-id}/messages-এ।

Laravel-এ কীভাবে WhatsApp মেসেজ গ্রহণ করবেন?

routes/api.php-তে একই পাথে একটি GET ও একটি POST রুট দিয়ে। ফাইলটি না থাকলে আগে php artisan install:api চালান। API রুট স্টেটলেস এবং web গ্রুপের বাইরে, তাই CSRF টোকেন না থাকার কারণে Meta-র POST বাতিল হয় না। routes/web.php-র রুটে ঠিক এই সমস্যাই হয়।

GET রুট Meta-র যাচাইকরণের উত্তর দেয়। Meta পাঠায় hub.mode, hub.verify_token ও hub.challenge, কিন্তু PHP আসা ভেরিয়েবলের নামে ডটকে আন্ডারস্কোরে বদলে দেয়, তাই Laravel দেখে hub_mode, hub_verify_token ও hub_challenge। ডট দেওয়া নাম পড়লে null পাওয়া যায় এবং যাচাইকরণ কখনো সম্পন্ন হয় না। চ্যালেঞ্জটি প্লেইন টেক্সট হিসেবে ফেরত দিন, response()->json() দিয়ে নয়।

POST রুট পেলোডটি একটি কিউ জবে দেয় এবং সঙ্গে সঙ্গে 200 ফেরত দেয়। পাথে একটি লম্বা র‍্যান্ডম কী রাখুন এবং দুই রুটেই সেটি যাচাই করুন। Meta ডেলিভারিতে Tech Provider-এর অ্যাপ সিক্রেট দিয়ে সই করে, তাই সিগনেচার হেডার আপনার দিকে যাচাই করা যায় না।

routes/api.php: verification and event intake
use App\Jobs\HandleWhatsAppEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('/whatsapp/{key}', function (Request $request, string $key) {
    abort_unless(hash_equals(config('services.whatsapp.url_key'), $key), 404);

    // PHP turns hub.mode into hub_mode: read the underscored names
    if ($request->query('hub_mode') === 'subscribe'
        && hash_equals(config('services.whatsapp.verify_token'),
                       (string) $request->query('hub_verify_token'))) {
        return response((string) $request->query('hub_challenge'), 200)
            ->header('Content-Type', 'text/plain');
    }

    abort(403);
});

Route::post('/whatsapp/{key}', function (Request $request, string $key) {
    abort_unless(hash_equals(config('services.whatsapp.url_key'), $key), 404);

    HandleWhatsAppEvent::dispatch($request->json()->all());

    return response('', 200);
});

Laravel থেকে কীভাবে WhatsApp মেসেজ পাঠাবেন?

Laravel-এর HTTP ক্লায়েন্ট দিয়ে: ফোন নম্বর আইডির মেসেজ এন্ডপয়েন্টে একটি POST, সঙ্গে অ্যাক্সেস টোকেন বেয়ারার টোকেন হিসেবে। দুটি মান আসে সংযোগ থেকে, ড্যাশবোর্ডে দেখা যায় এবং get_api_credentials ফেরত দেয়। এগুলো কোডে না রেখে এনভায়রনমেন্ট ভেরিয়েবলের ভিত্তিতে config/services.php-তে রাখুন।

বডির গঠন নির্ভর করে সময়ের ওপর। গ্রাহকের শেষ মেসেজের 24 ঘণ্টার মধ্যে নিচের মতো `text` অবজেক্ট কাজ করে। সেই সময়ের বাইরে Meta শুধু অনুমোদিত টেমপ্লেটের নাম ও ভাষা দেওয়া টেমপ্লেট অবজেক্ট গ্রহণ করে, আর ফ্রি টেক্সট 131047 ত্রুটি দিয়ে ব্যর্থ হয়। প্রতিক্রিয়াতেই তা দেখা যায়: ব্যর্থ কলে একটি ত্রুটি অবজেক্ট আসে, যার code বলে কী ভুল হয়েছে, তাই সেটি ফেলে না দিয়ে লগ করুন।

অনুরোধের কোনো অংশই EasyCoexistence-এর জন্য আলাদা নয়। এটি Meta-র নিজস্ব ডকুমেন্টেশনের কলই, তাই Guzzle বা সাধারণ cURL সহ যেকোনো PHP HTTP ক্লায়েন্টে একইভাবে কাজ করে।

Send a text reply inside the 24 hour window
use Illuminate\Support\Facades\Http;

$response = Http::withToken(config('services.whatsapp.token'))
    ->post('https://graph.facebook.com/v25.0/'
        . config('services.whatsapp.phone_number_id') . '/messages', [
        'messaging_product' => 'whatsapp',
        'to' => '14155550188', // digits only, with country code
        'type' => 'text',
        'text' => ['body' => 'Thanks, we are on it.'],
    ]);

if ($response->failed()) {
    // error.code 131047: outside the window, send a template instead
    logger()->warning('WhatsApp send failed', $response->json('error', []));
}

প্রোডাকশনের Laravel হ্যান্ডলারে এর বাইরে আর কী লাগে?

একটি আসল কিউ, ডুপ্লিকেট প্রতিরোধ এবং 24 ঘণ্টার সময়সীমা যাচাই।

কিউ জরুরি, কারণ Meta ধীর প্রতিক্রিয়া পেলে আবার পাঠায়। HandleWhatsAppEvent::dispatch() দ্রুত ফেরত আসে কেবল তখন, যখন কিউ কানেকশন আসল এবং একটি ওয়ার্কার চলছে। `sync` ড্রাইভারে জব অনুরোধের ভেতরেই চলে, আর একটি ধীর মডেল কল বা ডেটাবেসে লেখা ডুপ্লিকেট ডেলিভারিতে পরিণত হয়।

মেসেজ আইডি, অর্থাৎ প্রতিটি মেসেজের wamid, ধরে ডুপ্লিকেট বাদ দিন, কারণ পুনরায় পাঠানো ব্যতিক্রম নয়, স্বাভাবিক ঘটনা। ওই কলামে একটি ইউনিক ইনডেক্স, অথবা সেটির ওপর ভিত্তি করা ক্যাশ লকই যথেষ্ট।

আর প্রতিটি কন্টাক্ট শেষ কখন লিখেছে তা সংরক্ষণ করুন। এই টাইমস্ট্যাম্প থাকলে পাঠানোর অংশ নিজেই টেক্সট বা টেমপ্লেট বেছে নেয়, গ্রাহক অপেক্ষা করার পর 131047 ত্রুটি থেকে জানতে হয় না। WhatsApp Business অ্যাপে ফোন থেকে লেখা উত্তর একই রুটে ইকো ইভেন্ট হিসেবে আসে, তাই হ্যান্ডলার বুঝতে পারে কখন কোনো ব্যক্তি কথোপকথন নিজের হাতে নিয়েছেন।

সাধারণ ভুলগুলো

  • hub.challenge ডট দিয়ে পড়া। PHP নামটি বদলে hub_challenge করে দিয়েছে, তাই হ্যান্ডলার খালি বডি ফেরত দেয় এবং Meta কখনো যাচাই করে না।
  • ওয়েবহুককে routes/web.php-তে রাখা। Meta-র POST-এ CSRF টোকেন থাকে না, তাই 419 দিয়ে বাতিল হয়।
  • `sync` কিউতে ডিসপ্যাচ করা। জব 200 ফেরত দেওয়ার আগেই চলে, ধীর প্রক্রিয়াকরণ আবার পাঠানো হয় এবং মেসেজ দুবার প্রক্রিয়া হয়।
  • response()->json() দিয়ে চ্যালেঞ্জ ফেরত দেওয়া। মানের চারপাশের উদ্ধৃতি চিহ্ন Meta-র যাচাইকরণ ব্যর্থ করে।
EasyCoexistence দিয়ে এটি করা

easycoexistence.com-এ নম্বরটি সংযুক্ত করুন, ওয়েবহুকের গন্তব্য হিসেবে পাথে কী সহ আপনার Laravel রুট দিন, এবং ড্যাশবোর্ড থেকে ফোন নম্বর আইডি ও টোকেন নিন। প্রতি নম্বরে মাসে US$ 9 থেকে শুরু, নম্বর বাড়ার সঙ্গে সঙ্গে US$ 1 পর্যন্ত নেমে আসে, প্রথম 3 দিন ফ্রি।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

PHP SDK আছে কি?

আমাদের পক্ষ থেকে নেই, আর দরকারও নেই। API Meta-র, ডকুমেন্টেশনও Meta-র, এবং Laravel-এর HTTP ক্লায়েন্ট বা Guzzle সরাসরি সেটি ব্যবহার করতে পারে।

Laravel ছাড়া কি এটি কাজ করে?

হ্যাঁ। সাধারণ PHP-তে $_GET['hub_challenge'] পড়ুন, text/plain হিসেবে echo করুন এবং cURL দিয়ে পাঠান। আন্ডারস্কোরের নিয়ম PHP-র সব ফ্রেমওয়ার্কে প্রযোজ্য।

URL-এর পাথে কেন একটি কী লাগে?

কারণ এটিই একমাত্র কার্যকর প্রমাণীকরণ। Meta-র সিগনেচার Tech Provider-এর অ্যাপ সিক্রেট ব্যবহার করে, যা কখনো শেয়ার করা হয় না, তাই URL-এর গোপন কী-ই অপরিচিতদের নকল ইভেন্ট পোস্ট করা ঠেকায়।

টিম কি এখনো ফোন ব্যবহার করতে পারবে?

হ্যাঁ। Coexistence নম্বরটিতে WhatsApp Business অ্যাপ চালু রাখে, এবং ফোন থেকে পাঠানো মেসেজ আপনার রুটে ইকো ইভেন্ট হিসেবে পৌঁছায়।

আরও পড়ুন

শুরু করতে প্রস্তুত?

মাস নয়, কয়েক মিনিটেই WhatsApp Coexistence সেট আপ করুন। ফোনে অ্যাপটি কাজ করতে থাকে।

ফ্রি ট্রায়াল শুরু করুন

যাচাই করা হয়েছে

PHP ও Laravel থেকে WhatsApp মেসেজ পাঠান