Log masukMulakan percubaan percuma
Meta Tech Provider

Hantar dan terima WhatsApp dari PHP dan Laravel

Penerimaan ialah route Laravel yang menjawab GET pengesahan Meta dan menerima POST, dengan parameter dibaca sebagai hub_mode, hub_verify_token dan hub_challenge kerana PHP menukar titik kepada garis bawah. Penghantaran ialah satu POST Http::withToken() ke endpoint mesej Cloud API bersama phone number id dan token nombor itu. Tiada SDK diperlukan.

hub_challenge

PHP menukar titik dalam nama pemboleh ubah masuk kepada garis bawah, jadi hub.challenge dibaca sebagai hub_challenge.

routes/api.php

Route API Laravel yang tanpa keadaan, dicipta oleh install:api, disajikan di bawah /api dan di luar perlindungan CSRF kumpulan web.

v25.0

Versi Graph API dalam contoh hantar mesej semasa Meta, pada POST /{phone-number-id}/messages.

Bagaimana anda menerima mesej WhatsApp dalam Laravel?

Dengan satu GET dan satu POST pada laluan yang sama dalam routes/api.php. Jalankan php artisan install:api dahulu jika fail itu belum wujud. Route API tidak mempunyai keadaan dan berada di luar kumpulan web, jadi POST daripada Meta tidak ditolak kerana token CSRF tiada, yang berlaku pada route dalam routes/web.php.

GET menjawab pengesahan Meta. Meta menghantar hub.mode, hub.verify_token dan hub.challenge, tetapi PHP menulis semula titik dalam nama pemboleh ubah masuk kepada garis bawah, jadi Laravel melihat hub_mode, hub_verify_token dan hub_challenge. Kod yang membaca nama bertitik mendapat null dan tidak pernah mengesahkan. Pulangkan challenge sebagai teks biasa, bukan melalui response()->json().

POST menyerahkan payload kepada job beratur dan memulangkan 200 serta-merta. Letakkan kunci rawak yang panjang dalam laluan dan semaknya pada kedua-dua route: Meta menandatangani penghantaran dengan app secret Tech Provider, jadi pengepala tandatangan tidak boleh disahkan di pihak anda.

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

Bagaimana anda menghantar mesej WhatsApp dari Laravel?

Dengan klien HTTP Laravel: satu POST ke endpoint mesej untuk phone number id, dengan access token sebagai bearer token. Kedua-dua nilai datang daripada sambungan, dipaparkan dalam dashboard dan dipulangkan oleh get_api_credentials, dan patut diletakkan dalam config/services.php yang disandarkan pada pemboleh ubah persekitaran, bukan dalam kod.

Bentuk badan permintaan bergantung pada masa. Dalam tempoh 24 jam selepas mesej terakhir pelanggan, objek text boleh digunakan, seperti di bawah. Di luar tetingkap itu Meta hanya menerima objek template yang menamakan template yang diluluskan beserta bahasanya, dan teks bebas gagal dengan ralat 131047. Respons ialah tempat untuk melihatnya: panggilan yang gagal memulangkan objek ralat yang kodnya menerangkan apa yang tidak kena, jadi lognya dan jangan dibuang.

Tiada apa-apa dalam permintaan ini khusus kepada EasyCoexistence. Ia ialah panggilan dalam dokumentasi Meta sendiri, jadi mana-mana klien HTTP PHP, Guzzle atau cURL biasa, berfungsi dengan cara yang sama.

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

Apa lagi yang diperlukan oleh pengendali Laravel pengeluaran?

Baris gilir sebenar, penyahduplikasian dan semakan tetingkap.

Baris gilir penting kerana Meta mencuba semula respons yang perlahan. HandleWhatsAppEvent::dispatch() hanya kembali dengan pantas apabila sambungan baris gilir ialah sambungan sebenar dengan worker yang sedang berjalan. Pada pemacu sync, job berjalan di dalam permintaan, dan panggilan model atau penulisan pangkalan data yang perlahan menjadi penghantaran berganda.

Nyahduplikasi pada id mesej, iaitu wamid dalam setiap mesej, kerana percubaan semula itu perkara biasa dan bukan pengecualian. Indeks unik pada lajur itu, atau kunci cache berdasarkannya, sudah memadai.

Dan simpan masa setiap kenalan menulis kali terakhir. Dengan cap masa itu, laluan penghantaran memilih text atau template dengan sendirinya, bukannya mengetahuinya daripada ralat 131047 selepas pelanggan sudah menunggu. Balasan yang ditaip pada telefon dalam aplikasi WhatsApp Business tiba sebagai peristiwa echo pada route yang sama, jadi pengendali juga dapat melihat bila seseorang telah mengambil alih perbualan.

Kesilapan biasa

  • Membaca hub.challenge dengan titik. PHP menamakannya semula sebagai hub_challenge, jadi pengendali memulangkan badan kosong dan Meta tidak pernah mengesahkan.
  • Meletakkan webhook dalam routes/web.php. POST daripada Meta tiada token CSRF dan ditolak dengan 419.
  • Menghantar ke baris gilir sync. Job berjalan sebelum 200, pengendalian yang perlahan dicuba semula, dan mesej diproses dua kali.
  • Memulangkan challenge dengan response()->json(). Tanda petikan di sekeliling nilai itu menggagalkan semakan Meta.
Menggunakan EasyCoexistence untuk ini

Sambungkan nombor anda di easycoexistence.com, tetapkan destinasi webhook kepada route Laravel anda dengan kuncinya dalam laluan, dan baca phone number id serta token daripada dashboard. Daripada US$ 9 sebulan bagi setiap nombor, jatuh kepada US$ 1 apabila anda menambah nombor, dengan 3 hari pertama percuma.

Soalan lazim

Adakah terdapat SDK PHP?

Bukan daripada kami, dan tiada yang diperlukan. API itu milik Meta, didokumenkan oleh Meta, dan klien HTTP Laravel atau Guzzle boleh mencapainya secara terus.

Adakah ini berfungsi tanpa Laravel?

Ya. Dalam PHP biasa, baca $_GET['hub_challenge'], paparkannya sebagai text/plain, dan hantar dengan cURL. Peraturan garis bawah terpakai pada setiap rangka kerja PHP.

Mengapa URL memerlukan kunci dalam laluan?

Kerana itulah pengesahan yang berfungsi. Tandatangan Meta menggunakan app secret Tech Provider, yang tidak pernah dikongsi, jadi rahsia URL itulah yang menghalang orang luar menghantar peristiwa palsu.

Bolehkah pasukan masih menggunakan telefon?

Ya. Coexistence mengekalkan aplikasi WhatsApp Business berfungsi pada nombor itu, dan mesej yang dihantar dari telefon sampai ke route anda sebagai peristiwa echo.

Teruskan membaca

Sedia untuk bermula?

Sediakan WhatsApp Coexistence dalam beberapa minit, bukan berbulan-bulan. Aplikasi terus berfungsi pada telefon.

Mulakan Percubaan Percuma

Disahkan pada

Hantar WhatsApp dari PHP dan Laravel