UNPKG

@mirad-work/sms-core

Version:

A framework-agnostic TypeScript SMS service core with provider abstraction for Iranian SMS providers

142 lines 5.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MelipayamakDriver = void 0; const base_driver_1 = require("./base-driver"); const MELIPAYAMAK_ERROR_MESSAGES = { "0": "Invalid username or password", "1": "Access to this web service is disabled", "2": "Only one mobile number is allowed per request", "3": "Sender line is not defined in the system", "4": "Invalid or unapproved template bodyId", "5": "Template variables do not match the approved pattern", "6": "Internal error, contact support", "-5": "Insufficient credit", "-6": "System is being updated", "-7": "Message contains filtered words", "-10": "User account is not active", "-11": "Message was not sent", "-12": "User documents are incomplete", "-18": "Invalid mobile number", "-19": "Daily web service send limit reached", "108": "IP blocked due to failed API attempts", "109": "Allowed IP must be configured for API usage", "110": "ApiKey must be used instead of password", }; /** * Melipayamak SMS driver implementation * Uses the REST BaseServiceNumber API for shared-service template messages */ class MelipayamakDriver extends base_driver_1.BaseSmsDriver { constructor(config, httpClient) { super(config, httpClient); this.melipayamakConfig = config; } /** * Send a template-based SMS message (OTP/verification) */ async verify(message) { this.validateMessage(message); if (!message.template) { return this.createErrorResponse("Template is required for verify operation", "MISSING_TEMPLATE"); } if (!message.tokens) { return this.createErrorResponse("Tokens are required for verify operation", "MISSING_TOKENS"); } try { const url = this.buildUrl("BaseServiceNumber"); const payload = this.buildVerifyPayload(message); this.log("info", "Sending verification SMS via Melipayamak", { to: message.to, template: message.template, }); const response = await this.handleHttpRequest(() => this.httpClient.request({ method: "POST", url, data: new URLSearchParams(payload), headers: { ...this.buildHeaders(), "Content-Type": "application/x-www-form-urlencoded", }, })); return this.processMelipayamakResponse(response.data); } catch (error) { const err = error; this.log("error", "SMS verify failed", { error: err.message }); return this.createErrorResponse(err.message, "VERIFY_FAILED"); } } /** * Build payload for BaseServiceNumber requests */ buildVerifyPayload(message) { return { username: this.melipayamakConfig.username, password: this.melipayamakConfig.password, text: this.buildTemplateText(message.tokens), to: message.to, bodyId: message.template, }; } /** * Convert tokens to semicolon-separated template variables */ buildTemplateText(tokens) { const args = []; if (Array.isArray(tokens)) { tokens.forEach((token) => { if (token !== undefined) { args.push(String(token)); } }); } else { const paramNames = [ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", ]; paramNames.forEach((name) => { if (tokens[name] !== undefined) { args.push(String(tokens[name])); } }); if (args.length === 0) { Object.values(tokens).forEach((value) => { if (value !== undefined) { args.push(String(value)); } }); } } return args.join(";"); } /** * Process Melipayamak API response and convert to standard format */ processMelipayamakResponse(response) { if (this.isSuccessResponse(response)) { return this.createSuccessResponse(response, response.Value); } const errorCode = response.Value; const errorMessage = MELIPAYAMAK_ERROR_MESSAGES[errorCode] || `Melipayamak error: ${errorCode || response.StrRetStatus}`; return this.createErrorResponse(errorMessage, `MELIPAYAMAK_${errorCode || response.RetStatus}`, response); } isSuccessResponse(response) { if (response.RetStatus === 1 && response.StrRetStatus?.toLowerCase() === "ok") { return true; } return /^\d{16,}$/.test(response.Value); } } exports.MelipayamakDriver = MelipayamakDriver; //# sourceMappingURL=melipayamak-driver.js.map