Aplikasi E-Commerce Laravel 6 #16: Integrasi Telegram Bot

Aplikasi E-Commerce Laravel 6 #16: Integrasi Telegram Bot

Pendahuluan

Membuat notifikasi dalam bentuk sosial chat akan lebih cepat tersampaikan kepada pemilik aplikasi karena di era ini orang-orang banyak menghabiskan waktunya dengan sosial media / chat. Opsi lain dalam menyampaikan informasi terkini selain menggunakan email, kita juga bisa melakukan integrasi telegram bot di Laravel sehingga informasi yang sifatnya harus segera ditanggapi dapat dilihat dalam bentuk Telegram message.

Serial membuat Aplikasi E-Commerce Laravel 6 kali ini akan membahas dua bagian, dimana pada bagian pertama adalah melanjutkan seri sebelumnya dalam merespon permintaan return atau refund dari customer, jadi kita akan membuat fitur untuk admin agar dapat menyetujui atau menolak permintaan tersebut. Bagian selanjutnya adalah integrasi bot telegram ketika customer melakukan permintaan return, sehingga secara otomatis pesan akan terkirim kepada pemilik aplikasi.

Baca Juga: Aplikasi E-Commerce Laravel 6 #15: Complaint & Return Order

Approve Return By Admin

Fitur ini terbilang cukup mudah untuk diselesaikan, karena hanya ada tiga tahapan yakni membuat tombol ke halaman detail return dari halaman list pesanan, kemudian menampilkan detail permintaan return dan yang terakhir adalah meng-update status pesanan terkait berdasarkan jawaban admin dalam menggapi permintaan tersebut, dalam hal ini adalah terima atau tolak.

Buka file index.blade.php yang berada di dalam folder resources/views/orders dan modifikasi kolom status menjadi.

<td>
    {!! $row->status_label !!} <br>
    @if ($row->return_count > 0)
        <a href="{{ route('orders.return', $row->invoice) }}">Permintaan Return</a>
    @endif
</td>

Kemudian buka file OrderController.php dan cari method index(), lalu tambahkan withCount() pada query yang ada di dalam method index.

public function index()
{
    $orders = Order::with(['customer.district.city.province'])
        ->withCount('return')
        ->orderBy('created_at', 'DESC');
  //CUKUP TAMBAHKAN WITHCOUNT

    //[.. CODE LAINNYA TIDAK BERUBAH ..]
}

Note: Fungsi di atas akan menghasilkan objek baru bernama return_count dengan value berdasarkan ada tidaknya data di table order_returns.

Masih dengan file yang sama, kita akan membuat method baru untuk me-load view detail return. Tambahkan method

public function return($invoice)
{
    $order = Order::with(['return', 'customer'])->where('invoice', $invoice)->first();
    return view('orders.return', compact('order'));
}

Dilanjutkan dengan membuat file return.blade.php di dalam folder orders dan masukkan tag berikut

@extends('layouts.admin')

@section('title')
    <title>Detail pesanan</title>
@endsection

@section('content')
<main class="main">
    <ol class="breadcrumb">
        <li class="breadcrumb-item">Home</li>
        <li class="breadcrumb-item active">View Order</li>
    </ol>
    <div class="container-fluid">
        <div class="animated fadeIn">
            <div class="row">
                <div class="col-md-12">
                    <div class="card">
                        <div class="card-header">
                            <h4 class="card-title">
                                Detail pesanan
                            </h4>
                        </div>
                        <div class="card-body">
                            <div class="row">
                                <div class="col-md-6">
                                    <h4>Detail Pelanggan</h4>
                                    <table class="table table-bordered">
                                        <tr>
                                            <th width="30%">Nama Pelanggan</th>
                                            <td>{{ $order->customer_name }}</td>
                                        </tr>
                                        <tr>
                                            <th>Telp</th>
                                            <td>{{ $order->customer_phone }}</td>
                                        </tr>
                                        <tr>
                                            <th>Alasan Return</th>
                                            <td>{{ $order->return->reason }}</td>
                                        </tr>
                                        <tr>
                                            <th>Rekening Pengembalian Dana</th>
                                            <td>{{ $order->return->refund_transfer }}</td>
                                        </tr>
                                        <tr>
                                            <th>Status</th>
                                            <td>{!! $order->return->status_label !!}</td>
                                        </tr>
                                    </table>
                                    
                                    <!-- BAGIAN PENTING HANYA PADA FORM DIBAWAH -->
                                    @if ($order->return->status == 0)
                                    <form action="{{ route('orders.approve_return') }}" onsubmit="return confirm('Kamu Yakin?');" method="post">
                                        @csrf
                                        <div class="input-group mb-3">
                                            <input type="hidden" name="order_id" value="{{ $order->id }}">
                                            <select name="status" class="form-control" required>
                                                <option value="">Pilih</option>
                                                <option value="1">Terima</option>
                                                <option value="2">Tolak</option>
                                            </select>
                                            <div class="input-group-prepend">
                                                <button class="btn btn-primary btn-sm">Proses Return</button>
                                            </div>
                                        </div>
                                    </form>
                                    @endif
                                </div>
                                <div class="col-md-6">
                                    <h4>Foto Barang Return</h4>
                                    <img src="{{ asset('storage/return/' . $order->return->photo) }}" class="img-responsive" height="200" alt="">
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</main>
@endsection

Untuk mempermudah proses penulisan, routing-nya di-skip dulu. Tugas kita saat ini adalah membuat method untuk meng-handle request terima atau tolak. Buka file OrderController.php dan tambahkan method

public function approveReturn(Request $request)
{
    $this->validate($request, ['status' => 'required']); //validasi status
    $order = Order::find($request->order_id); //query berdasarkan order_id
    $order->return()->update(['status' => $request->status]); //update status yang ada di table order_returns melalui order
    $order->update(['status' => 4]); //update status yang ada di table orders
    return redirect()->back();
}

Kemudian hubungkan method di atas ke dalam routing agar bisa diakses oleh user, buka file routes/web.php dan tambahkan line berikut di dalam route dengan group prefix orders

Route::get('/return/{invoice}', 'OrderController@return')->name('orders.return');
Route::post('/return', 'OrderController@approveReturn')->name('orders.approve_return');

Bagian terakhir adalah membuat Accessor untuk status_label, buka file OrderReturn.php dan modifikasi menjadi

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class OrderReturn extends Model
{
    protected $guarded = [];
    protected $appends = ['status_label'];

    public function getStatusLabelAttribute()
    {
        if ($this->status == 0) {
            return '<span class="badge badge-secondary">Menunggu Konfirmasi</span>';
        } elseif ($this->status == 2) {
            return '<span class="badge badge-danger">Ditolak</span>';
        }
        return '<span class="badge badge-success">Selesai</span>';
    }
}

Integrasi Bot Telegram

Telegram mendukung para developer untuk mengintegrasikan aplikasinya secara gratis, sehingga Telegram menyediakan API dalam memudahkan proses integrasi tersebut. Langkah awal sebelum mengintegrasikan aplikasi kita dengan bot Telegram, maka kita perlu membuat bot dari aplikasi Telegram itu sendiri.

Langkahnya sendiri cukup mudah, dari aplikasi Telegram, cari username BotFather kemudian klik start. Dari kotak chat, ketikkan /newbot dan ikuti instruksi dari Telegram yang meminta data terkait nama bot dan username yang diinginkan. Setelah semuanya selesai, Telegram akan mengirimkan token untuk mengakses HTTP API.

Integrasi Bot Telegram di Laravel akan kita mulai dari tahap menambahkan token ke dalam file .env

TELEGRAM_KEY=botAPIKEY

Note: Formatnya adalah kata bot diikuti dengan token yang kamu miliki.

Skenarionya adalah Bot akan mengirimkan pesan ketika permintaan return dikirimkan oleh customer, maka buka file Ecommerce/OrderController.php dan modifikasi method processReturn() menjadi

public function processReturn(Request $request, $id)
{
    $this->validate($request, [
        'reason' => 'required|string',
        'refund_transfer' => 'required|string',
        'photo' => 'required|image|mimes:jpg,png,jpeg'
    ]);

    $return = OrderReturn::where('order_id', $id)->first();
    if ($return) return redirect()->back()->with(['error' => 'Permintaan Refund Dalam Proses']);

    if ($request->hasFile('photo')) {
        $file = $request->file('photo');
        $filename = time() . Str::random(5) . '.' . $file->getClientOriginalExtension();
        $file->storeAs('public/return', $filename);

        OrderReturn::create([
            'order_id' => $id,
            'photo' => $filename,
            'reason' => $request->reason,
            'refund_transfer' => $request->refund_transfer,
            'status' => 0
        ]);
      
        //CODE BARU HANYA PADA BAGIAN INI SAJA
        $order = Order::find($id); //AMBIL DATA ORDER BERDASARKAN ID
        //KIRIM PESAN MELALUI BOT
        $this->sendMessage('#' . $order->invoice, $request->reason); 
        //CODE BARU HANYA PADA BAGIAN INI SAJA
        
        return redirect()->back()->with(['success' => 'Permintaan Refund Dikirim']);
    }
}

Masih dengan file yang sama, tambahkan kedua method baru berikut ini untuk berinteraksi dengan API Telegram.

//REUSABLE CURL AGAR TIDAK MENULISKAN CODE YANG SAMA BERULANG KALI
private function getTelegram($url, $params)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url . $params); 

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 3);
    $content = curl_exec($ch);
    curl_close($ch);
    return json_decode($content, true);
}

private function sendMessage($order_id, $reason)
{
    $key = env('TELEGRAM_KEY'); //AMBIL TOKEN DARI ENV
    //KEMUDIAN KIRIM REQUEST KE TELEGRAM UNTUK MENGAMBIL DATA USER YANG ME-LISTEN BOT KITA
    $chat = $this->getTelegram('https://api.telegram.org/'. $key .'/getUpdates', '');
    //JIKA ADA
    if ($chat['ok']) {
        //SAYA BERASUMSI PESAN INI HANYA DIKIRIM KE ADMIN, MAKA KITA TIDAK PERLU MELOOPING HASIL DARI GET DATA USER
        //CUKUP MENGAMBIL KEY 0 SAJA ATAU LIST YANG PERTAMA
        //UNTUK MENDAPATKAN CHAT_ID
        $chat_id = $chat['result'][0]['message']['chat']['id'];
        //TEKS YANG DIINGINKAN
        $text = 'Hai DaengWeb, OrderID ' . $order_id . ' Melakukan Permintaan Refund Dengan Alasan "'. $reason .'", Segera Dicek Ya!';
      
        //DAN KIRIM REQUEST KE TELEGRAM UNTUK MENGIRIMKAN PESAN
        return $this->getTelegram('https://api.telegram.org/'. $key .'/sendMessage', '?chat_id=' . $chat_id . '&text=' . $text);
    }
}

Sebelum melakukan proses uji coba, daftarkan user yang akan menerima chat dengan membuka bot kita atau mengakses t.me/nama_bot. Kemudian tap Start.

aplikasi e-commerce laravel 6 - integrasi bot telegram

[Issue] Show Return Status

Kesalahan dari artikel sebelumnya adalah kita tidak menampilkan status return sehingga customer tidak mengetahui feedback dari permintaan yang dikirimnya. Untuk mengatasinya sangat mudah, buka file index.blade.php yang ada di dalam folder resources/views/ecommerce/orders dan modifikasi kolom invoice menjadi

<td>
    <strong>{{ $row->invoice }}</strong><br>
    @if ($row->return_count == 1)
    <small>Return: {!! $row->return->status_label !!}</small>
    @endif
</td>

Baca Juga: Tips Mengelola Timestamps di Laravel

Kesimpulan

Artikel singkat dan padat ini kita belajar hal baru yakni bagaimana melakukan integrasi dengan pihak ketiga, dalam hal ini adalah integrasi bot Telegram. Selain itu, kita juga menyelesaikan fitur return yang sudah dimulai dari seri ke-15.

Adapun dokumentasi code dari artikel ini bisa dilihat di Github.

Category:
Share:

Comments