Sende WhatsApp-Benachrichtigungen mit Laravel

November 22, 2019
Autor:in:
Chimezie Enyinnaya
Mitwirkende:r
Die von Twilio-Mitwirkenden geäußerten Meinungen sind ihre eigenen

Laravel Notifications

Laravel erleichtert das Senden von Benachrichtigungen in Ihrer PHP-Anwendung. Es bietet vorkonfigurierte Unterstützung für Kanäle wie E-Mail, SMS, Slack und Datenbank. Doch was, wenn wir Benachrichtigungen an andere Kanäle als diese senden wollen, z. B. WhatsApp? In diesem Tutorial zeige ich, wie Sie mit der Twilio-API WhatsApp-Benachrichtigungen in Ihre Laravel-App implementieren können.

Tools zur Durchführung dieses Tutorials

Sie benötigen folgende Tools, um dieses Tutorial zu absolvieren:

Was wir bauen werden

Wir verwenden für dieses Tutorial das Konzept eines Bestellsystems. Zur Vereinfachung entwickeln wir kein vollwertiges Bestellsystem, sondern lediglich den Teil, der Benachrichtigungen sendet.

Erstellen einer neuen Laravel-Anwendung

Wir erstellen zunächst eine neue Laravel-Anwendung. Dazu benötigen wir das oben erwähnte Laravel-Installationsprogramm. Führen Sie den folgenden Befehl in Ihrer Konsole aus:

$ laravel new laravel-whatsapp-notification
$ cd laravel-whatsapp-notification

Nachdem die Anwendung erstellt wurde, müssen wir die NPM-Abhängigkeiten installieren (weil Bootstrap als NPM-Abhängigkeit enthalten ist):

$ npm install

Führen Sie nach der Installation aller Abhängigkeiten diesen Befehl aus:

$ npm run dev

Hinzufügen der Authentifizierung

Als Nächstes fügen wir eine Authentifizierung hinzu. Ab Laravel 6 ist das Authentifizierungs-Scaffolding in einem separaten Paket enthalten. Wir müssen dieses zusammen mit Composer installieren:

$ composer require laravel/ui –dev

Anschließend können wir den Befehl für das Authentifizierungs-Scaffolding ausführen:

$ php artisan ui vue –auth

Da WhatsApp Telefonnummern nutzt, müssen wir die Telefonnummern von Nutzern in unserer Anwendung speichern. Wir erreichen dies beispielsweise durch Erfassen der Telefonnummern bei der Registrierung der Nutzer. Zunächst ergänzen wir das Registrierungsformular um ein Feld für die Telefonnummer. Fügen Sie direkt nach dem E-Mail-Adressfeld den folgenden Code register.blade.php ein:

// resources/views/auth/register.blade.php

<div class="form-group row">
  <label for="phone_number" class="col-md-4 col-form-label text-md-right">{{ __('Phone Number') }}</label>
  <div class="col-md-6">
    <input id="phone_number" type="text" class="form-control @error('phone_number') is-invalid @enderror" name="phone_number" value="{{ old('phone_number') }}" required autocomplete="phone_number">
    @error('phone_number')
      <span class="invalid-feedback" role="alert">
        <strong>{{ $message }}</strong>
      </span>
    @enderror
  </div>
</div>

Hinweis: Die Telefonnummern der Nutzer müssen im E.164.-Format vorliegen.

Laravel registration form

Als Nächstes aktualisieren wir sowohl die validator()- als auch die  create()-Methode des RegisterController, wie nachfolgend gezeigt:

// app/Http/Controllers/Auth/RegisterController.php

protected function validator(array $data)
{
  return Validator::make($data, [
    'name' => ['required', 'string', 'max:255'],
    'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
    'phone_number' => ['required', 'string', 'unique:users'],
    'password' => ['required', 'string', 'min:8', 'confirmed'],
  ]);
}


protected function create(array $data)
{
  return User::create([
    'name' => $data['name'],
    'email' => $data['email'],
    'phone_number' => $data['phone_number'],
    'password' => Hash::make($data['password']),
  ]);
}

Wir haben dem Telefonnummernfeld einige Validierungsregeln hinzugefügt. Die Telefonnummer wird zusammen mit den anderen erfassten Daten in der Datenbank gespeichert.

Abschließend fügen wir das Telefonnummernfeld der Liste der Felder zu, für die innerhalb des Modells User (Nutzer) eine Massenzuweisung vorgenommen werden kann:

// app/User.php

protected $fillable = [
  'name', 'email', 'password', 'phone_number'
];

Erstellen der Modelle und Migrationen

Wir müssen außerdem die Migrationsdatei für die Benutzertabelle aktualisieren, die im Lieferumfang der Standard-Laravel-Anwendung enthalten ist. Dazu müssen wir ein neues Feld für die Telefonnummer hinzufügen:

// database/migrations/2014_10_12_000000_create_users_table.php

$table->string('phone_number')->unique();

Danach erstellen wir ein Modell des Typs Order (Bestellung) einschließlich der zugehörigen Migrationsdatei:

$ php artisan make:model Order –m

Die Migrationsdatei aktualisieren wir dann wie folgt:

// database/migrations/2019_11_14_123551_create_orders_table.php

Schema::create('orders', function (Blueprint $table) {
  $table->bigIncrements('id');
  $table->string('name');
  $table->integer('amount');
  $table->timestamps();
});

Damit das Ganze nicht zu kompliziert wird, enthält die Tabelle orders (Bestellungen) nur die Felder „id“ (Kennung), „name“ und „amount“ (Betrag) sowie die Zeitstempel.

Bevor wir die Migration starten, müssen wir die Datenbank einrichten. Der Einfachheit halber nutzen wir SQLite für unsere Datenbank. Wir aktualisieren die Datei .env wie folgt:

// .env

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

Standardmäßig sucht Laravel im Datenbankverzeichnis nach einer database.sqlite-Datei. Sie erstellen diese wie folgt:

$ touch database/database.sqlite

Jetzt können wir die Migration durchführen:

$ php artisan migrate

Implementieren der Bestellaufgabe

Wie zuvor erwähnt, werden wir kein kein vollwertiges Bestellsystem entwickeln. Stattdessen implementieren wir lediglich eine Pseudobestellung. Wir erstellen dafür eine Factory-Klasse, die willkürlich künstliche Daten generiert. Führen Sie den folgenden Befehl aus:

$ php artisan make:factory OrderFactory

Dadurch wird eine neue OrderFactory.php-Datei im Verzeichnis database/factories erstellt. Ersetzen Sie den Inhalt der Datei mit dem folgenden Code:

// database/factories/OrderFactory.php

<?php

use App\Order;
use Faker\Generator as Faker;

$factory->define(Order::class, function (Faker $faker) {
    return [
        'name' => $faker->sentence,
        'amount' => $faker->numberBetween($min = 1000, $max = 9000),
    ];
});

Als Nächstes erstellen wir die Benutzeroberfläche für die Bestellaufgabe. Wir fügen Sie in home.blade.php ein, direkt unter dem Text „You're logged in!“ (Sie sind angemeldet):

// resources/views/home.blade.php

<form action="{{ route('order') }}" method="post">
    @csrf
    <button type="submit" class="btn btn-primary">Place Order</button>
</form>

Nichts Kompliziertes also. Nur ein einfaches Formular mit einer Schaltfläche, die eine Weitergabe an eine benannte Route namens order durchführt.

Laravel order button

Diese Route erstellen wir jetzt:

// routes/web.php

Route::post('/order', 'OrderController@store')->name('order')->middleware('auth');

Abschließend erstellen wir den OrderController (Bestell-Controller), zu dem die Route führt:

$ php artisan make:controller OrderController

Danach fügen wir den folgenden Code hinzu:

// app/Http/Controllers/OrderController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class OrderController extends Controller
{
  public function store(Request $request)
  {
    $order = factory(\App\Order::class)->create();


    return redirect()->route('home')->with('status', 'Order Placed!');
  }
}

Wir verwenden hier die zuvor erstellte Factory, um nach der Weitergabe eine neue Bestellung zu generieren. Anschließend leiten wir den Nutzer zurück zur Seite. Er sieht dabei eine Statusmeldung, die die erfolgreiche Bestellaufgabe bestätigt.

Einrichten von Twilio Sandbox für WhatsApp

Um echte Nachrichten mit WhatsApp senden zu können, muss WhatsApp zunächst unser Konto offiziell bestätigen. Das heißt jedoch nicht, dass wir bis dahin nicht weiter entwickeln können. Mit Twilio Sandbox für WhatsApp können wir unsere App in einer Entwicklerumgebung testen. Wir müssen uns zunächst mit der Sandbox verbinden, indem wir von unserem Gerät aus eine WhatsApp-Nachricht an eine Nummer senden, die uns zur Verfügung gestellt wird. Wir führen als Erstes die Anweisungen auf der Registerkarte Learn (Lernen) durch. Sobald Ihr Konto verbunden ist, können Sie beliebige Nachrichten senden.

Twilio WhatsApp console

Nach der Einrichtung der Sandbox brauchen Sie Ihre Twilio-Anmeldeinformationen. Wir richten damit den Zugriff auf das Twilio-PHP SDK ein. Kopieren Sie in Ihrem Twilio-Dashboard sowohl Ihre ACCOUNT SID (KONTO-SID) als auch Ihr AUTH TOKEN (Authentifizierungstoken). Notieren Sie sich die Telefonnummer, die Ihrer Sandbox zugewiesen ist. Es handelt sich um die Nummer, von der aus Sie Ihre Benachrichtigungen senden werden.

Jetzt erstellen wir in .env die Umgebungsvariablen mit diesen Angaben:

// .env

TWILIO_AUTH_SID=YOUR_TWILIO_AUTH_SID
TWILIO_AUTH_TOKEN=YOUR_TWILIO_AUTH_TOKEN
TWILIO_WHATSAPP_FROM=YOUR_TWILIO_WHATSAPP_FROM

Erstellen Sie eine dedizierte Dienstkonfiguration für Twilio. Fügen Sie den folgenden Code in config/services.php ein:

// config/services.php

'twilio' => [
  'sid' => env('TWILIO_AUTH_SID'),
  'token' => env('TWILIO_AUTH_TOKEN'),
  'whatsapp_from' => env('TWILIO_WHATSAPP_FROM')
],

Überblick über das Senden von Benachrichtigungen mit der Twilio-API für WhatsApp

Bevor wir mit der Twilio-API für WhatsApp Benachrichtigungen senden, sehen wir uns die Funktionsweise kurz etwas genauer an. Sie können mit der Twilio-API für WhatsApp zwei Arten von Nachrichten senden: unidirektionale und bidirektionale Nachrichten.

Das Senden von Benachrichtigungen fällt in die Kategorie der unidirektionale Kommunikation, während es sich bei dialogorientierten Nachrichten um bidirektionale Kommunikation handelt. Zum Senden von Benachrichtigungen müssen wir die WhatsApp-Nachrichtenvorlage nutzen.

Dieses Nachrichtenformat kann wiederverwendet werden, nachdem Nutzer sich angemeldet und Ihnen erlaubt haben, Nachrichten an sie zu senden. Nachrichtenvorlagen unterstützen die Aufrechterhaltung hochwertiger Inhalte und vermeiden Spam im Ökosystem.

Vorlagen enthalten Platzhalter, die beim Senden der Nachricht durch dynamischen Inhalt ersetzt werden können. Die Twilio WhatsApp-Sandbox enthält standardmäßig drei vorkonfigurierte Vorlagen:

  • Ihr {{1}}-Code lautet {{2}}
  • Ihr Termin bei {{1}} ist am {{2}}
  • Ihre {{1}}-Bestellung {{2}} wurde versandt und sollte am {{3}} zugestellt werden. Details: {{4}}

Für dieses Tutorial verwenden wir die dritte Vorlage. Weitere Informationen zu Vorlagen – und wie Sie eine eigene erstellen können – finden Sie in der Dokumentation.

Erstellen eines benutzerdefinierten Benachrichtigungskanals

Unsere Nutzer können nun eine Bestellung aufgeben. Daraufhin senden wir ihnen eine Benachrichtigung, um zu bestätigen, dass ihre Bestellung verarbeitet wurde. Da wir diese Benachrichtigung über WhatsApp senden möchten, müssen wir in Laravel einen benutzerdefinierten Benachrichtigungskanal erstellen. Dafür benötigen wir zwei Dateien: WhatsAppChannel.php und WhatsAppMessage.php. Die erste Datei enthält die Implementierung zum Senden einer Nachricht (Benachrichtigung), die zweite enthält die API zum Verfassen einer Nachricht.

Wir erstellen zunächst ein neues Verzeichnis namens Channels in unserem app-Ordner. Darin erstellen wir ein weiteres Verzeichnis namens Messages. Und innerhalb von „Messages“ (Nachrichten) erstellen wir WhatsAppMessage.php und fügen den folgenden Code ein:

// app/Channels/Messages/WhatsAppMessage.php

<?php


namespace App\Channels\Messages;

class WhatsAppMessage
{
  public $content;
  
  public function content($content)
  {
    $this->content = $content;

    return $this;
  }
}

Es handelt sich um eine einfache Klasse mit einer $content-Eigenschaft und einer Set-Methode zum Einstellen des Werts. Die an die Methode weitergegebenen Daten entsprechen dem Inhalt der Benachrichtigung, die wir senden werden.

Als Nächstes erstellen wir die WhatsAppChannel.php-Datei direkt im Verzeichnis Channels und fügen den folgenden Code ein:

// app/Channels/WhatsAppChannel.php

<?php
namespace App\Channels;

use Illuminate\Notifications\Notification;
use Twilio\Rest\Client;

class WhatsAppChannel
{
    public function send($notifiable, Notification $notification)
    {
        $message = $notification->toWhatsApp($notifiable);


        $to = $notifiable->routeNotificationFor('WhatsApp');
        $from = config('services.twilio.whatsapp_from');


        $twilio = new Client(config('services.twilio.sid'), config('services.twilio.token'));


        return $twilio->messages->create('whatsapp:' . $to, [
            "from" => 'whatsapp:' . $from,
            "body" => $message->content
        ]);
    }
}

Es muss für jeden Benachrichtigungskanal eine send()-Methode geben. Diese enthält die tatsächliche Implementierung zum Senden der Benachrichtigung. Sie muss zwei Argumente akzeptieren: $notifiable und $notification. Das erste Argument ist eine Eigenschaft, die von jedem Modell, das Benachrichtigungen sendet, verwendet werden muss. Das zweite Argument ist eine Instanz der tatsächlichen Benachrichtigung (die wir gleich erstellen werden).

Wir rufen die toWhatsApp()-Methode der Instanz der Klasse Notification auf (die wir später erstellen werden) und geben sie an $notifiable weiter. Dabei ist $message eine Instanz der Klasse WhatsAppMessage und enthält die Benachrichtigung, die wir senden möchten.

Um die Telefonnummer des Nutzers, an den die Benachrichtigung gehen soll, zu erhalten, rufen wir die routeNotificationFor()-Methode auf. Laravel sucht dann bei dem Modell, das die Eigenschaft verwendet, nach der routeNotificationForWhatsApp()-Methode.

Zum Schluss erstellen wir eine neue Instanz des Twilio-PHP-SDK, die wir zum Senden der Benachrichtigung nutzen. Beachten Sie, dass wir für beide Telefonnummern („to“ [an] und „from“ [von]) das Präfix „WhatsApp“ verwenden müssen.

Da wir das Twilio-PHP-SDK brauchen, müssen wir es zunächst installieren:

$ composer require twilio/sdk

Wie bereits erwähnt, benötigen wir eine routeNotificationForWhatsApp()-Methode für das Modell, das die Eigenschaft „notifiable“ nutzt. In unserem Fall handelt es sich um das Modell „User“ (Nutzer):

// app/User.php

public function routeNotificationForWhatsApp()
{
  return $this->phone_number;
}

Wir geben hier einfach das Telefonnummernfeld zurück, da es die Telefonnummern unserer Nutzer enthält.

Jetzt können wir eine Benachrichtigung erstellen, die über unseren benutzerdefinierten Benachrichtigungskanal gesendet wird:

$ php artisan make:notification OrderProcessed

Dadurch wird eine neue OrderProcessed.php-Datei im Verzeichnis app/Notifications erstellt. Öffnen Sie diese und ersetzen Sie den Inhalt durch:

// app/Notifications/OrderProcessed.php

<?php

namespace App\Notifications;

use App\Channels\Messages\WhatsAppMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use App\Channels\WhatsAppChannel;
use App\Order;


class OrderProcessed extends Notification
{
  use Queueable;


  public $order;
  
  public function __construct(Order $order)
  {
    $this->order = $order;
  }
  
  public function via($notifiable)
  {
    return [WhatsAppChannel::class];
  }
  
  public function toWhatsApp($notifiable)
  {
    $orderUrl = url("/orders/{$this->order->id}");
    $company = 'Acme';
    $deliveryDate = $this->order->created_at->addDays(4)->toFormattedDateString();


    return (new WhatsAppMessage)
        ->content("Your {$company} order of {$this->order->name} has shipped and should be delivered on {$deliveryDate}. Details: {$orderUrl}");
  }
}

Mit der via()-Methode weisen wir Laravel an, unseren benutzerdefinierten Kanal zu verwenden. Über die toWhatsApp()-Methode verfassen wir den Nachrichtentext, den wir senden möchten. Wir erstellen eine neue Instanz von WhatsAppMessage und geben diese zurück, während wir durch Aufrufen der content()-Methode den Inhalt der Benachrichtigung festlegen. Sie sehen, dass wir hier die weiter oben erwähnte WhatsApp-Nachrichtenvorlage verwenden.

Abschließend aktualisieren wir die Speichermethode für OrderController.php, sodass sie den Code enthält, der das Senden der Benachrichtigung auslöst:

// app/Http/Controllers/OrderController.php

// add this at the top of the class
use App\Notifications\OrderProcessed;


public function store(Request $request)
{
  $order = factory(\App\Order::class)->create();


  $request->user()->notify(new OrderProcessed($order));


  return redirect()->route('home')->with('status', 'Order Placed!');
}

Testen unserer Anwendung

Wir testen nun, was wir bislang erstellt haben. Zunächst prüfen wir, ob unsere App ausgeführt wird:

$ php artisan serve

Erstellen Sie ein Konto mit derselben Telefonnummer, die Sie Ihrer Sandbox hinzugefügt haben. Nachdem Sie auf die Schaltfläche „Place Order“ geklickt haben, sollten Sie eine Nachricht erhalten, die ungefähr so aussieht:

WhatsApp order notification

Fazit

Sie haben in diesem Tutorial gelernt, wie Sie in einer Laravel-Anwendung Benachrichtigungen über WhatsApp senden. Sie können jedoch nicht nur Benachrichtigungen senden. Sie können die Twilio-API für WhatsApp auch für dialogorientierte Nachrichten an WhatsApp nutzen.

Den gesamten Quellcode für dieses Tutorial finden Sie auf GitHub.

Chimezie Enyinnaya ist Softwareentwickler und -trainer.