@sahabaplus/moyasar
Version:
A comprehensive TypeScript SDK for integrating with the Moyasar payment gateway
108 lines • 3.59 kB
JavaScript
import { WebhookValidation } from "./validation";
import { WebhookError } from "./errors";
export class WebhookUtils {
/**
* Verify webhook payload signature
*/
static async verifyWebhookSignature(payload, options) {
const { secret_token } = options;
return secret_token === payload.secret_token;
}
/**
* Parse webhook payload safely
*/
static parseWebhookPayload(rawPayload) {
try {
const payloadString = rawPayload instanceof Buffer
? rawPayload.toString("utf8")
: rawPayload;
const parsed = JSON.parse(payloadString);
// Basic validation
if (!parsed.id || !parsed.type || !parsed.data) {
throw new WebhookError("Invalid webhook payload structure", {});
}
return parsed;
}
catch (error) {
if (error instanceof WebhookError) {
throw error;
}
throw new WebhookError(`Failed to parse webhook payload: ${error}`, {});
}
}
/**
* Validate webhook payload
*/
static validateWebhookPayload(payload) {
const errors = [];
// Check required fields
errors.push(...WebhookValidation.validateRequired(payload, [
"id",
"type",
"created_at",
"account_name",
"data",
]));
// Validate event type
if (payload.type && !WebhookValidation.isValidWebhookEvent(payload.type)) {
errors.push(`Invalid webhook event type: ${payload.type}`);
}
// Validate live mode
if (typeof payload.live !== "boolean") {
errors.push("live field must be a boolean");
}
return errors;
}
/**
* Extract signature from headers (common patterns)
*/
static extractSignatureFromHeaders(headers) {
// Common signature header patterns
const signatureHeaders = [
"x-moyasar-signature",
"x-signature",
"signature",
"authorization",
];
for (const header of signatureHeaders) {
const value = headers[header] || headers[header.toLowerCase()];
if (value) {
const signature = Array.isArray(value) ? value[0] : value;
// Remove common prefixes
return signature.replace(/^(sha256=|hmac-sha256=|Bearer\s+)/i, "");
}
}
return null;
}
/**
* Create a consistent payload string for signature verification
*/
static createSignaturePayload(payload, timestamp) {
const basePayload = JSON.stringify(payload);
return timestamp ? `${timestamp}.${basePayload}` : basePayload;
}
/**
* Get webhook event categories
*/
static getEventCategory(event) {
if (event.startsWith("payment_")) {
return "payment";
}
return "unknown";
}
/**
* Check if webhook should be retried based on response
*/
static shouldRetryWebhook(statusCode, retryCount, maxRetries = 5) {
if (retryCount >= maxRetries) {
return false;
}
// Don't retry client errors (4xx) except specific ones
if (statusCode >= 400 && statusCode < 500) {
return [408, 429].includes(statusCode); // Timeout, Rate Limited
}
// Retry server errors (5xx) and network errors
return statusCode >= 500 || statusCode === 0;
}
}
//# sourceMappingURL=utils.js.map