Skip to main content

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 NameValueDescription
X-Hesda-Eventtransaction.updateTipe 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

AttributeTypeDescription
transaction_idstringID unik transaksi.
product_namestringNama produk yang ditransaksikan.
customer_nostringNomor pelanggan/tujuan transaksi.
snstringSerial number (kosong jika gagal).
statusstringStatus transaksi (success/failed/pending).
messagestringPesan keterangan transaksi.

Verifikasi Signature

Untuk keamanan, setiap webhook dilengkapi dengan signature yang harus diverifikasi menggunakan SHA256 HMAC.

Cara Kerja Signature

  1. Webhook payload (raw JSON body) di-hash menggunakan SHA256 dengan secret key
  2. Hash tersebut dikirim melalui header X-Hesda-Signature
  3. 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 CodeDescription
200Webhook berhasil diterima dan diproses
400Bad request (payload tidak valid)
401Unauthorized (signature tidak valid)
500Internal server error