Como criar um canal de notificação Laravel para WhatsApp com Twilio

November 22, 2019
Escrito por
Chimezie Enyinnaya
Contribuidor
As opiniões expressas pelos colaboradores da Twilio são de sua autoria

Como criar um canal de notificação Laravel para WhatsApp com Twilio

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:

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.

Formulário de registro do Laravel

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.

Botão de pedido do Laravel

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.

Console da Twilio para WhatsApp

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).

Notificação de pedido do WhatsApp

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 help@twilio.com - contribuições valiosas podem render brindes da Twilio.