Prijavite seZapočnite besplatno probno razdoblje
Meta Tech Provider

Slanje i primanje WhatsApp poruka iz PHP-a i Laravela

Primanje je Laravel ruta koja odgovara na Metin GET za provjeru i prihvaća POST zahtjeve, a parametre čita kao hub_mode, hub_verify_token i hub_challenge jer PHP pretvara točke u podcrte. Slanje je jedan POST zahtjev preko Http::withToken() na messages endpoint Cloud API-ja, s phone number id-jem i tokenom broja. SDK nije potreban.

hub_challenge

PHP pretvara točke u nazivima dolaznih varijabli u podcrte, pa se hub.challenge čita kao hub_challenge.

routes/api.php

Laravelove API rute bez stanja, koje stvara install:api, poslužuju se pod /api i izvan CSRF zaštite web grupe.

v25.0

Verzija Graph API-ja iz Metinih aktualnih primjera slanja poruka, na POST /{phone-number-id}/messages.

Kako primati WhatsApp poruke u Laravelu?

Pomoću jedne GET i jedne POST rute na istoj putanji u routes/api.php. Ako ta datoteka ne postoji, prvo pokrenite php artisan install:api. API rute nemaju stanje i izvan su web grupe, pa se Metin POST ne odbija zbog nedostajućeg CSRF tokena, što se događa na ruti u routes/web.php.

GET odgovara na Metinu provjeru. Meta šalje hub.mode, hub.verify_token i hub.challenge, ali PHP u nazivima dolaznih varijabli zamjenjuje točke podcrtama, pa Laravel vidi hub_mode, hub_verify_token i hub_challenge. Kôd koji čita nazive s točkama dobiva null i nikad ne prođe provjeru. Challenge vratite kao običan tekst, ne preko response()->json().

POST predaje payload zadatku u redu čekanja i odmah vraća 200. Stavite dugačak nasumičan ključ u putanju i provjeravajte ga na obje rute: Meta potpisuje isporuke tajnim ključem aplikacije Tech Providera, pa se zaglavlje potpisa na vašoj strani ne može validirati.

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);
});

Kako poslati WhatsApp poruku iz Laravela?

Laravelovim HTTP klijentom: jedan POST na messages endpoint za phone number id, s pristupnim tokenom kao bearer tokenom. Obje vrijednosti dolaze iz veze, prikazane su na nadzornoj ploči i vraća ih get_api_credentials, a pripadaju u config/services.php uz varijable okruženja, a ne u kôd.

Oblik tijela zahtjeva ovisi o vremenu. Unutar 24 sata od zadnje poruke klijenta radi objekt text, kao u nastavku. Izvan tog razdoblja Meta prihvaća samo objekt template s imenom odobrenog predloška i njegovim jezikom, a slobodan tekst pada s pogreškom 131047. Odgovor je mjesto na kojem to vidite: neuspjeli poziv vraća objekt error čiji kôd govori što je pošlo po zlu, pa ga zapišite u zapisnik umjesto da ga odbacite.

Niti jedan dio zahtjeva nije specifičan za EasyCoexistence. To je poziv iz Metine vlastite dokumentacije, pa svaki PHP HTTP klijent, Guzzle ili običan cURL, radi na isti način.

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', []));
}

Što produkcijskom Laravel rukovatelju treba povrh toga?

Pravi red čekanja, deduplikacija i provjera razdoblja.

Red čekanja je važan jer Meta ponavlja isporuku ako je odgovor spor. HandleWhatsAppEvent::dispatch() brzo vraća odgovor samo kad je veza reda čekanja prava i kad radi worker. Na sync driveru zadatak se izvršava unutar zahtjeva, a spor poziv modela ili upis u bazu pretvara se u dvostruku isporuku.

Deduplicirajte prema id-ju poruke, odnosno wamid-u u svakoj poruci, jer su ponovljene isporuke uobičajene, a ne iznimne. Dovoljan je jedinstveni indeks na tom stupcu ili cache lock s njim kao ključem.

I spremite kad je koji kontakt zadnji put pisao. S tom vremenskom oznakom put slanja sam bira tekst ili predložak, umjesto da to saznate iz pogreške 131047 kad klijent već čeka. Odgovori otipkani na telefonu u aplikaciji WhatsApp Business stižu kao echo događaji na istu rutu, pa rukovatelj može vidjeti i kad je osoba preuzela razgovor.

Uobičajene pogreške

  • Čitanje hub.challenge s točkom. PHP ga je preimenovao u hub_challenge, pa rukovatelj vraća prazno tijelo i Meta nikad ne potvrdi provjeru.
  • Stavljanje webhooka u routes/web.php. Metin POST nema CSRF token i odbija se s kôdom 419.
  • Slanje zadataka u sync red. Zadatak se izvršava prije odgovora 200, spora obrada se ponavlja, a poruke se obrade dvaput.
  • Vraćanje challengea preko response()->json(). Navodnici oko vrijednosti ne prolaze Metinu provjeru.
Radite ovo uz EasyCoexistence

Povežite broj na easycoexistence.com, postavite odredište webhooka na svoju Laravel rutu s ključem u putanji i očitajte phone number id i token s nadzorne ploče. Od US$ 9 po broju mjesečno, uz pad na US$ 1 kako dodajete brojeve, a prva 3 dana su besplatna.

Često postavljana pitanja

Postoji li PHP SDK?

Od nas ne, a nije ni potreban. API je Metin i Meta ga dokumentira, a Laravelov HTTP klijent ili Guzzle dosežu ga izravno.

Radi li ovo bez Laravela?

Da. U običnom PHP-u pročitajte $_GET['hub_challenge'], ispišite ga kao text/plain i šaljite preko cURL-a. Pravilo o podcrtama vrijedi za svaki PHP framework.

Zašto URL treba ključ u putanji?

Zato što je to autentifikacija koja funkcionira. Metin potpis koristi tajni ključ aplikacije Tech Providera, koji se nikad ne dijeli, pa tajna u URL-u sprječava da stranci šalju lažne događaje.

Može li tim i dalje koristiti telefon?

Da. Coexistence održava aplikaciju WhatsApp Business aktivnom na broju, a poruke poslane s telefona stižu na vašu rutu kao echo događaji.

Nastavite čitati

Spremni za početak?

Postavite WhatsApp Coexistence u nekoliko minuta, a ne mjeseci. Aplikacija i dalje radi na telefonu.

Započnite besplatno probno razdoblje

Provjereno na

WhatsApp poruke iz PHP-a i Laravela