UNPKG

totem-otp-delivery-webhook

Version:
145 lines 5.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebhookDeliveryAgent = void 0; // Use Node.js built-in fetch (available in Node 18+) or fallback to https module const https_1 = require("https"); const http_1 = require("http"); const url_1 = require("url"); class WebhookDeliveryAgent { constructor(options) { this.webhookUrl = options.webhookUrl; this.bodyBuilder = options.bodyBuilder || this.defaultBodyBuilder; this.headers = { 'Content-Type': 'application/json', ...options.headers }; this.method = options.method || 'POST'; this.timeout = options.timeout || 30000; } async sendMessageToAudience(otp) { const body = this.bodyBuilder(otp); const bodyString = typeof body === 'string' ? body : JSON.stringify(body); try { const response = await this.makeHttpRequest(bodyString); if (response.statusCode < 200 || response.statusCode >= 300) { throw new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`); } // Try to get receipt ID from response const receiptId = await this.extractReceiptId(response); return receiptId || this.generateReceiptId(otp); } catch (error) { throw new Error(`Webhook delivery failed: ${error.message}`); } } /** * Default body builder that creates a standard webhook payload */ defaultBodyBuilder(otp) { return { event: 'otp_requested', timestamp: new Date().toISOString(), data: { target: { type: otp.target.type, value: otp.target.value, uniqueIdentifier: otp.target.uniqueIdentifier }, otp: { value: otp.value, reference: otp.reference, expiresAt: new Date(otp.expiresAtMs).toISOString(), resendAllowedAt: new Date(otp.resendAllowedAtMs).toISOString() } } }; } /** * Make HTTP request using Node.js built-in modules */ makeHttpRequest(body) { return new Promise((resolve, reject) => { const url = new url_1.URL(this.webhookUrl); const isHttps = url.protocol === 'https:'; const request = isHttps ? https_1.request : http_1.request; const options = { hostname: url.hostname, port: url.port || (isHttps ? 443 : 80), path: url.pathname + url.search, method: this.method, headers: { ...this.headers, 'Content-Length': Buffer.byteLength(body) }, timeout: this.timeout }; const req = request(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { resolve({ statusCode: res.statusCode || 0, statusMessage: res.statusMessage || '', headers: res.headers, data }); }); }); req.on('error', (error) => { reject(error); }); req.on('timeout', () => { req.destroy(); reject(new Error(`Request timeout after ${this.timeout}ms`)); }); req.write(body); req.end(); }); } /** * Extract receipt ID from webhook response */ async extractReceiptId(response) { try { const contentType = response.headers['content-type'] || ''; if (contentType.includes('application/json')) { const data = JSON.parse(response.data); // Try common receipt ID field names return (data.receiptId || data.receipt_id || data.id || data.messageId || data.message_id || null); } // If response is text, try to use it as receipt ID if (contentType.includes('text/') || !contentType) { const text = response.data.trim(); return text || null; } return null; } catch { return null; } } /** * Generate a fallback receipt ID if none is provided by the webhook */ generateReceiptId(otp) { const timestamp = Date.now(); const targetHash = this.simpleHash(otp.target.value); return `webhook_${timestamp}_${targetHash}_${otp.reference}`; } /** * Simple hash function for generating receipt IDs */ simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = (hash << 5) - hash + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash).toString(16); } } exports.WebhookDeliveryAgent = WebhookDeliveryAgent; //# sourceMappingURL=WebhookDeliveryAgent.js.map