Skip to content
← Back to Functions
Code

Webhook Payload Builder

Builds outbound webhook payloads with event metadata, versioning, and stable IDs.

Function signature

ogBuildWebhookPayload(event_type, resource_data = array(), options = array())

Categories

  • APIs and Webhooks

Parameters

event_typeEvent type name.resource_dataResource payload data.optionsVersion, secret, and ID options. Recognized keys: `event_id`, `secret`, `version`.

Return value

Short public-safe status message.

  • payload
  • payload_json
  • signature
  • signature_header

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.
 */

/**
 * Builds outbound webhook payloads with event metadata, versioning, and stable IDs.
 *
 * This helper builds a payload array and optional HMAC signature. It does not send the webhook.
 *
 * @param string $event_type Event type name.
 * @param array $resource_data Resource payload data.
 * @param array $options Version, secret, and ID options.
 * @return array Webhook payload and optional signature metadata.
 */
function ogBuildWebhookPayload($event_type, $resource_data = array(), $options = array()) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	$event_type = preg_replace('/[^a-zA-Z0-9_.-]/', '', (string)$event_type);
	if (empty($event_type)) {
		$result['message'] = 'Event type is required.';
		return $result;
	}
	if (!is_array($resource_data)) {
		$result['message'] = 'Resource data must be an array.';
		return $result;
	}
	if (!is_array($options)) {
		$options = array();
	}

	$version = '1.0';
	if (!empty($options['version'])) {
		$version = preg_replace('/[^0-9.]/', '', (string)$options['version']);
	}
	if (empty($version)) {
		$version = '1.0';
	}

	$event_id = bin2hex(random_bytes(16));
	if (!empty($options['event_id'])) {
		$event_id = preg_replace('/[^a-zA-Z0-9_.-]/', '', (string)$options['event_id']);
	}
	$created_at = time();
	$payload = array(
		'event_id' => $event_id,
		'event_type' => $event_type,
		'version' => $version,
		'created_at' => $created_at,
		'data' => $resource_data
	);

	$payload_json = json_encode($payload);
	if ($payload_json === false) {
		$result['message'] = 'Webhook payload could not be encoded.';
		return $result;
	}

	$signature = '';
	if (!empty($options['secret'])) {
		$signature = hash_hmac('sha256', $created_at . '.' . $payload_json, (string)$options['secret']);
	}

	$signature_header = '';
	if (!empty($signature)) {
		$signature_header = 't=' . $created_at . ',v1=' . $signature;
	}

	$result['success'] = true;
	$result['message'] = 'Webhook payload built.';
	$result['data'] = array(
		'payload' => $payload,
		'payload_json' => $payload_json,
		'signature' => $signature,
		'signature_header' => $signature_header
	);

	return $result;
}