Implementasi Phone Number Verification dengan Twilio Verify di Laravel 9
Tags: tutorials
Published: 2023-07-09 09:42:10

---
title: Implementasi Phone Number Verification dengan Twilio Verify di Laravel 9
published: true
date: 2022-03-24 23:22:50 UTC
tags: Tutorials
canonical_url: https://divisidev.com/post/phone-number-verification-twilio-laravel
---

 **Twilio Verify: User Verification API** - Verify merupakan salah satu service yang disediakan oleh Twilio, service ini bekerja untuk menangkal penipuan dan melindungi akun user. Dan dengan twilio verify, kita dapat dengan cepat memverifikasi user via SMS, voice, TOTP, push dan email. Pada artikel ini, saya akan membagikan cara mengimplementasikan Twilio Verify untuk membuat verifikasi akun. Jadi skenarionya, kita akan membuat authentication menggunakan nomor handphone dan setiap user yang mendaftar harus dapat diverifikasi.

Oke, mari kita langsung saja ke step by stepnya: 👇

## Step 1: Install Laravel

```
//via Laravel Installer
composer global require laravel/installer
laravel new laravel-twilio-verify

//via Composer
composer create-project laravel/laravel laravel-twilio-verify
```

Langkah pertama yang harus kita lakukan tentu saja adalah menginstall laravel. Ada beberapa cara yang bisa dilakukan untuk menginstall laravel, diantaranya adalah dengan menggunakan composer atau laravel installer. Jika kamu sudah menginstall laravel installer, kamu bisa langsung saja menjalankan perintah  **laravel new laravel-twilio-verify**. Dan jika kamu tidak menggunakan laravel installer atau terbiasa menggunakan composer, kamu bisa menjalankan perintah  **composer create-project laravel/laravel laravel-twilio-verify**.

Setelah berhasil menginstall laravel, sekarang kita bisa menjalankan perintah `php artisan serve`, lalu buka pada browser dengan URL 127.0.0.1:{port} atau laravel-twilio-verify.test.

```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_twilio_verify
DB_USERNAME=root
DB_PASSWORD=
```

Oke, setelah menyelesaikan step pertama, lanjutkan dengan membuat database baru dan jangan lupa untuk menyesuaikan  **DB\_DATABASE**  pada file .env.

## Step 2: Install Laravel UI

```
composer require laravel/ui
php artisan ui bootstrap --auth
npm install && npm run dev
```

Kemudian, kita perlu auth preset. Untuk itu, disini saya akan menggunakan laravel ui package. Silahkan jalankan perintah seperti di atas secara berurutan untuk menginstall package tersebut pada project laravel kita.

## Step 3: Setup Twilio Verify Service

Pada step ketigaini, kita akan melakukan set up Twilio pada laravel project kita. Jika kamu belum mendaftar akun Twilio, silahkan melakukan pendaftaran terlebih dahulu di situs resmi [Twilio.com](https://www.twilio.com/referral/8gkinp "Twilio.com") atau silahkan [klik link disini](https://www.twilio.com/referral/8gkinp "klik link disini"). Isi data pada beberapa input fields yang tersedia seperti First Name, Last Name, Email dan Password.

![Twilio Verify Service](https://divisidev.com/storage/photos/1/twilio-verify-service.PNG)

Kemudian, masuk pada product verfiy/services dan silahkan buat service baru. Setelah kamu menambahkan friendly name seperti di atas dan klik create button, maka kamu akan mendapatkan service id. Simpan service id tersebut untuk kita tambahkan pada file .env nantinya.

```
composer require twilio/sdk
```

Nah, sebelum mengimplementasi Twilio pada laravel project kita, ada hal yang harus kita lakukan yaitu menginstall Twilio SDK. Silahkan install Twilio SDK menggunakan perintah composer seperti di atas.

```
TWILIO_AUTH_SID="AC045b168ea3fad122bb8206dcb"
TWILIO_AUTH_TOKEN="cb6f96cd2e744f9b08112520"
TWILIO_VERIFY_SID="VAe74cefd2d8d146ba3e30c89fd"
```

Selanjutnya, kita perlu menambahkan beberapa variable baru pada file .env kita. Tambahkan variable seperti di atas pada file .env dan sesuaikan valuenya dengan data dari akun Twilio kamu.

## Step 4: Setup Model & Migration

```
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('phone_number')->unique();
        $table->boolean('isVerified')->default(false);
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}
```

Oke, selanjutnya kita perlu melakukan set up pada file users migration. Disini kita hanya perlu menambahkan dua column yaitu phone\_number dan isVerified. Kenapa kita perlu menambahkan kedua column tersebut? Karena seperti yang telah saya jelaskan sebelumnya, pada artikel ini kita mengimplementasikan twilio verify service untuk membuat phone number verification di laravel.

> Selain menambahkan field baru, dan pada artikel ini tujuannya adalah untuk implementasi phone number verification dengan twilio, jadi field email dan email\_verified\_at bisa kita hapus.

```
php artisan migrate
```

Jika sudah memperbarui file users migration, sekarang kita bisa menjalankan perintah artisan migrate untuk memigrasi file-file migration menjadi table-table di database yang telah kita buat sebelumnya.

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

Karena kita mengubah file default users migration dari laravel, maka kita juga perlu menyesuaikannya pada file User model. Silahkan buka file models/User.php, sesuaikan kode menjadi seperti di atas pada method $fillable.

## Step 5: Setup RegisterController

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

Memasuki step ke lima, kali ini kita akan bekerja pada RegisterController.php. Silahkan buka file tersebut yang terletak di direktori app/Http/Controllers/Auth. Karena kita melakukan perubahan pada preset yang telah disediakan oleh laravel ui, jadi kita juga harus memperbarui beberapa hal pada RegisterController.php. Pertama, ubah validatornya menjadi contoh kode di atas. Disini kita mengubah validator untuk email menjadi phone\_number.

```
    protected function create(array $data)
    {
        $sid = env("TWILIO_AUTH_SID");
        $token = env("TWILIO_AUTH_TOKEN");
        $twilio_verify_sid = env("TWILIO_VERIFY_SID");
        
        $twilio = new Client($sid, $token);
        
        $twilio->verify->v2->services($twilio_verify_sid)
            ->verifications
            ->create($data['phone_number'], "sms");

        User::create([
            'name' => $data['name'],
            'phone_number' => $data['phone_number'],
            'password' => Hash::make($data['password']),
        ]);

        return redirect()->route('verify')
                ->with(['phone_number' => $data['phone_number']]);
    }
```

Kemudian pada function create, ubah kodenya menjadi seperti di atas. Disini kita menambahkan pengaturan untuk Twilio service, dan mengubah request data yang akan diinputkan ke table users.

```
    protected function verify(Request $request)
    {
        $data = $request->validate([
            'verification_code' => ['required', 'numeric'],
            'phone_number' => ['required', 'string'],
        ]);
        
        $sid = env("TWILIO_AUTH_SID");
        $token = env("TWILIO_AUTH_TOKEN");
        $twilio_verify_sid = env("TWILIO_VERIFY_SID");
        
        $twilio = new Client($sid, $token);
        
        $verification = $twilio->verify->v2->services($twilio_verify_sid)
            ->verificationChecks
            ->create($data['verification_code'], array('to' => $data['phone_number']));
        
            if ($verification->valid) {
                $user = tap(User::where('phone_number', $data['phone_number']))->update(['isVerified' => true]);
                Auth::login($user->first());
                return redirect()->route('home')
                    ->with(['message' => 'Your account has been verified']);
            }

        return back()->with([
            'phone_number' => $data['phone_number'],
            'error' => 'Invalid verification code entered!'
        ]);
    }
```

Kemudian, tambahkan kode baru yaitu function verify untuk melakukan pekerjaan verifikasi akun dengan nomor handphone nantinya. Copy code seperti di atas, lalu paste pada file RegisterController.php.

```
public function register(Request $request)
{
    $this->validator($request->all())->validate();
    event(new Registered($user = $this->create($request->all())));
    if ($response = $this->registered($request, $user)) {
        return $response;
    }
    return $request->wantsJson()
                ? new JsonResponse([], 201)
                : redirect()->route('verify')->with(['phone_number' => $request->phone_number]);
}
```

Nah, selain menambahkan function verify, kita juga perlu menambahkan function register seperti di atas. By the way, kode tersebut merupakan bawaan dari laravel ui, namun kita akan overide kode tersebut pada RegisterController.php.

## Step 6: Define Route

```
Route::get('/verify', function () {
    return view('auth.verify');
})->name('verify');

Route::post('/verify', [App\Http\Controllers\Auth\RegisterController::class,'verify'])->name('verify');
```

Nah, setelah membuat controller, sekarang kita harus menambahkan route baru di file web.php. Copy code di atas, dan tambahkan pada routes/web.php.

## Step 7: Setup View

**register.blade.php**

```
@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="row mb-3">
                            <label for="name" class="col-md-4 col-form-label text-md-end">{{ __('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="row mb-3">
                            <label for="phone_number" class="col-md-4 col-form-label text-md-end">{{ __('Phone Number') }}</label>

                            <div class="col-md-6">
                                <input id="phone_number" type="tel" 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>

                        <div class="row mb-3">
                            <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('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="row mb-3">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('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="row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```

Setelah membuat controller dan menambahkan route, sekarang kita perlu mengubah file view bawaan dari laravel ui package. Silahkan buka file resources/views/auth/register.blade.php, ubah kode yang ada menjadi seperti di atas. Pada file ini, kita hanya mengubah email address input field menjadi phone number.

**verify.blade.php**

```
@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">Please enter the OTP sent to your number: {{session('phone_number')}}</div>
                <div class="card-body">
                    @if (session('error'))
                    <div class="alert alert-danger" role="alert">
                        {{session('error')}}
                    </div>
                    @endif
                    <form action="{{route('verify')}}" method="post">
                        @csrf
                        <div class="form-group row mb-3">
                            <label for="verification_code"
                                class="col-md-4 col-form-label text-md-right">{{ __('Phone Number') }}</label>
                            <div class="col-md-6">
                                <input type="hidden" name="phone_number" value="{{session('phone_number')}}">
                                <input id="verification_code" type="tel"
                                    class="form-control @error('verification_code') is-invalid @enderror"
                                    name="verification_code" value="{{ old('verification_code') }}" required>
                                @error('verification_code')
                                <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">
                                    {{ __('Verify Phone Number') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```

File view yang berikutnya adalah verify.blade.php. Silahkan buka file tersebut, lalu ubah kodenya menjadi seperti di atas. Di file ini, kita menyertakan input hidden yang mempunyai value phone number dari yang diisi user saat melakukan proses registrasi.

## Testing

![testing register](https://divisidev.com/storage/photos/1/laravel-twilio-register.PNG)

Oke, setelah melalui proses-proses di atas, sekarang merupakan waktunya untuk testing. Silahkan jalankan laravel project kamu, lalu buka di browser dengan 127.0.0.1:{port} atau bisa juga dengan seperti laravel-twilio-verify.test. Buka halaman register dan cobalah untuk register akun baru. \*Untuk phone number input field, pastikan mengisinya dengan format +62.

![twilio sms chanel](https://divisidev.com/storage/photos/1/twilio-sms-chanel.jpg)

Jika proses registrasi berhasil, maka akan ada sms masuk yang berisi kode verifikasi seperti di atas.

![laravel twilio verify phone number](https://divisidev.com/storage/photos/1/laravel-twilio-verify.PNG)

Setelah proses registrasi pada langkah sebelumnya berhasil, maka kamu akan diarahkan ke halaman verify phone number seperti di atas. Silahkan isi input field tersebut dengan kode yang telah dikirim via sms. Jika akun berhasil diverifikasi, maka kamu akan diarahkan ke halaman home dan pada table users, isVerified akan berubah menjadi 1 atau true.

### Bonus

```
$twilio->verify->v2->services($twilio_verify_sid)
    ->verifications
    ->create($data['phone_number'], "whatsapp");
```

Jika kamu tidak ingin kode verifikasi dikirim via sms, mungkin kamu bisa mencoba opsi chanel whatsapp. Caranya, buka file RegisterController.php, lalu pada function create silahkan ubah chanelnya menjadi whatsapp atau seperti kode di atas.

![twilio whatsapp chanel](https://divisidev.com/storage/photos/1/twilio-whatsapp-chanel.jpg)

Nah, sekarang jika kamu coba register akun lagi, kode verifikasi akan dikirim via whatsapp seperti gambar di atas.

```
$phone_number = $data['phone_number'];
if ($data['phone_number'][0] == "0") {
    $phone_number = substr($phone_number, 1);
}

if ($phone_number[0] == "8") {
    $phone_number = "62" . $phone_number;
}
```

Ingin mengubah format input pada phone number input field? mungkin format input saat ini yaitu harus menyertakan kode negara seperti +62 dinilai kurang user friendly, kamu bisa menambahkan kode seperti di atas pada function create di RegisterController.php. Dengan kode tersebut, jika user menginputkan seperti 0821234567 maka akan dikonversi menjadi 62821234567.

```
protected function create(array $data)
{
    $sid = env("TWILIO_AUTH_SID");
    $token = env("TWILIO_AUTH_TOKEN");
    $twilio_verify_sid = env("TWILIO_VERIFY_SID");

    $phone_number = $data['phone_number'];
    if ($data['phone_number'][0] == "0") {
        $phone_number = substr($phone_number, 1);
    }

    if ($phone_number[0] == "8") {
        $phone_number = "62" . $phone_number;
    }

    $twilio = new Client($sid, $token);
    
    $twilio->verify->v2->services($twilio_verify_sid)
        ->verifications
        ->create('+'.$phone_number, "whatsapp");

    User::create([
        'name' => $data['name'],
        'phone_number' => $phone_number,
        'password' => Hash::make($data['password']),
    ]);

    return redirect()->route('verify')
            ->with(['phone_number' => $data['phone_number']]);
}
```

Dan sekarang, function create pada RegisterController menjadi seperti kode di atas. 

Demikianlah artikel tentang implementasi phone number verification dengan twilio verify service di laravel 9 kali ini. Jika kamu punya saran, kritik, masukan atau apapun itu yang ingin didiskusikan, silahkan tulis komentar teman-teman pada form komentar di bawah ini. Semoga artikel ini dapat membantu dan sampai jumpa pada artikel berikutnya. Happy coding 👨‍💻

 

**Credit: [Device illustrations by Storyset](https://storyset.com/device "Device illustrations by Storyset")**