/opt/canhelp/node_modules/openai/resources/webhooks
NameSizeModeActions
index.d.mts680644editdlrm
index.d.mts.map1270644editdlrm
index.d.ts660644editdlrm
index.d.ts.map1260644editdlrm
index.js3060644editdlrm
index.js.map1510644editdlrm
index.mjs1530644editdlrm
index.mjs.map1360644editdlrm
webhooks.d.mts150420644editdlrm
webhooks.d.mts.map66010644editdlrm
webhooks.d.ts150390644editdlrm
webhooks.d.ts.map66000644editdlrm
webhooks.js55480644editdlrm
webhooks.js.map33170644editdlrm
webhooks.mjs53730644editdlrm
webhooks.mjs.map33250644editdlrm
Edit: /opt/canhelp/node_modules/openai/resources/webhooks/webhooks.mjs (5373B)
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. var _Webhooks_instances, _Webhooks_validateSecret, _Webhooks_getRequiredHeader; import { __classPrivateFieldGet } from "../../internal/tslib.mjs"; import { InvalidWebhookSignatureError } from "../../error.mjs"; import { APIResource } from "../../core/resource.mjs"; import { buildHeaders } from "../../internal/headers.mjs"; export class Webhooks extends APIResource { constructor() { super(...arguments); _Webhooks_instances.add(this); } /** * Validates that the given payload was sent by OpenAI and parses the payload. */ async unwrap(payload, headers, secret = this._client.webhookSecret, tolerance = 300) { await this.verifySignature(payload, headers, secret, tolerance); return JSON.parse(payload); } /** * Validates whether or not the webhook payload was sent by OpenAI. * * An error will be raised if the webhook payload was not sent by OpenAI. * * @param payload - The webhook payload * @param headers - The webhook headers * @param secret - The webhook secret (optional, will use client secret if not provided) * @param tolerance - Maximum age of the webhook in seconds (default: 300 = 5 minutes) */ async verifySignature(payload, headers, secret = this._client.webhookSecret, tolerance = 300) { if (typeof crypto === 'undefined' || typeof crypto.subtle.importKey !== 'function' || typeof crypto.subtle.verify !== 'function') { throw new Error('Webhook signature verification is only supported when the `crypto` global is defined'); } __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_validateSecret).call(this, secret); const headersObj = buildHeaders([headers]).values; const signatureHeader = __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_getRequiredHeader).call(this, headersObj, 'webhook-signature'); const timestamp = __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_getRequiredHeader).call(this, headersObj, 'webhook-timestamp'); const webhookId = __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_getRequiredHeader).call(this, headersObj, 'webhook-id'); // Validate timestamp to prevent replay attacks const timestampSeconds = parseInt(timestamp, 10); if (isNaN(timestampSeconds)) { throw new InvalidWebhookSignatureError('Invalid webhook timestamp format'); } const nowSeconds = Math.floor(Date.now() / 1000); if (nowSeconds - timestampSeconds > tolerance) { throw new InvalidWebhookSignatureError('Webhook timestamp is too old'); } if (timestampSeconds > nowSeconds + tolerance) { throw new InvalidWebhookSignatureError('Webhook timestamp is too new'); } // Extract signatures from v1, format // The signature header can have multiple values, separated by spaces. // Each value is in the format v1,. We should accept if any match. const signatures = signatureHeader .split(' ') .map((part) => (part.startsWith('v1,') ? part.substring(3) : part)); // Decode the secret if it starts with whsec_ const decodedSecret = secret.startsWith('whsec_') ? Buffer.from(secret.replace('whsec_', ''), 'base64') : Buffer.from(secret, 'utf-8'); // Create the signed payload: {webhook_id}.{timestamp}.{payload} const signedPayload = webhookId ? `${webhookId}.${timestamp}.${payload}` : `${timestamp}.${payload}`; // Import the secret as a cryptographic key for HMAC const key = await crypto.subtle.importKey('raw', decodedSecret, { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']); // Check if any signature matches using timing-safe WebCrypto verify for (const signature of signatures) { try { const signatureBytes = Buffer.from(signature, 'base64'); const isValid = await crypto.subtle.verify('HMAC', key, signatureBytes, new TextEncoder().encode(signedPayload)); if (isValid) { return; // Valid signature found } } catch { // Invalid base64 or signature format, continue to next signature continue; } } throw new InvalidWebhookSignatureError('The given webhook signature does not match the expected signature'); } } _Webhooks_instances = new WeakSet(), _Webhooks_validateSecret = function _Webhooks_validateSecret(secret) { if (typeof secret !== 'string' || secret.length === 0) { throw new Error(`The webhook secret must either be set using the env var, OPENAI_WEBHOOK_SECRET, on the client class, OpenAI({ webhookSecret: '123' }), or passed to this function`); } }, _Webhooks_getRequiredHeader = function _Webhooks_getRequiredHeader(headers, name) { if (!headers) { throw new Error(`Headers are required`); } const value = headers.get(name); if (value === null || value === undefined) { throw new Error(`Missing required header: ${name}`); } return value; }; //# sourceMappingURL=webhooks.mjs.map