Thursday, 8 July, 2021 UTC


Summary

O Laravel facilita o envio de notificações em seu aplicativo PHP. Pronto para uso, ele oferece suporte a vários canais, como e-mail, SMS, Slack e banco de dados. E se quisermos enviar notificações para um canal diferente além desses, digamos o WhatsApp? Neste tutorial, mostrarei como implementar notificações do WhatsApp no aplicativo Laravel usando a API da Twilio para WhatsApp.
Ferramentas necessárias para completar este tutorial
Para seguir este tutorial, você precisará do seguinte:
  • Composer e Instalador do Laravel instalado em sua máquina local
  • Conhecimento básico da Estrutura do Laravel
  • Uma conta da Twilio
O que vamos criar
Para o propósito deste tutorial, usaremos o conceito de um sistema de pedidos. Para simplificar, não criaremos um sistema de pedidos com todos os recursos, apenas a parte em que o sistema envia as notificações.
Como criar um novo aplicativo Laravel
Vamos começar criando um novo aplicativo Laravel. Usaremos o instalador do Laravel mencionado nos pré-requisitos. Execute o seguinte comando no console:
$ laravel new laravel-whatsapp-notification $ cd laravel-whatsapp-notification 
Depois que o aplicativo é criado, precisamos instalar as dependências do NPM, pois o Bootstrap vem pré-empacotado como uma dependência do NPM:
$ npm install 
Depois que as dependências forem instaladas, execute:
$ npm run dev 
Adicionar autenticação
Em seguida, vamos adicionar autenticação. A partir do Laravel 6, o suporte de autenticação foi extraído para um pacote separado, por isso precisamos instalá-lo com o Composer:
$ composer require laravel/ui --dev 
Em seguida, podemos executar para obter o suporte de autenticação:
$ php artisan ui vue --auth 
Como o WhatsApp usa números de telefone, precisamos de uma forma de coletar os números de telefone dos usuários em nosso aplicativo. Uma forma de conseguir isso é coletando os números de telefone dos usuários no momento do registro. Vamos atualizar o formulário de registro para incluir o campo de número de telefone. Adicione o seguinte código no register.blade.php logo após o campo de endereço de e-mail:
// 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> 
Observação: os números de telefone do usuário devem estar no formato E.164.
Em seguida, vamos atualizar os métodos validator() e create() do RegisterController como mostrado abaixo:
// 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']), ]); } 
Adicionamos algumas regras de validação para o campo de número de telefone e mantemos o número de telefone no banco de dados junto com os outros dados que estão sendo coletados.
Por último, precisamos adicionar o campo de número de telefone à lista de campos que podem ser atribuídos em massa dentro do modelo User:
// app/User.php protected $fillable = [ 'name', 'email', 'password', 'phone_number' ]; 
Criar modelos e migrações
Precisamos também atualizar o arquivo de migração de tabela dos usuários que vem com o aplicativo Laravel padrão adicionando um novo campo para o número de telefone:
// database/migrations/2014_10_12_000000_create_users_table.php $table->string('phone_number')->unique(); 
Em seguida, vamos criar um modelo Order e o seu arquivo de migração correspondente:
$ php artisan make:model Order -m 
Em seguida, vamos atualizar o arquivo de migração conforme abaixo:
// 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(); }); 
Para manter as coisas simples, a tabela orders conterá apenas os campos: id, name (nome), amount (valor) e os registros de data e hora.
Antes de executar a migração, vamos verificar se nosso banco de dados está configurado. Para manter as coisas simples e diretas, usaremos o SQLite em nosso banco de dados. Atualize o arquivo .env conforme abaixo:
// .env DB_CONNECTION=sqlite DB_DATABASE=/absolute/path/to/database.sqlite 
Por padrão, o Laravel vai procurar por um arquivo database.sqlite no diretório do banco de dados. Para criá-lo:
$ touch database/database.sqlite 
Agora, podemos executar a migração:
$ php artisan migrate 
Implementar o pedido
Como eu disse anteriormente, não vamos construir um sistema de pedidos completo. Implementaremos apenas um pedido simulado. Para isso, precisamos criar uma classe factory para gerar aleatoriamente dados falsos. Execute o comando abaixo:
$ php artisan make:factory OrderFactory 
Um novo arquivo OrderFactory.php será criado no diretório database/factories. Substitua o conteúdo do arquivo pelo seguinte código:
// 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), ]; }); 
Em seguida, vamos criar a UI para o nosso pedido. Vamos adicioná-lo dentro de home.blade.php imediatamente abaixo do texto "You're logged in!" (Você está conectado!):
// resources/views/home.blade.php <form action="{{ route('order') }}" method="post"> @csrf <button type="submit" class="btn btn-primary">Place Order</button> </form> 
Nada muito elaborado. Apenas um formulário simples com um botão, que irá enviar para uma rota nomeada chamada order.
Em seguida, precisamos criar a rota:
// routes/web.php Route::post('/order', 'OrderController@store')->name('order')->middleware('auth'); 
Por fim, vamos criar o OrderController para que a rota aponta:
$ php artisan make:controller OrderController 
Em seguida, vamos adicionar o seguinte código:
// 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!'); } } 
Aqui estamos usando a factory que criamos anteriormente para criar um novo pedido no envio. Em seguida, redirecionamos de volta para a página com uma mensagem de status de sucesso.
Configurar a sandbox da Twilio para WhatsApp
Para enviar mensagens com WhatsApp em produção, precisamos esperar que o WhatsApp aprove formalmente nossa conta. Mas, isso não significa que temos que esperar para começar a construir. Com a Sandbox da Twilio para WhatsApp, podemos testar nosso app em um ambiente de desenvolvedor. Para usar a sandbox, primeiro precisamos nos conectar a ela enviando uma mensagem do WhatsApp do nosso dispositivo para um número que será disponibilizado para nós. Para começar, siga as instruções na guia Learn (Aprender). Você poderá enviar qualquer mensagem depois que sua conta estiver conectada.
Assim que o sandbox estiver configurado, pegue suas credenciais da Twilio. Vamos usá-las para configurar o acesso ao SDK do PHP da Twilio. Acesse o dashboard da Twilio e copie o ACCOUNT SID (SID DA CONTA) e AUTH TOKEN (TOKEN DE AUTENTICAÇÃO). Anote o número de telefone atribuído à sandbox, pois é o número a partir do qual você enviará suas notificações.
Em seguida, vamos criar as variáveis de ambiente para manter esses detalhes dentro de .env:
// .env TWILIO_AUTH_SID=YOUR_TWILIO_AUTH_SID TWILIO_AUTH_TOKEN=YOUR_TWILIO_AUTH_TOKEN TWILIO_WHATSAPP_FROM=YOUR_TWILIO_WHATSAPP_FROM 
Crie uma configuração de serviço dedicada para a Twilio. Adicione o código abaixo dentro de config/services.php:
// config/services.php 'twilio' => [ 'sid' => env('TWILIO_AUTH_SID'), 'token' => env('TWILIO_AUTH_TOKEN'), 'whatsapp_from' => env('TWILIO_WHATSAPP_FROM') ], 
Visão geral do envio de notificações com a API da Twilio para WhatsApp
Antes de nos aprofundarmos no envio de notificações com a API da Twilio para WhatsApp, vamos dedicar um momento para entender como funciona. Há dois tipos de mensagens que podem ser enviadas usando a API da Twilio para WhatsApp: mensagens unilaterais e mensagens bidirecionais. O envio de notificações se enquadra em mensagens unilaterais e o envio de mensagens de conversação se enquadra em mensagens bidirecionais. Para poder enviar mensagens de notificação, precisamos usar o que é chamado de modelo de mensagem WhatsApp.
Um modelo de mensagem do WhatsApp é um formato de mensagem que pode ser reutilizado para enviar mensagens aos usuários uma vez que eles tenham ativado e dado permissão ao seu app para enviar mensagens. As mensagens de modelo são usadas para ajudar a manter conteúdo de alta qualidade e evitar spam no ecossistema.
As mensagens de modelo usam valores de espaço reservado que podem ser substituídos por conteúdo dinâmico quando a mensagem é enviada. Pronto para usar, o sandbox da Twilio WhatsApp vem com três modelos pré-provisionados:
  • Seu código {{1}} é {{2}}
  • Seu agendamento {{1}} está próximo em {{2}}
  • Seu pedido {{1}} de {{2}} foi enviado e deve ser entregue em {{3}}. Detalhes : {{4}}
Para o propósito deste tutorial, usaremos o terceiro modelo. Para saber mais sobre modelos e como você pode criar seu próprio, confira os documentos.
Criar um canal de notificação personalizado
Da forma como está, nossos usuários podem fazer um pedido. Agora, precisamos enviar uma notificação para que eles saibam que seu pedido foi processado. Como queremos enviar essa notificação por WhatsApp, precisamos criar um canal de notificação personalizado no Laravel. Para isso, precisaremos de dois arquivos: WhatsAppChannel.php e WhatsAppMessage.php. O primeiro conterá a implementação para enviar uma mensagem (notificação), enquanto o último conterá a API para compor uma mensagem.
Vamos começar criando um novo diretório chamado Channels (Canais) em nossa pasta app. Dentro dela, criaremos outro diretório chamado Messages (Mensagens). Dentro de Messages (Mensagens), criaremos o arquivo WhatsAppMessage.php e colaremos o seguinte código:
// app/Channels/Messages/WhatsAppMessage.php <?php namespace App\Channels\Messages; class WhatsAppMessage { public $content; public function content($content) { $this->content = $content; return $this; } } 
Esta é uma classe simples que contém uma propriedade $content e um setter (método de conteúdo) para definir o valor da propriedade de conteúdo. Qualquer que seja o dado passado ao método será o conteúdo da notificação que enviaremos.
Em seguida, vamos criar o arquivo WhatsAppChannel.php diretamente dentro do diretório Channels (Canais) e colar o seguinte código nele:
// 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 ]); } } 
Cada classe de canal de notificação deve ter um método send(), que conterá a implementação real para enviar a notificação. Ele deve aceitar dois argumentos: $notifiable e $notification. O primeiro é um traço que qualquer modelo que envia notificações precisa usar, enquanto o último é uma instância da notificação real, que criaremos em breve.
Usando a instância de notificação, chamamos o método toWhatsApp() que criaremos mais tarde e o passamos para $notifiable. Aqui, $message será uma instância do WhatsAppMessage e conterá a notificação que desejamos enviar.
Para obter o número de telefone do usuário para o qual queremos enviar a notificação, chamamos um método routeNotificationFor() no atributo $notification. Internamente, Laravel vai procurar um método routeNotificationForWhatsApp() no modelo usando o atributo.
Por último, criamos uma nova instância da SDK PHP da Twilio que usamos para enviar a notificação. Observe que precisamos prefixar os números de telefone (de e para) com o WhatsApp.
Como estamos usando a SDK PHP da Twilio, precisamos ter certeza de que ela está instalada:
$ composer require twilio/sdk 
Lembra que eu disse que precisamos ter um método routeNotificationForWhatsApp() no modelo usando o atributo Notifiable? Em nosso caso, esse é o modelo de usuário:
// app/User.php public function routeNotificationForWhatsApp() { return $this->phone_number; } 
Estamos simplesmente retornando o campo de número de telefone, pois esse é o campo que contém os números de telefone dos nossos usuários.
Agora, podemos criar uma notificação que usará nosso canal de notificação personalizado:
$ php artisan make:notification OrderProcessed 
Isso criará um novo arquivo OrderProcessed.php dentro do app/Notifications. Abra-o e substitua o conteúdo por:
// 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}"); } } 
Dentro do método via(), estamos dizendo ao Laravel que queremos usar nosso canal personalizado. Dentro do método toWhatsApp(), vamos compor a mensagem que será enviada. Criamos e retornamos uma nova instância do WhatsAppMessage enquanto configuramos o conteúdo da notificação chamando o método content(). Observe que estamos usando o modelo de mensagem WhatsApp sobre o qual falamos anteriormente.
Por fim, vamos atualizar o método de armazenamento OrderController.php para incluir o código que disparará a notificação:
// 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!'); } 
Testar o aplicativo
Agora, vamos testar o que estamos construindo até agora. Primeiro, vamos verificar se nosso aplicativo está em execução:
$ php artisan serve 
Crie uma conta com o mesmo número de telefone adicionado ao Sandbox. Você deve receber uma mensagem semelhante à mensagem abaixo quando clicar no botão "Place Order" (Fazer pedido).
Conclusão
Neste tutorial, aprendemos como enviar notificações em um aplicativo Laravel por meio do WhatsApp. Você não está limitado a enviar apenas notificações, pois pode enviar mensagens de conversa para o WhatsApp usando a API da Twilio para WhatsApp.
Você pode encontrar o fonte completo deste tutorial no GitHub.
Este artigo foi traduzido do original "How to Create a Laravel Notification Channel for WhatsApp with Twilio". Enquanto melhoramos nossos processos de tradução, adoraríamos receber seus comentários em [email protected] - contribuições valiosas podem render brindes da Twilio.