feat(whatsapp service): menambahkan zawa api di config service

-membuat sesi dan generate qr code
-membuat model dan migrasi
-menambahkan permission
This commit is contained in:
Yoga Pangestu 2025-10-28 23:27:32 +07:00
parent f8129deaa0
commit 5c7060565b
8 changed files with 205 additions and 0 deletions

View File

@ -0,0 +1,98 @@
<?php
namespace App\Livewire\Studio\Setting;
use App\Models\Whatsapp as WhatsappModel;
use App\Traits\WithToast;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Livewire\Attributes\Title;
use Livewire\Component;
#[Title('Whatsapp')]
class Whatsapp extends Component
{
use WithToast;
public array $whatsapp = [];
public function mount(): void
{
$whatsapp = WhatsappModel::first();
$this->whatsapp = [
'id' => $whatsapp?->id,
'zawa_id' => $whatsapp?->zawa_id,
'session_id' => $whatsapp?->session_id,
'qr_code' => $whatsapp?->qr_code,
];
}
public function createSession(): void
{
try {
$response = Http::post(config('services.zawa.url').'/authorize');
if ($response->successful()) {
$data = $response->json();
WhatsappModel::updateOrCreate(
['zawa_id' => $data['id']],
[
'session_id' => $data['sessionId'],
]
);
$this->whatsapp['zawa_id'] = $data['id'];
$this->whatsapp['session_id'] = $data['sessionId'];
$this->toast('Berhasil membuat sesi WhatsApp');
} else {
$this->toast('Gagal membuat sesi WhatsApp', 'Gagal', 'danger');
}
} catch (\Throwable $e) {
Log::error($e);
$this->toast('Gagal membuat sesi WhatsApp, silakan coba lagi.', 'Gagal', 'danger');
}
}
public function generateQrCode(): void
{
try {
$response = Http::withHeaders([
'id' => $this->whatsapp['zawa_id'],
'session-id' => $this->whatsapp['session_id'],
])->get(config('services.zawa.url').'/qrcode');
if ($response->successful()) {
$data = $response->json();
$qrBase64 = 'data:image/png;base64,'.$data['qrcode'];
WhatsappModel::updateOrCreate(
['zawa_id' => $this->whatsapp['zawa_id']],
[
'session_id' => $this->whatsapp['session_id'],
'qr_code' => $qrBase64,
]
);
$this->whatsapp['qr_code'] = $qrBase64;
$this->toast('Berhasil generate QR Code WhatsApp');
} else {
$this->toast('Gagal generate QR Code, silakan coba lagi.', 'Gagal', 'danger');
}
} catch (\Throwable $e) {
Log::error($e);
$this->toast('Terjadi kesalahan saat generate QR Code,silakan hubungi Administrator.', 'Gagal', 'danger');
}
}
public function render()
{
return view('livewire.studio.setting.whatsapp', [
'pageTitle' => 'Whatsapp',
]);
}
}

10
app/Models/Whatsapp.php Normal file
View File

@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Whatsapp extends Model
{
protected $guarded = ['id'];
}

View File

@ -170,6 +170,13 @@ public function boot(): void
'match' => 'studio.setting.application',
'can' => 'view application settings',
],
[
'label' => 'Whatsapp',
'icon' => 'chat-bubble-oval-left-ellipsis',
'route' => 'studio.setting.whatsapp',
'match' => 'studio.setting.whatsapp',
'can' => 'view whatsapp settings',
],
],
],
];

View File

@ -35,4 +35,8 @@
],
],
'zawa' => [
'url' => env('ZAWA_API_URL'),
],
];

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('whatsapps', function (Blueprint $table) {
$table->id();
$table->string('zawa_id', 100);
$table->string('session_id', 100);
$table->text('qr_code')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('whatsapps');
}
};

View File

@ -108,6 +108,8 @@ public function run(): void
'view application settings',
'view whatsapp settings',
'view general settings',
'update general settings',

View File

@ -0,0 +1,52 @@
<flux:main>
<div class="flex justify-between items-center">
<div>
<flux:heading size="xl">{{ $pageTitle }}</flux:heading>
<flux:text>
Integrasikan WhatsApp untuk pengiriman invoice, kode verifikasi, serta
broadcast voucher atau informasi kepada pelanggan secara cepat dan efikien.
</flux:text>
</div>
</div>
<div class="mt-6 space-y-4">
<flux:callout icon="{{ $whatsapp['zawa_id'] ? 'check-circle' : 'link' }}"
color="{{ $whatsapp['zawa_id'] ? 'emerald' : 'gray' }}">
<flux:heading>Langkah 1: Buat Sesi WA</flux:heading>
<flux:callout.text>
Klik tombol untuk membuat sesi WhatsApp dan mendapatkan <code>sessionId</code>.
</flux:callout.text>
<x-slot name="actions">
@if (!$whatsapp['zawa_id'])
<flux:button wire:click="createSession">Buat Sesi</flux:button>
@else
<span class="text-sm text-emerald-600 font-medium"> Sesi sudah dibuat</span>
@endif
</x-slot>
</flux:callout>
<flux:callout icon="{{ $whatsapp['qr_code'] ? 'check-circle' : 'qr-code' }}"
color="{{ $whatsapp['qr_code'] ? 'emerald' : 'gray' }}"
class="{{ $whatsapp['zawa_id'] ? '' : 'opacity-50 pointer-events-none' }}">
<flux:heading>Langkah 2: Generate QR Code</flux:heading>
<flux:callout.text>
Gunakan <code>sessionId</code> untuk men-generate QR code yang akan discan di WhatsApp.
</flux:callout.text>
<x-slot name="actions">
@if (!$whatsapp['qr_code'] && $whatsapp['zawa_id'])
<flux:button wire:click="generateQrCode">Generate QR Code</flux:button>
@endif
</x-slot>
@if ($whatsapp['qr_code'])
<div class="mt-4 flex flex-col">
<img src="{{ $whatsapp['qr_code'] }}" alt="QR Code WhatsApp" class="w-56 h-56 rounded-lg shadow" />
<p class="mt-2 text-sm text-emerald-600 font-medium">Scan QR ini di WhatsApp</p>
</div>
@endif
</flux:callout>
</div>
</flux:main>

View File

@ -37,6 +37,7 @@
use App\Livewire\Studio\Setting\Application as ApplicationComponent;
use App\Livewire\Studio\Setting\Password as PasswordComponent;
use App\Livewire\Studio\Setting\Profile as ProfileComponent;
use App\Livewire\Studio\Setting\Whatsapp as WhatsappComponent;
use Illuminate\Support\Facades\Route;
Route::middleware('auth')->prefix('studio')->group(function () {
@ -159,4 +160,5 @@
});
Route::get('/settings/applications', ApplicationComponent::class)->name('studio.setting.application')->middleware('can:view application settings');
Route::get('/settings/whatsapp', WhatsappComponent::class)->name('studio.setting.whatsapp')->middleware('can:view whatsapp settings');
});