https://d226lax1qjow5r.cloudfront.net/blog/blogposts/send-greek-unicode-viber-messages-with-symfony/greek-unicode-viber-messages-symfony.png

Griechische Unicode Viber-Nachrichten mit Symfony senden

Zuletzt aktualisiert am January 15, 2024

Lesedauer: 11 Minuten

Ich liebe die zufälligen Dinge, die man bei Developer Advocacy herausfindet. Dieser besondere Fund stammt aus einem Gespräch, das ich auf der We Are Developers Conference in Berlin dieses Jahr hatte. Es stellte sich heraus, dass die offiziellen Nachrichten der griechischen Regierung über Viberversendet werden, die für einen bedeutenden Anteil von 4,55 % am Markt für mobile Nachrichten. Da ist mir ein Licht aufgegangen: Vonage unterstützt Viber in der Messages APIWarum also nicht ein Beispiel für den Versand einer Unicode-Nachricht mit PHP an ein Viber-Gerät zeigen? Und genau das, liebe Leser, werden wir tun, und zwar von Grund auf.

Wir werden das Symfony-Framework für dieses Tutorial, aber anstatt dem Installationsprozess zu folgen, der in den Symfony Docs beschrieben ist, habe ich einen etwas anderen Ansatz gewählt. Neal Brooks half mir bei der Erstellung dieses Repository das ein komplettes Framework mit einem einzigen Befehl hochfährt!

Erste Schritte

Kommen wir zur Sache und starten wir zuerst die App. Da wir mit Docker für diese Anwendung, müssen Sie zuerst Docker für Ihre Plattform installiert habenund Sie müssen git Versionskontrolle installiert haben. Ein weiterer erforderlicher Schritt (der für Windows-Benutzer relevanter ist als für Linux- oder Mac-Umgebungen) besteht darin, sicherzustellen, dass GNU Make installiert ist.

Klonen Sie das folgende Repository von Ihrer Kommandozeile aus:

git clone https://github.com/nealio82/symfony-starter-kit

Jetzt verwenden wir make um die Anwendung zu erstellen:

make create-webapp

Der Befehl bewirkt zwei Dinge:

  • Laden Sie alle Abhängigkeiten für die neueste Version von Symfony herunter und installieren Sie sie, die sich im Ordner app Ordner befindet (dies ist jetzt der Quellcode Ihrer Anwendung)

  • Starten Sie die Docker-Umgebung mit docker compose up was den Symfony-PHP-Container mit PHP8.2, Postgres, Node und Nginx als Webserver der Wahl hochfährt.

Denn wir werden super faul sind, werden wir auch einen Befehl verwenden, um unsere Anwendung im Browser zu öffnen:

make open-web

Splash screen of Symfony applicationWelcome to Symfony!

Installieren Sie die Abhängigkeiten und konfigurieren Sie

Wir sind dran! Jetzt können wir mit der Entwicklung beginnen. Als erstes fügen wir das Vonage PHP SDK als eine Abhängigkeit der Symfony-Anwendung hinzuzufügen, indem wir Composer verwenden. Wir können das Makefile verwenden, um dies innerhalb des PHP-Containers zu tun.

make composer require vonage/client-core

Wir werden mit der App einen eingehenden Webhook über eine exponierte Route simulieren und dann die Nachricht innerhalb dieser Nutzlast über Viber an eine Nummer senden. Damit dies funktioniert, sind einige Schritte erforderlich: Erstens benötigen Sie ein Vonage Account.

Als Nächstes müssen wir eine Vonage-Anwendung erstellen, die Nachrichten empfangen kann. Dies können wir über das Vonage Dashboard tun:

Screenshot of application creation in the Vonage DashboardCreating an Application in the Vonage Dashboard

Kümmern Sie sich nicht um die Nachrichten-Webhooks für eingehende URLs - für die Zwecke dieses Artikels sind wir nicht daran interessiert, entweder Statusrückrufe oder eingehende Nachrichten zu erhalten. Beim Erstellen der App können Sie Dummy-URLs in die Webhook-Konfiguration einfügen, da es sich um Pflichtfelder handelt.

Die wichtigsten Teile, die Sie benötigen, sind:

  • Ihre Anwendungs-ID

  • Die private.key wird über die Schaltfläche Generate public and private key Schaltfläche auf diesem Dashboard heruntergeladen und in den Symfony-Stammordner gelegt (d.h. app)

Nachdem Sie auf "Anwendung generieren" geklickt haben, müssen wir die Möglichkeit haben, unsere Konfiguration mit dem Config Builder von Symfony abzurufen. Wir werden sie als Parameter konfigurieren, da dies die einfachste Form ist, um globale Anwendungswerte zu erhalten.

Erstellen Sie eine neue Datei, vonage.yamlund legen Sie sie in app/config/packages. In dieser Datei werden wir unsere Schlüssel ablegen:

parameters:  
  application_id: '99996908-65ec-XxXx-a640-f5f4a999a3b9'  
  private_key_path: '%kernel.project_dir%/private.key'

Stellen Sie sicher, dass Sie den Dummy-Wert, den ich für application_id durch den richtigen Wert aus der Vonage-Anwendung, die Sie über das Dashboard erstellt haben. Wenn Sie diese Parameter definiert haben, können Sie von überall in Symfony auf ihre Werte zugreifen, indem Sie die ParameterBag (mehr dazu später).

Verwendung der Nachrichten-Sandbox

Während das Dashboard geöffnet ist, konfigurieren wir den Account, den wir für die Nutzung der Viber Business Messages-Plattform verwenden werden. Anstatt ein eigenes Viber Business Messages-Konto einzurichten, verwenden wir ein bereits eingerichtetes Konto, das in der Nachrichten-Sandbox.

Bevor Sie die Sandbox einrichten, müssen Sie die Viber-App auf Ihrem Telefon installiert haben. Laden Sie die App herunter und folgen Sie dem kompletten Prozess.

Der nächste Schritt besteht darin, die mit Ihrem Viber Account verbundene Nummer für die Nachrichten-Sandbox zuzulassen. Gehen Sie dazu zur Option Nachrichten-Sandbox im Dashboard. Du kannst dorthin navigieren, indem du das Menü über Troubleshoot & Learn > Developer Tools > Messages Sandbox aufrufst. Klicken Sie auf der Viber-Karte auf den Link "Zur Sandbox hinzufügen" und folgen Sie den Anweisungen, um Ihre Nummer für den Viber-Account in der Sandbox zuzulassen. Da wir das vorbereitete Sandbox-Konto verwenden, wird das Vonage-Branding in den Nachrichten von diesem Konto vorhanden sein.

Weiterleitung

Nachdem das Sandbox-Konto eingerichtet ist, erstellen wir als Nächstes die Route in Symfony, die die Nachricht auslösen wird. Wir werden dies innerhalb des Docker-Containers tun (vorausgesetzt, Sie befinden sich eine Ebene über dem app Verzeichnis befinden, in dem sich der gesamte Quellcode befindet):

./app/bin/console make:controller

Hier werden Sie aufgefordert, Ihren Controller zu benennen. Nennen wir ihn MessengerController. Die Konsole wird den Rest für Sie vorbereiten. Sie können dies an den beiden generierten Codes sehen:

namespace App\Controller;  
  
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;  
use Symfony\Component\HttpFoundation\Response;  
use Symfony\Component\Routing\Annotation\Route;  
  
class MessengerController extends AbstractController  
{  
    #[Route('/messenger', name: 'app_messenger')]  
    public function index(): Response  
    {  
        return $this->render('messenger/index.html.twig', [  
            'controller_name' => 'MessengerController',  
        ]);    
	}
}        

Sie können die neue Route jetzt über Ihren Browser aufrufen:

Screenshot of the default Symfony contoller template pageSymfony's default controller template

Unsere Route wird sich eher wie eine REST-API-Route verhalten als eine Route für eine Webanwendung. Wir müssen sie also als einen POST Endpunkt angeben und dafür sorgen, dass er JSON zurückgibt. Aktualisieren wir den Code, um dies zu tun:

#[Route('/messenger', name: 'app_messenger', methods: ['POST'], format: 'json')] 
public function index(): Response  
{ 
    return new JsonResponse(['message_success' => true]);  
}

Drei Dinge haben sich hier geändert, um eine Antwort zu erhalten:

  • Die Route-Anmerkung hat sich geändert und erlaubt nun POST nur noch Anfragen.

  • Die Route-Anmerkung legt nun auch fest, dass nur application/json an diesen Endpunkt gesendet werden können

  • Wir geben nun ein JsonResponse Objekt zurück.

Sie können nun versuchen, den Endpunkt mit einem API-Testprogramm wie Postman. Hier habe ich mich für die Verwendung von Insomnia:

Screenshot of Insomina sending a POST requestUsing Insomnia to test our Application

OK, wir haben einen funktionierenden Anfrage/Antwort-Lebenszyklus. Ausgezeichnet. Zeit, den Rest des Puzzles zusammenzusetzen.

Sie haben vielleicht bemerkt, dass wir eine message in der JSON-Nutzlast senden - und, wie versprochen, ist es in griechischem Unicode! Der erste Schritt im Code ist also das Extrahieren dieser Zeichenkette. Mit Hilfe von Symfony's Dependency Injection fügen wir das Request Objekt in die Controllermethode ein, wodurch wir Zugriff auf die gesamte Anfrage erhalten:

use Symfony\Component\HttpFoundation\Request;

#[Route('/messenger', name: 'app_messenger', methods: ['POST'], format: 'json')] 
public function index(Request $request): Response  
{ 
    return new JsonResponse(['message_success' => true]);  
}

Jetzt können wir einen Schlüssel in der Nutzlast der Anfrage herausziehen, der message:

use Symfony\Component\HttpFoundation\Request;

#[Route('/messenger', name: 'app_messenger', methods: ['POST'], format: 'json')] 
public function index(Request $request): Response  
{ 
	$message = $request->getPayload()->get('message');
	
    return new JsonResponse(['message_success' => true]);  
}

Vonage verwenden

So, wir haben unsere Nachricht und Anfrage/Antwort konfiguriert. Nun ist es an der Zeit, das Vonage PHP SDK in unseren Controller einzubinden, wobei der Basis-Client mit unseren Anmeldeinformationen konfiguriert wird, die wir in der Symfony-Konfiguration eingerichtet haben. Wir verwenden ein Objekt namens ParameterBag um diese Anmeldeinformationen herauszuholen. Um Zugriff auf diese Klasse zu erhalten, injizieren Sie sie in den Konstruktor des Controllers:

public function __construct(  
    protected ParameterBagInterface $parameterBag,  
) {}

Sie können jetzt darauf zugreifen mit $this->parameterBag. Lassen Sie uns herausholen, was wir brauchen:

use Symfony\Component\HttpFoundation\Request;

#[Route('/messenger', name: 'app_messenger', methods: ['POST'], format: 'json')] 
public function index(Request $request): Response  
{ 
	$message = $request->getPayload()->get('message');

	$privateKey = file_get_contents($this->parameterBag->get('private_key_path'));
	$applicationId = $this->parameterBag->get('application_id');
	
    return new JsonResponse(['message_success' => true]);
}

Da wir nun die beiden erforderlichen Parameter für unsere Vonage-Anmeldeinformationen haben, können wir sie als Argumente verwenden, um ein Vonage\Credentials\Keypair Objekts verwenden und dieses Objekt anschließend bei der Instanzierung eines neuen Vonage Client:

use Symfony\Component\HttpFoundation\Request;

#[Route('/messenger', name: 'app_messenger', methods: ['POST'], format: 'json')] 
public function index(Request $request): Response  
{ 
	$message = $request->getPayload()->get('message');

	$privateKey = file_get_contents($this->parameterBag->get('private_key_path'));
	$applicationId = $this->parameterBag->get('application_id');
	
	$vonageCredentials = new Client\Credentials\Keypair($privateKey, $applicationId);  
  
	$client = new Client(  
		$vonageCredentials,  
		[
			'base_api_url' => 'https://messages-sandbox.nexmo.com'  
	    ]  
	);
	
    return new JsonResponse(['message_success' => true]);
}

Ein wichtiger Schritt, der hier zu beachten ist, ist, dass die Client eine zusätzliche Option einnimmt, base_api_url. Diese setzt die im SDK integrierten Basis-URL-Einstellungen außer Kraft, so dass Sie die Messages API-Sandbox verwenden können.

Es ist an der Zeit, die Viber-Nachricht zu erstellen. Sie müssen eine Nummer verwenden from Nummer verwenden, die Ihnen im Vonage Dashboard angezeigt wird. Sie können diese Nummer sehen, wenn Sie auf der Seite Messages Sandbox nach unten scrollen:

Screenshot of the Messages Sandbox documentationYou can see the correct 'from' field here

Wir verwenden diese Nummer bei der Erstellung des ViberText Objekts:

$messageText = 'Καλώς ήρθατε στο Vonage στα Ελληνικά!'
$vonageMessage = new ViberText('44999999999', '22353', $messageText);

Der letzte Schritt ist das Senden der Nachricht, aber es wäre besser, den zurückgegebenen JSON-Schlüssel message_success sowohl genau als auch defensiv ist. Hier ist also das vollständige Endergebnis:

namespace App\Controller;  
  
use Psr\Log\LoggerInterface;  
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;  
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;  
use Symfony\Component\HttpFoundation\JsonResponse;  
use Symfony\Component\HttpFoundation\Request;  
use Symfony\Component\HttpFoundation\Response;  
use Symfony\Component\Routing\Annotation\Route;  
use Vonage\Client;  
use Vonage\Messages\Channel\Viber\ViberText;  
  
class MessengerController extends AbstractController  
{  
    public function __construct(  
        protected ParameterBagInterface $parameterBag,  
        protected LoggerInterface $logger  
    ) {}  
  
    #[Route('/messenger', name: 'app_messenger', methods: ['POST'], format: 'json')]  
    public function index(Request $request): Response  
    {  
        $messageText = $request->getPayload()->get('message');  
        $responseData = ['message_success' => false];  
  
		$privateKey = file_get_contents($this->parameterBag->get('private_key_path'));
		$applicationId = $this->parameterBag->get('application_id');
	
		$vonageCredentials = new Client\Credentials\Keypair($privateKey, $applicationId);  
  
		$client = new Client(  
			$vonageCredentials,  
			[
				'base_api_url' => 'https://messages-sandbox.nexmo.com'  
		    ]  
		);
        
        $vonageMessage = new ViberText('44999999999', '22353', $messageText);  
  
        try {  
            $client->messages()->send($vonageMessage);  
            $responseData['message_success'] = true;  
        } catch (\Exception $exception) {  
            $this->logger->error($exception->getMessage());  
        }
        
        return new JsonResponse($responseData);  
    }
}

Beim endgültigen Code sind noch ein paar Dinge zu beachten. Erstens bedeutet die defensive Codeanforderung, dass wir einen Try-Catch-Block eingeführt haben. Aber was tun wir, wenn dieser Block fehlschlägt, abgesehen vom Senden von false um dem Client mitzuteilen, dass das Ergebnis fehlgeschlagen ist? Nun, wir können die Fehlerantwort protokollieren. Dies wurde mit Hilfe von Symfony's Dependency Injection gemacht, um die Logger zur Controller-Klasse über den Konstruktor hinzuzufügen. In diesem Fall kommt Symfony mit dem bekannten Monolog von Haus aus konfiguriert, so dass man die LoggerInterface hier.

Schießen Sie die Anfrage auf Insomina erneut ab und...

Screenshot of a Viber app on a mobile device showing the Greek messageGreek Viber Messages!

Magie! Wir haben eine griechische Lokalnachricht auf Viber!

Schlussfolgerung

Die Verwendung des PHP-SDKs von Vonage ist darauf ausgelegt, die Entwicklungszeit zu verkürzen. Zusammen mit der schnellen Entwicklungszeit, die das Symfony-Framework bietet, steht Ihnen ein leistungsstarkes Toolset zur Verfügung. Wenn Sie etwas bauen und Hilfe oder Anleitung benötigen, lassen Sie es uns wissen, indem Sie Registrieren Sie sich für unser Community Slack.

Zusätzliche Ressourcen

SMS-Versand aus PHP mit Failover: Die Cupcake-Bäckerei

Typsicherheit richtig gemacht - PHP Array Hacking

Scrub Up! Reinigung Ihrer PHP-Anwendung mit PHPStan

Vonage PHP SDK

Teilen Sie:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondeSenior PHP Entwickler Advocate

Als ausgebildeter Schauspieler mit einer Dissertation in Standup-Comedy bin ich über die Meetup-Szene zur PHP-Entwicklung gekommen. Man findet mich, wenn ich über Technik spreche oder schreibe, oder wenn ich seltsame Platten aus meiner Vinylsammlung spiele oder kaufe.