Slanje i prijem WhatsApp poruka iz PHP-a i Laravela
Prijem je Laravel ruta koja odgovara na Metin verifikacioni GET i prihvata POST zahteve, a parametre čita kao hub_mode, hub_verify_token i hub_challenge, jer PHP pretvara tačke u donje crte. Slanje je jedan Http::withToken() POST na Cloud API endpoint za poruke, sa phone number id i tokenom broja. SDK nije potreban.
PHP pretvara tačke u imenima dolaznih promenljivih u donje crte, pa se hub.challenge čita kao hub_challenge.
Laravelove API rute bez stanja, koje kreira install:api, služe se pod /api i van CSRF zaštite web grupe.
Verzija Graph API-ja iz Metinih aktuelnih primera slanja poruke, na POST /{phone-number-id}/messages.
Kako se primaju WhatsApp poruke u Laravelu?
Pomoću jednog GET i jednog POST na istoj putanji u routes/api.php. Ako fajl ne postoji, prvo pokrenite php artisan install:api. API rute nemaju stanje i nisu u web grupi, pa se Metin POST ne odbija zbog nedostajućeg CSRF tokena, što se dešava na ruti u routes/web.php.
GET odgovara na Metinu verifikaciju. Meta šalje hub.mode, hub.verify_token i hub.challenge, ali PHP u imenima dolaznih promenljivih menja tačke donjim crtama, pa Laravel vidi hub_mode, hub_verify_token i hub_challenge. Kod koji čita imena sa tačkom dobija null i nikada ne verifikuje. Challenge vratite kao običan tekst, a ne preko response()->json().
POST prosleđuje payload job-u u redu čekanja i odmah vraća 200. Stavite dug nasumičan ključ u putanju i proverite ga na obe rute: Meta potpisuje isporuke app secretom Tech Providera, pa zaglavlje sa potpisom ne možete sami da proverite.
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);
});Kako se šalje WhatsApp poruka iz Laravela?
Laravelovim HTTP klijentom: jedan POST na endpoint za poruke za dati phone number id, sa pristupnim tokenom kao Bearer tokenom. Obe vrednosti dolaze iz povezivanja, vidljive su u kontrolnoj tabli i vraća ih get_api_credentials, a pripadaju u config/services.php, uz promenljive okruženja, a ne u kod.
Oblik tela zavisi od vremena. U roku od 24 sata od poslednje poruke klijenta radi text objekat, kao ispod. Van tog prozora Meta prihvata samo template objekat sa odobrenim šablonom i njegovim jezikom, a slobodan tekst pada sa greškom 131047. Odgovor je mesto gde se to vidi: neuspeli poziv vraća objekat greške čiji kod govori šta nije u redu, pa ga zapišite u log umesto da ga odbacite.
Ništa u zahtevu nije specifično za EasyCoexistence. To je poziv iz Metine dokumentacije, pa svaki PHP HTTP klijent, Guzzle ili običan cURL, radi na isti način.
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', []));
}Šta produkcioni Laravel handler treba pored toga?
Pravi red čekanja, deduplikaciju i proveru prozora.
Red čekanja je bitan jer Meta ponavlja isporuku kada odgovor kasni. HandleWhatsAppEvent::dispatch() se brzo vraća samo kada je konekcija reda prava i radi worker. Na sync drajveru job se izvršava unutar zahteva, a spor poziv modela ili upis u bazu pretvara se u dupliranu isporuku.
Deduplikujte po id-ju poruke, wamid iz svake poruke, jer su ponavljanja normalna, a ne izuzetak. Dovoljan je unique indeks na toj koloni ili cache lock sa tim ključem.
I čuvajte kada je svaki kontakt poslednji put pisao. Uz taj vremenski žig putanja slanja sama bira tekst ili šablon, umesto da to sazna iz greške 131047 kada klijent već čeka. Odgovori otkucani na telefonu u aplikaciji WhatsApp Business stižu kao echo događaji na istoj ruti, pa handler može da vidi i kada je čovek preuzeo razgovor.
Česte greške
- Čitanje hub.challenge sa tačkom. PHP ga je preimenovao u hub_challenge, pa handler vraća prazno telo i Meta nikada ne verifikuje.
- Webhook u routes/web.php. Metin POST nema CSRF token i odbija se sa 419.
- Slanje u sync red. Job se izvršava pre 200, spora obrada se ponavlja i poruke se obrađuju dvaput.
- Vraćanje challenge-a preko response()->json(). Navodnici oko vrednosti ruše Metinu proveru.
Povežite broj na easycoexistence.com, podesite odredište webhooka na vašu Laravel rutu sa ključem u putanji i pročitajte phone number id i token iz kontrolne table. Od US$ 9 po broju mesečno, do US$ 1 kako dodajete brojeve, a prva 3 dana su besplatna.
Često postavljana pitanja
Postoji li PHP SDK?
Ne od nas, i nije potreban. API je Metin, dokumentovan od Mete, a Laravelov HTTP klijent ili Guzzle dopiru do njega direktno.
Radi li ovo bez Laravela?
Da. U čistom PHP-u pročitajte $_GET['hub_challenge'], vratite ga kao text/plain i šaljite preko cURL-a. Pravilo o donjim crtama važi za svaki PHP framework.
Zašto URL treba ključ u putanji?
Zato što je to autentifikacija koja zaista radi. Metin potpis koristi app secret Tech Providera koji se nikada ne deli, pa tajna u URL-u sprečava da nepoznati šalju lažne događaje.
Može li tim i dalje da koristi telefon?
Da. Coexistence održava aplikaciju WhatsApp Business aktivnom na broju, a poruke poslate sa telefona stižu na vašu rutu kao echo događaji.
Nastavite sa čitanjem
Spremni da počnete?
Podesite WhatsApp Coexistence za nekoliko minuta, a ne meseci. Aplikacija nastavlja da radi na telefonu.
Započnite besplatni probni periodProvereno na