handle method

Future<WebhookHandleResult> handle({
  1. required String rawBody,
  2. required Map<String, String> headers,
  3. String? path,
  4. bool verify = true,
})

Verify (when a secret is configured), parse, normalise, and dispatch.

Throws NorbixWebhookSignatureError on a bad signature or guard mismatch, and NorbixWebhookParseError on a malformed body.

Implementation

Future<WebhookHandleResult> handle({
  required String rawBody,
  required Map<String, String> headers,
  String? path,
  bool verify = true,
}) async {
  final dh = parseWebhookHeaders(headers);

  bool? verified;
  if (verify && _secret != null) {
    final check = verifySignature(
      secret: _secret,
      rawBody: rawBody,
      signature: dh.signature,
      timestamp: dh.timestamp,
      toleranceSeconds: _toleranceSeconds,
    );
    if (!check.ok) {
      throw NorbixWebhookSignatureError(check.reason ?? 'Invalid signature');
    }
    verified = true;
  }

  final envelope = _parseEnvelope(rawBody);

  if (_projectId != null && envelope.projectId != _projectId) {
    throw NorbixWebhookSignatureError(
      'delivery projectId ${envelope.projectId} does not match configured $_projectId',
    );
  }
  if (_accountId != null && envelope.accountId != _accountId) {
    throw NorbixWebhookSignatureError(
      'delivery accountId ${envelope.accountId} does not match configured $_accountId',
    );
  }

  final normalized = normalizeWebhook(envelope);
  final event = WebhookEvent(
    name: envelope.event,
    deliveryId: envelope.id,
    createdOn: envelope.createdOn,
    triggerId: envelope.triggerId,
    correlationId: null,
    accountId: dh.accountId ?? envelope.accountId,
    projectId: dh.projectId ?? envelope.projectId,
    integrationId: dh.integrationId,
    destinationId: dh.destinationId,
    verified: verified,
    metadata: normalized.metadata,
    raw: envelope,
  );
  final ctx = WebhookContext(
    path: path,
    verified: verified,
    accountId: dh.accountId ?? envelope.accountId,
    projectId: dh.projectId ?? envelope.projectId,
    integrationId: dh.integrationId,
    destinationId: dh.destinationId,
  );

  var handled = false;
  final handler = _handlers[envelope.event];
  if (handler != null) {
    await handler(normalized.payload, event);
    handled = true;
  }
  for (final raw in _onAll[envelope.event] ?? const []) {
    await raw(envelope, ctx);
  }

  return WebhookHandleResult(
    event: envelope.event,
    deliveryId: envelope.id,
    verified: verified,
    handled: handled,
    triggerId: envelope.triggerId,
  );
}