Wednesday, 30 June, 2021 UTC


Summary

O WhatsApp é frequentemente mencionado como o app de mensagens mais popular do mundo, que permite a comunicação de seus usuários de forma segura e em tempo real. Como proprietário de uma empresa, você pode se basear na velocidade e segurança fornecidas pelo WhatsApp para interagir, enviar alertas e notificações, prestar suporte ou até mesmo enviar OTPs (One-time Passwords, senhas de uso único) aos seus clientes.
Neste tutorial, você aprenderá a enviar notificações com OTPs para os usuários pelo WhatsApp usando a API da Twilio para WhatsApp durante o registro
Pré-requisitos
Para acompanhar este tutorial, você precisará do seguinte:
  • Conhecimento básico do Laravel
  • Laravel instalado no computador local
  • Composer instalado globalmente
  • Conta da Twilio
  • Número da Twilio habilitado para WhatsApp
Configuração do projeto
Este tutorial usará o Laravel, então a primeira etapa é gerar um novo aplicativo Laravel. Usando o Instalador do Laravel, execute o código a seguir no terminal para gerar um novo projeto:
$ laravel new whatsapp-otp 
Em seguida, você precisará configurar um banco de dados para o aplicativo. Neste tutorial, usaremos um banco de dados MySQL. Caso não tenha o MySQL na máquina local, acesse o site oficial para saber como instalá-lo. Assim que concluir a instalação com sucesso, acione o terminal e execute este comando para fazer login no MySQL:
$ mysql -u {your_user_name} 
OBSERVAÇÃO: adicione o sinalizador -p caso você tenha uma senha para a instância do MySQL.
Depois de fazer login, execute o seguinte comando para criar um banco de dados:
mysql> create database whatsapp-otp; mysql> exit; 
Em seguida, atualize o arquivo .env com suas credenciais do banco de dados. Abra o arquivo .env e faça os ajustes a seguir:
DB_DATABASE=whatsapp-otp DB_USERNAME={your_user_name} DB_PASSWORD={your_db_password} 
Configurar a API da Twilio para WhatsApp
Para utilizar a API da Twilio para WhatsApp, é necessário obter um número de telefone da Twilio aprovado para WhatsApp, que será utilizado para envio e recebimento de mensagens. Entretanto, isso somente será um pré-requisito se você utilizar a API na produção. Para fins de teste e desenvolvimento, a Twilio disponibiliza a área sandbox, que pode ser usada para envio e recebimento de mensagens pelo WhatsApp em um ambiente de desenvolvedor.

Acessar a sandbox do WhatsApp

Antes de iniciar o teste com a sandbox da Twilio, é necessário participar. Para isso, acesse a seção WhatsApp em seu dashboard da Twilio e envie o texto fornecido (que está no formato join-{unique text}) ao número de WhatsApp disponibilizado. Geralmente é +1 (415) 523-8886.
Ao enviar a mensagem com sucesso, você obterá uma resposta semelhante a esta:
Agora que você se conectou à sandbox do WhatsApp, é necessário adicionar suas credenciais da Twilio ao arquivo .env da seguinte maneira:
TWILIO_WHATSAPP_NUMBER= TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= 
OBSERVAÇÃO: é possível localizar seu número do WhatsApp da Twilio na sandbox, em Sandbox Participants (Participantes da sandbox). O Account SID (SID da conta) e o Auth Token (token de autenticação) estão disponíveis no dashboard.
Enviar OTPs pelo WhatsApp
Para agilizar este tutorial, o suporte de Autenticação do Laravel será usado para autenticar usuários no aplicativo. Acione um terminal no diretório de projetos e execute o seguinte comando para instalar o pacote laravel/ui e também oferecer suporte a um sistema de autenticação básico:
$ composer require laravel/ui --dev $ php artisan ui bootstrap --auth $ npm install && npm run dev 
Após executá-lo com sucesso, você poderá visualizar o login, registro, e início, bem como as rotas para autenticação.
OBSERVAÇÃO: para usar o comando npm, é necessário ter o Node.js instalado globalmente em sua máquina.
Em seguida, você precisa criar uma coluna na tabela users (usuários) para armazenar a OTP gerada. Abra o arquivo de migração de usuário (database/migrations/2014_10_12_000000_create_users_table.php) e faça as seguintes alterações no método up():
/** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->string('phone_number'); $table->string('otp')->nullable(); $table->rememberToken(); $table->timestamps(); }); } 
Isso adiciona as colunas otp e phone_number na tabela users, que será usada para armazenar as OTPs e números de telefone dos usuários, respectivamente.
Em seguida, abra o arquivo modelo do User (app/User.php) para adicionar os campos otp e phone_number à matriz fillable:
/** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', 'otp', 'phone_number', ]; 
Agora, para que esse esquema reflita em seu banco de dados, execute o seguinte comando para processar as migrações disponíveis:
$ php artisan migrate 

Modifique a lógica de registro

O suporte básico de autenticação Laravel precisa ser modificado para auxiliar na geração de uma OTP no momento do registro e da entrega pela API da Twilio para WhatsApp. Antes de fazer os ajustes na lógica de registro, é necessário instalar o SDK da Twilio, que será usado para o envio das mensagens do WhatsApp. Abra um terminal no diretório de projetos e execute o seguinte comando para instalá-lo pelo Composer:
$ composer require twilio/sdk 
Em seguida, abra o controlador de registro (app/Http/Controllers/Auth/RegisterController.php) e faça as seguintes alterações:
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use App\User; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Twilio\Rest\Client; class RegisterController extends Controller { /* |-------------------------------------------------------------------------- | Register Controller |-------------------------------------------------------------------------- | | This controller handles the registration of new users as well as their | validation and creation. By default this controller uses a trait to | provide this functionality without requiring any additional code. | */ use RegistersUsers; /** * Where to redirect users after registration. * * @var string */ protected $redirectTo = RouteServiceProvider::HOME; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest'); } /** * Get a validator for an incoming registration request. * * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], 'phone_number' => ['required', 'numeric'], ]); } /** * Create a new user instance after a valid registration. * * @param array $data * @return \App\User */ protected function create(array $data) { $otp = rand(1000, 9999); $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'phone_number' => $data['phone_number'], 'password' => Hash::make($data['password']), 'otp' => $otp, ]); $this->sendWhatsappNotification($otp, $user->phone_number); return $user; } private function sendWhatsappNotification(string $otp, string $recipient) { $twilio_whatsapp_number = getenv("TWILIO_WHATSAPP_NUMBER"); $account_sid = getenv("TWILIO_ACCOUNT_SID"); $auth_token = getenv("TWILIO_AUTH_TOKEN"); $client = new Client($account_sid, $auth_token); $message = "Your registration pin code is $otp"; return $client->messages->create("whatsapp:$recipient", array('from' => "whatsapp:$twilio_whatsapp_number", 'body' => $message)); } } 
O método validator() foi modificado para incluir o campo phone_number, enquanto o método create() também foi modificado para gerar uma OTP numérica de quatro dígitos usando o método integrado rand() do PHP:
$otp = rand(1000, 9999); 
Então, o usuário é armazenado no banco de dados usando o método Eloquent create(), que retorna o modelo de User salvo. Após isso, a OTP gerada é enviada ao usuário chamando o método sendWhatsappNotification() e transformando a otp e o phone_number do usuário em argumentos.
O SDK da Twilio é inicializado no método sendWhatsappNotification() usando suas credenciais (disponíveis no Dashboard da Twilio), instanciando uma nova classe Client:
$client = new Client($account_sid, $auth_token); 
Depois, o modelo de mensagem para envio da OTP estará preparado:
$message = "Your registration pin code is $otp"; 
OBSERVAÇÃO: é necessário usar um modelo aprovado para o envio de uma mensagem unidirecional usando a API da Twilio para WhatsApp. Clique aqui para saber mais sobre os modelos para WhatsApp. A sandbox do WhatsApp inclui modelos predefinidos, um deles é: Your {{1}} code is {{2}} (Seu código {{1}} é {{2}})
Este é o modelo em uso no momento, no qual {{1}} e {{2}} são espaços reservados para serem substituídos dinamicamente; neste caso, eles são substituídos por registration e $otp respectivamente.
Em seguida, usando a instância do Twilio Client, a mensagem de modelo é enviada ao destinatário:
$client->messages->create("whatsapp:$recipient", array('from' => "whatsapp:$twilio_whatsapp_number", 'body' => $message)); 
O método messages→create() aceita dois argumentos de um destinatário da mensagem e uma matriz com as propriedades de from e body, sendo que from é o seu número de telefone da Twilio aprovado para WhatsApp e body é a mensagem que será enviada ao destinatário.
OBSERVAÇÃO: para o dizer ao SDK da Twilio que envie essa mensagem pelo WhatsApp, você deve prefixar o whatsapp: ao número de telefone do destinatário e, também, ao número do WhatsApp da Twilio. Caso não esteja prefixado, a mensagem será enviada como um SMS comum ao destinatário.
Atualizar a visualização
Neste ponto, você já deve ter modificado com sucesso a lógica de registro com suporte para também enviar a OTP aos seus usuários pelo WhatsApp. Agora, você precisa atualizar a visualização para incluir o campo phone_number ao formulário de registro. Abra resources/views/auth/register.blade.php e faça as seguintes alterações no código:
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Register') }}</div> <div class="card-body"> <form method="POST" action="{{ route('register') }}"> @csrf <div class="form-group row"> <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label> <div class="col-md-6"> <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus> @error('name') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="form-group row"> <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email"> @error('email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password"> @error('password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="form-group row"> <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label> <div class="col-md-6"> <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password"> </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Phone Number') }}</label> <div class="col-md-6"> <input id="phone_number" type="tel" class="form-control @error('phone_number') is-invalid @enderror" value="{{old('phone_number')}}" name="phone_number" required> @error('phone_number') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="form-group row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Send OTP') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection 
Testar
Para testar seu aplicativo, abra um terminal e execute o seguinte comando:
 $ php artisan serve 
Ao fazê-lo com sucesso, você verá sua porta e URL localhost, pela qual é possível acessar o aplicativo Laravel. Ela geralmente é 127.0.0.1:8000. Em seguida, navegue até a página de registro e preencha o formulário. Após isso, clique no botão Send OTP (Enviar OTP) para receber uma breve mensagem do WhatsApp com sua OTP.
Conclusão
Agora que concluiu este tutorial, você aprendeu com sucesso a enviar notificações do WhatsApp pelo seu aplicativo Laravel e também viu como modificar a lógica de registro de autenticação com suporte do Laravel. Se você quiser dar uma olhada no código-fonte completo deste tutorial, ele está disponível no Github.
Você pode ir além e modificar o processo de autenticação para verificar a OTP enviada ao seu usuário antes de conceder a ele acesso ao aplicativo. Também é possível obter mais informações sobre como proteger seu aplicativo Laravel usando o Twilio Authy aqui.
Adoraria esclarecer as suas dúvidas sobre este tutorial. Entre em contato comigo via:
Este artigo foi traduzido do original "Sending One-time Passwords in WhatsApp using PHP, Laravel, and the Twilio API for WhatsApp". Enquanto melhoramos nossos processos de tradução, adoraríamos receber seus comentários em [email protected] - contribuições valiosas podem render brindes da Twilio.