UNPKG

@zed-io/wam-payment-sdk

Version:

Official WAM Payment SDK for creating and signing payment links

192 lines (188 loc) 6.79 kB
import * as crypto from 'crypto'; class WamPaymentError extends Error { constructor(message, code, validationErrors) { super(message); this.code = code; this.validationErrors = validationErrors; this.name = 'WamPaymentError'; } } var WamPaymentErrorCode; (function (WamPaymentErrorCode) { WamPaymentErrorCode["INVALID_CONFIG"] = "INVALID_CONFIG"; WamPaymentErrorCode["INVALID_AMOUNT"] = "INVALID_AMOUNT"; WamPaymentErrorCode["INVALID_CURRENCY"] = "INVALID_CURRENCY"; WamPaymentErrorCode["INVALID_REFERENCE"] = "INVALID_REFERENCE"; WamPaymentErrorCode["INVALID_RETURN_URL"] = "INVALID_RETURN_URL"; WamPaymentErrorCode["SIGNING_ERROR"] = "SIGNING_ERROR"; WamPaymentErrorCode["VALIDATION_ERROR"] = "VALIDATION_ERROR"; })(WamPaymentErrorCode || (WamPaymentErrorCode = {})); class WamPaymentSDK { constructor(config) { this.validateConfig(config); this.config = config; this.baseUrl = this.getBaseUrl(); } /** * Generates a signed payment link for WAM payment processing * @param params Payment parameters including amount, currency, reference, and optional return URL * @returns Payment link response with URL, signature, and metadata */ generatePaymentLink(params) { // Validate input parameters this.validatePaymentParams(params); // Create the payload to sign (must match the format expected by WAM) const payload = `${params.amount}|TTD|${params.reference}`; // Generate HMAC-SHA256 signature const signature = this.generateSignature(payload); // Build the payment URL const paymentUrl = this.buildPaymentUrl(params, signature); return { url: paymentUrl, signature, payload, }; } /** * Validates payment parameters * @param params Payment parameters to validate * @throws WamPaymentError if validation fails */ validatePaymentParams(params) { const errors = []; // Validate amount if (typeof params.amount !== "number" || params.amount <= 0) { errors.push({ field: "amount", message: "Amount must be a positive number", }); } // Validate reference if (!params.reference || typeof params.reference !== "string" || params.reference.trim().length === 0) { errors.push({ field: "reference", message: "Reference must be a non-empty string", }); } // Validate return URL if provided if (params.returnUrl && typeof params.returnUrl !== "string") { errors.push({ field: "returnUrl", message: "Return URL must be a string", }); } if (params.returnUrl && !this.isValidUrl(params.returnUrl)) { errors.push({ field: "returnUrl", message: "Return URL must be a valid URL", }); } if (errors.length > 0) { throw new WamPaymentError("Validation failed", WamPaymentErrorCode.VALIDATION_ERROR, errors); } } /** * Validates the SDK configuration * @param config Configuration to validate * @throws WamPaymentError if configuration is invalid */ validateConfig(config) { const errors = []; if (!config.businessId || typeof config.businessId !== "string") { errors.push({ field: "businessId", message: "Business ID is required and must be a string", }); } if (!config.privateKey || typeof config.privateKey !== "string") { errors.push({ field: "privateKey", message: "Private key is required and must be a string", }); } if (errors.length > 0) { throw new WamPaymentError("Invalid configuration", WamPaymentErrorCode.INVALID_CONFIG, errors); } } /** * Generates HMAC-SHA256 signature * @param payload The payload to sign * @returns Hex-encoded signature */ generateSignature(payload) { try { return crypto .createHmac("sha256", this.config.privateKey) .update(payload) .digest("hex"); } catch (error) { throw new WamPaymentError("Failed to generate signature", WamPaymentErrorCode.SIGNING_ERROR); } } /** * Gets the base URL based on environment configuration * @returns Base URL for WAM payment gateway */ getBaseUrl() { // Determine environment from config, default to production const environment = this.config.environment || 'production'; // Return appropriate URL based on environment switch (environment) { case 'staging': case 'development': return "https://staging.billing.wam.money"; case 'production': default: return "https://billing.wam.money"; } } /** * Builds the complete payment URL with all parameters * @param params Payment parameters * @param signature Generated signature * @returns Complete payment URL */ buildPaymentUrl(params, signature) { const paymentUrl = new URL(`${this.baseUrl}/pay/external/generic/${this.config.businessId}`); // Add required parameters paymentUrl.searchParams.set("amount", params.amount.toString()); paymentUrl.searchParams.set("currency", "TTD"); paymentUrl.searchParams.set("reference", params.reference); paymentUrl.searchParams.set("signature", signature); // Add optional return URL if (params.returnUrl) { paymentUrl.searchParams.set("returnUrl", params.returnUrl); } return paymentUrl.toString(); } /** * Validates if a string is a valid URL * @param url String to validate * @returns true if valid URL, false otherwise */ isValidUrl(url) { try { new URL(url); return true; } catch { return false; } } /** * Gets the current configuration (without sensitive data) * @returns Configuration object without private key */ getConfig() { return { businessId: this.config.businessId, environment: this.config.environment || 'production', baseUrl: this.baseUrl, }; } } export { WamPaymentError, WamPaymentErrorCode, WamPaymentSDK, WamPaymentSDK as default }; //# sourceMappingURL=index.esm.js.map