Panduan ini menjelaskan arsitektur dan langkah pengiriman kode verifikasi satu kali (One-Time Password) ke WhatsApp pelanggan secara otomatis saat proses registrasi, login, atau transaksi sensitif.
1. Pratinjau Pesan OTP di Layar Pengguna
Tampilan template resmi kategori AUTHENTICATION dengan tombol Salin Kode:
CODE
1┌──────────────────────────────────────────────┐
2│ 🔐 Kode Keamanan Akun │
3│ │
4│ Kode verifikasi PFNApp Anda adalah: *492019* │
5│ Berlaku selama 5 menit. Jangan berikan kode │
6│ ini kepada siapa pun, termasuk pihak kami. │
7│ │
8│ ──────────────────────────────────────────── │
9│ [ 📋 Salin Kode: 492019 ] │
10│ 14:20 ✓✓ │
11└──────────────────────────────────────────────┘
2. Persiapan Template & Kebutuhan (1 Menit)
- Buka menu Console > WhatsApp > Templates (
/console/whatsapp/templates). - Klik Buat Template:
- Nama Template:
otp_auth_code - Kategori:
AUTHENTICATION - Bahasa: Indonesian (
id) - Tipe Tombol:
OTP / COPY_CODE
- Nama Template:
- Simpan dan tunggu status template disetujui (umumnya instan).

3. Contoh Implementasi Pengiriman OTP
Kirimkan HTTP POST ke /api/whatsapp/messages dengan parameter template otp_auth_code:
Node.js / TypeScript (Next.js / Express Backend)
TYPESCRIPT
1interface SendOtpOptions {
2 phoneNumber: string
3 otpCode: string
4}
5
6export async function sendWhatsAppOtp({
7 phoneNumber,
8 otpCode,
9}: SendOtpOptions) {
10 const response = await fetch("https://pfnapp.id/api/whatsapp/messages", {
11 method: "POST",
12 headers: {
13 Authorization: `Bearer ${process.env.PFN_WHATSAPP_API_KEY}`,
14 "Content-Type": "application/json",
15 },
16 body: JSON.stringify({
17 to: phoneNumber, // contoh: "+6281234567890"
18 type: "template",
19 template: {
20 name: "otp_auth_code",
21 language: { code: "id" },
22 components: [
23 {
24 type: "body",
25 parameters: [
26 { type: "text", text: otpCode }, // Variabel {{1}} di body teks
27 ],
28 },
29 {
30 type: "button",
31 sub_type: "copy_code",
32 index: "0",
33 parameters: [
34 { type: "text", text: otpCode }, // Parameter kode pada tombol Salin Kode
35 ],
36 },
37 ],
38 },
39 }),
40 })
41
42 if (!response.ok) {
43 const errorData = await response.json()
44 throw new Error(`Gagal mengirim OTP: ${JSON.stringify(errorData)}`)
45 }
46
47 return await response.json()
48}
PHP / Laravel (Service Class)
PHP
1namespace App\Services;
2
3use Illuminate\Support\Facades\Http;
4
5class WhatsAppOtpService
6{
7 public function sendOtp(string $phoneNumber, string $otpCode): array
8 {
9 $response = Http::withToken(config('services.pfn.whatsapp_key'))
10 ->post('https://pfnapp.id/api/whatsapp/messages', [
11 'to' => $phoneNumber,
12 'type' => 'template',
13 'template' => [
14 'name' => 'otp_auth_code',
15 'language' => ['code' => 'id'],
16 'components' => [
17 [
18 'type' => 'body',
19 'parameters' => [
20 ['type' => 'text', 'text' => $otpCode],
21 ],
22 ],
23 [
24 'type' => 'button',
25 'sub_type' => 'copy_code',
26 'index' => '0',
27 'parameters' => [
28 ['type' => 'text', 'text' => $otpCode],
29 ],
30 ],
31 ],
32 ],
33 ]);
34
35 return $response->throw()->json();
36 }
37}
Python (FastAPI / Django Backend)
PYTHON
1import os
2import requests
3
4def send_whatsapp_otp(phone_number: str, otp_code: str) -> dict:
5 url = "https://pfnapp.id/api/whatsapp/messages"
6 headers = {
7 "Authorization": f"Bearer {os.getenv('PFN_WHATSAPP_API_KEY')}",
8 "Content-Type": "application/json",
9 }
10 payload = {
11 "to": phone_number,
12 "type": "template",
13 "template": {
14 "name": "otp_auth_code",
15 "language": {"code": "id"},
16 "components": [
17 {
18 "type": "body",
19 "parameters": [{"type": "text", "text": otp_code}],
20 },
21 {
22 "type": "button",
23 "sub_type": "copy_code",
24 "index": "0",
25 "parameters": [{"type": "text", "text": otp_code}],
26 },
27 ],
28 },
29 }
30
31 res = requests.post(url, json=payload, headers=headers)
32 res.raise_for_status()
33 return res.json()
4. Rekomendasi Keamanan & Best Practices
- Masa Berlaku Kode (TTL): Simpan hash kode OTP di memory cache (Redis) dengan TTL maksimal 5 menit.
- Pembatasan Upaya (Rate Limiting): Batasi request pengiriman OTP maksimal 3 kali per nomor dalam rentang waktu 10 menit untuk mencegah spam dan tagihan tak terduga.
- Format Nomor E.164: Pastikan backend Anda menormalisasi input pengguna (misal: otomatis mengubah
0812...menjadi+62812...sebelum request dikirim).