Webhook Delivery Queue Item
Creates a queued webhook delivery record with payload hash and retry metadata.
Function signature
ogBuildWebhookDeliveryItem(event = array(), options = array())
Categories
- APIs and Webhooks
Parameters
eventEvent data with target_url, event_type, payload, and optional resource_id. Recognized keys: `event_type`, `payload`, `target_url`.optionsDelivery options including secret, max_attempts, and timeout_seconds. Recognized keys: `max_attempts`, `secret`.Return value
Short public-safe status message.
- delivery_id
- target_url
- event_type
- payload_json
- payload_hash
- signature
- attempt_count
- max_attempts
- created_at
- next_attempt_at
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, policy arrays, URLs, signatures, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Creates a queued outbound webhook delivery record.
*
* The payload is JSON encoded, hashed, and optionally HMAC signed. Secrets
* are never stored in the returned queue data.
*
* @param array $event Event data with target_url, event_type, payload, and optional resource_id.
* @param array $options Delivery options including secret, max_attempts, and timeout_seconds.
* @return array Queue-ready webhook delivery data.
*/
function ogBuildWebhookDeliveryItem($event = array(), $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($event)) {
$result['message'] = 'Event data must be an array.';
return $result;
}
if (!is_array($options)) {
$options = array();
}
$target_url = '';
if (!empty($event['target_url'])) {
$target_url = trim((string)$event['target_url']);
}
if (filter_var($target_url, FILTER_VALIDATE_URL) === false) {
$result['message'] = 'Webhook target URL is invalid.';
return $result;
}
if (stripos($target_url, 'https://') !== 0) {
$result['message'] = 'Webhook target URL must use HTTPS.';
return $result;
}
$event_type = '';
if (!empty($event['event_type'])) {
$event_type = preg_replace('/[^a-zA-Z0-9_.-]/', '', (string)$event['event_type']);
}
if (empty($event_type)) {
$result['message'] = 'Webhook event type is required.';
return $result;
}
$payload = array();
if (!empty($event['payload']) && is_array($event['payload'])) {
$payload = $event['payload'];
}
$delivery_id = bin2hex(random_bytes(16));
$created_at = time();
$body = array(
'id' => $delivery_id,
'event_type' => $event_type,
'created_at' => $created_at,
'payload' => $payload
);
$payload_json = json_encode($body);
if ($payload_json === false) {
$result['message'] = 'Webhook payload could not be encoded.';
return $result;
}
$payload_hash = hash('sha256', $payload_json);
$signature = '';
if (!empty($options['secret'])) {
$signature = hash_hmac('sha256', $created_at . '.' . $payload_json, (string)$options['secret']);
}
$max_attempts = 5;
if (!empty($options['max_attempts'])) {
$max_attempts = (int)$options['max_attempts'];
}
if ($max_attempts < 1) {
$max_attempts = 1;
}
$result['success'] = true;
$result['message'] = 'Webhook delivery item built.';
$result['data'] = array(
'delivery_id' => $delivery_id,
'target_url' => $target_url,
'event_type' => $event_type,
'payload_json' => $payload_json,
'payload_hash' => $payload_hash,
'signature' => $signature,
'attempt_count' => 0,
'max_attempts' => $max_attempts,
'created_at' => $created_at,
'next_attempt_at' => $created_at
);
return $result;
}