Trimiteți și primiți WhatsApp din PHP și Laravel
Primirea înseamnă o rută Laravel care răspunde la GET-ul de verificare al Meta și acceptă POST-uri, citind parametrii ca hub_mode, hub_verify_token și hub_challenge, pentru că PHP transformă punctele în caractere de subliniere. Trimiterea este un singur POST prin Http::withToken() către endpoint-ul de mesaje din Cloud API, cu phone number id și token-ul numărului. Nu este nevoie de niciun SDK.
PHP convertește punctele din numele variabilelor primite în caractere de subliniere, așa că hub.challenge se citește ca hub_challenge.
Rutele API fără stare din Laravel, create de install:api, sunt servite sub /api și în afara protecției CSRF a grupului web.
Versiunea Graph API din exemplele actuale Meta pentru trimiterea mesajelor, la POST /{phone-number-id}/messages.
Cum primiți mesaje WhatsApp în Laravel?
Cu un GET și un POST pe aceeași cale în routes/api.php. Rulați mai întâi php artisan install:api dacă fișierul nu există. Rutele API nu au stare și sunt în afara grupului web, deci POST-ul Meta nu este respins pentru lipsa unui token CSRF, cum se întâmplă pe o rută din routes/web.php.
GET-ul răspunde la verificarea Meta. Meta trimite hub.mode, hub.verify_token și hub.challenge, dar PHP rescrie punctele din numele variabilelor primite în caractere de subliniere, deci Laravel vede hub_mode, hub_verify_token și hub_challenge. Codul care citește numele cu punct primește null și nu se verifică niciodată. Returnați challenge-ul ca text simplu, nu prin response()->json().
POST-ul trimite payload-ul către un job din coadă și returnează 200 imediat. Puneți o cheie lungă și aleatorie în cale și verificați-o pe ambele rute: Meta semnează livrările cu app secret-ul Tech Provider-ului, deci antetul de semnătură nu poate fi validat de partea dumneavoastră.
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);
});Cum trimiteți un mesaj WhatsApp din Laravel?
Cu clientul HTTP din Laravel: un singur POST către endpoint-ul de mesaje pentru phone number id, cu token-ul de acces ca token bearer. Ambele valori vin din conexiune, apar în dashboard și sunt returnate de get_api_credentials, iar locul lor este în config/services.php, pe baza variabilelor de mediu, nu în cod.
Forma corpului depinde de moment. În 24 de ore de la ultimul mesaj al clientului funcționează un obiect text, ca mai jos. În afara acestei ferestre, Meta acceptă doar un obiect template care indică un template aprobat și limba lui, iar textul liber eșuează cu eroarea 131047. Răspunsul este locul unde se vede: un apel eșuat returnează un obiect error al cărui code spune ce a mers prost, deci înregistrați-l în log în loc să-l ignorați.
Nimic din cerere nu este specific EasyCoexistence. Este apelul din documentația Meta, așa că orice client HTTP pentru PHP, Guzzle sau cURL simplu, funcționează la fel.
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', []));
}Ce mai are nevoie un handler Laravel de producție?
O coadă reală, deduplicare și o verificare a ferestrei.
Coada contează pentru că Meta reîncearcă la un răspuns lent. HandleWhatsAppEvent::dispatch() revine rapid doar când conexiunea cozii este una reală, cu un worker pornit. Pe driverul sync, job-ul rulează în interiorul cererii, iar un apel lent la un model sau o scriere în baza de date se transformă într-o livrare dublă.
Deduplicați după id-ul mesajului, wamid-ul din fiecare mesaj, pentru că reîncercările sunt normale, nu excepții. Un index unic pe acea coloană sau un lock în cache cu aceeași cheie este suficient.
Și salvați momentul în care a scris fiecare contact ultima dată. Cu acel timestamp, calea de trimitere alege singură între text și template, în loc să afle din eroarea 131047 după ce clientul a așteptat deja. Răspunsurile scrise de pe telefon în aplicația WhatsApp Business ajung ca evenimente echo pe aceeași rută, deci handler-ul poate vedea și când o persoană a preluat o conversație.
Greșeli frecvente
- Citirea hub.challenge cu punct. PHP l-a redenumit hub_challenge, deci handler-ul returnează un corp gol, iar Meta nu verifică niciodată webhook-ul.
- Punerea webhook-ului în routes/web.php. POST-ul Meta nu are token CSRF și este respins cu 419.
- Trimiterea în coada sync. Job-ul rulează înainte de 200, procesarea lentă este reîncercată, iar mesajele sunt procesate de două ori.
- Returnarea challenge-ului cu response()->json(). Ghilimelele din jurul valorii pică verificarea Meta.
Conectați numărul pe easycoexistence.com, setați destinația webhook-ului la ruta dumneavoastră Laravel, cu cheia în cale, și citiți phone number id și token-ul din dashboard. De la US$ 9 pe număr pe lună, ajungând la US$ 1 pe măsură ce adăugați numere, cu primele 3 zile gratuite.
Întrebări frecvente
Există un SDK PHP?
Nu de la noi și nu este nevoie de unul. API-ul este al Meta, documentat de Meta, iar clientul HTTP din Laravel sau Guzzle îl accesează direct.
Funcționează fără Laravel?
Da. În PHP simplu citiți $_GET['hub_challenge'], afișați-l ca text/plain și trimiteți cu cURL. Regula caracterelor de subliniere se aplică oricărui framework PHP.
De ce are nevoie URL-ul de o cheie în cale?
Pentru că este autentificarea care funcționează. Semnătura Meta folosește app secret-ul Tech Provider-ului, care nu este niciodată partajat, deci secretul din URL este cel care împiedică străinii să trimită evenimente false.
Poate echipa să folosească în continuare telefonul?
Da. Coexistence păstrează aplicația WhatsApp Business funcțională pe număr, iar mesajele trimise de pe telefon ajung la ruta dumneavoastră ca evenimente echo.
Continuați să citiți
Gata să începeți?
Configurați WhatsApp Coexistence în câteva minute, nu luni. Aplicația continuă să funcționeze pe telefon.
Începeți perioada de probă gratuităVerificat la