Webhook
Webhook digunakan untuk mengirimkan notifikasi real-time ke sistem Anda ketika terjadi perubahan status transaksi
Webhook Headers
Setiap request webhook yang dikirim akan menyertakan header khusus untuk identifikasi dan keamanan:
| Header Name | Value | Description |
|---|---|---|
| X-Hesda-Event | transaction.update | Tipe event yang terjadi |
| X-Hesda-Signature | {signature_hash} | Signature SHA256 untuk verifikasi keamanan |
Webhook Payload
Webhook akan mengirimkan data dalam format JSON:
{
"transaction_id": "faVfBMpLMJm0",
"product_name": "XX 5.000",
"customer_no": "0895xxx",
"sn": "1234567890",
"status": "success",
"message": "Transaksi Berhasil"
}
Payload Structure
| Attribute | Type | Description |
|---|---|---|
| transaction_id | string | ID unik transaksi. |
| product_name | string | Nama produk yang ditransaksikan. |
| customer_no | string | Nomor pelanggan/tujuan transaksi. |
| sn | string | Serial number (kosong jika gagal). |
| status | string | Status transaksi (success/failed/pending). |
| message | string | Pesan keterangan transaksi. |
Verifikasi Signature
Untuk keamanan, setiap webhook dilengkapi dengan signature yang harus diverifikasi menggunakan SHA256 HMAC.
Cara Kerja Signature
- Webhook payload (raw JSON body) di-hash menggunakan SHA256 dengan secret key
- Hash tersebut dikirim melalui header
X-Hesda-Signature - Sistem Anda harus memverifikasi signature untuk memastikan webhook berasal dari server yang valid
Keamanan Webhook
Selalu verifikasi signature sebelum memproses webhook untuk mencegah request palsu. Jangan pernah membagikan secret key Anda.
Implementasi di CodeIgniter 3
Berikut contoh implementasi webhook handler di CodeIgniter 3:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Webhook extends CI_Controller {
// Secret key dari dashboard PPOB
private $secret_key = 'your_secret_key_here';
public function __construct() {
parent::__construct();
}
public function handle() {
// Ambil headers
$event = $this->input->get_request_header('X-Hesda-Event');
$signature = $this->input->get_request_header('X-Hesda-Signature');
// Ambil raw body
$raw_body = file_get_contents('php://input');
// Verifikasi signature
if (!$this->verify_signature($raw_body, $signature)) {
log_message('error', 'Invalid webhook signature');
$this->output
->set_status_header(401)
->set_content_type('application/json')
->set_output(json_encode([
'status' => 'error',
'message' => 'Invalid signature'
]));
return;
}
// Parse JSON payload
$payload = json_decode($raw_body, true);
if (!$payload) {
log_message('error', 'Invalid JSON payload');
$this->output
->set_status_header(400)
->set_content_type('application/json')
->set_output(json_encode([
'status' => 'error',
'message' => 'Invalid payload'
]));
return;
}
// Proses webhook berdasarkan event
if ($event === 'transaction.update') {
$this->process_transaction_update($payload);
}
// Response success
$this->output
->set_status_header(200)
->set_content_type('application/json')
->set_output(json_encode([
'status' => 'success',
'message' => 'Webhook received'
]));
}
private function verify_signature($payload, $signature) {
// Generate signature dari payload
$expected_signature = hash_hmac('sha256', $payload, $this->secret_key);
// Bandingkan signature
return hash_equals($expected_signature, $signature);
}
private function process_transaction_update($payload) {
// Load model
$this->load->model('Transaction_model');
// Update status transaksi di database
$data = [
'status' => $payload['status'],
'sn' => $payload['sn'],
'message' => $payload['message'],
'updated_at' => date('Y-m-d H:i:s')
];
$this->Transaction_model->update_by_transaction_id(
$payload['transaction_id'],
$data
);
// Log webhook
log_message('info', 'Transaction updated: ' . $payload['transaction_id']);
// Kirim notifikasi ke user (opsional)
// $this->send_notification($payload);
}
}
Contoh Request dengan cURL
curl -X POST https://yourdomain.com/webhooks/ppob \
-H "Content-Type: application/json" \
-H "X-Hesda-Event: transaction.update" \
-H "X-Hesda-Signature: {generated_signature}" \
-d '{
"transaction_id": "faVfBMpLMJm0",
"product_code": "XXL5",
"product_name": "XX 5.000",
"customer_no": "0895xxx",
"price": 6150,
"sn": "1234567890",
"status": "success",
"message": "Transaksi Berhasil"
}'
Status Codes
Response yang harus dikembalikan:
| Status Code | Description |
|---|---|
| 200 | Webhook berhasil diterima dan diproses |
| 400 | Bad request (payload tidak valid) |
| 401 | Unauthorized (signature tidak valid) |
| 500 | Internal server error |