This document is a walkthrough of implementing a sample solution for using Bandwidth’s Port Out Validation.
Please see the first post in this series for a guide on how port out validation works.
This is a sample route using express that is designed to process an incoming port out validation webhook from Bandwidth. This sample code assumes at least some familiarity with NodeJS and utilizes the npm package xml2js for conversion between XML and JSON. This is not meant to be a fully implemented port out validation solution, but rather a brief example of the general process of how a successful port out validation solution works. Please consult with your own teams about your company’s needs for this kind of solution, and remember that Bandwidth is always here to answer questions and provide guidance.
From our experts — an example implementation of NodeJS code for the Bandwidth Port Out Validation API:
const xml2js = require("xml2js"); module.exports = (app) => { //define our stored values we are validating against const validValues = { numbersStored: [ "9992228888", "3334442222" ], accountIdStored: "1234", pinStored: "567" } //defining our functions that validate against our stored data function CheckNumber(number) { if (validValues.numbersStored.indexOf(number) === -1) return false; else return true; } function CheckAccountId(accountId) { if (validValues.accountIdStored === accountId) return true; else return false; } function CheckPin(pin) { if (validValues.pinStored === pin) return true; else return false; } //generates validation failure XML function ValidationFails(errorTypes, PON) { var xmlBuilder = { PortOutValidationResponse: { Portable: false, PON: PON, Errors: [], AcceptableValues: { Pin: validValues.pinStored, AccountNumber: validValues.accountIdStored, TelephoneNumbers: { TelephoneNumber: [ validValues.numbersStored[0], validValues.numbersStored[1] ] } } } } //loop through errors and prepare error objects for (var i = 0; i < errorTypes.length; i++) { var errorObject = { Error: { Code: "", Description: "" } } switch (errorTypes[i]) { case ("bad_number"): errorObject.Error.Code = "7518"; errorObject.Error.Description = "Telephone Number Not Active"; xmlBuilder.PortOutValidationResponse.Errors.push(errorObject); break; case ("bad_account"): errorObject.Error.Code = "7511"; errorObject.Error.Description = "Invalid Account Code"; xmlBuilder.PortOutValidationResponse.Errors.push(errorObject); break; case ("bad_pin"): errorObject.Error.Code = "7513"; errorObject.Error.Description = "PIN Invalid"; xmlBuilder.PortOutValidationResponse.Errors.push(errorObject); break; case ("no_account"): errorObject.Error.Code = "7510"; errorObject.Error.Description = "Required account Code missing"; xmlBuilder.PortOutValidationResponse.Errors.push(errorObject); break; case ("no_pin"): errorObject.Error.Code = "7512"; errorObject.Error.Description = "Required PIN missing"; xmlBuilder.PortOutValidationResponse.Errors.push(errorObject); break; } } //creates xml and return it to be sent in response to request var builder = new xml2js.Builder({renderOpts: {pretty: true}}); var errorXml = builder.buildObject(xmlBuilder); return errorXml; } //generates validation success XML function ValidationSucceeds(PON) { var xmlBuilder = { PortOutValidationResponse: { Portable: true, PON: PON } } var builder = new xml2js.Builder({renderOpts: {pretty: true}}); var successXml = builder.buildObject(xmlBuilder); return successXml; } //define route that receives webhook app.post("/api/pov", (req, res) => { var povData = req.body; //create an array of all numbers in the request var numbersArray = []; for (var i = 0; i < povData.PortOutValidationRequest.TelephoneNumbers[0].TelephoneNumber.length; i++) { numbersArray.push(povData.PortOutValidationRequest.TelephoneNumbers[0].TelephoneNumber[i]); } var errorTypes = []; for (var i = 0; i < numbersArray.length; i++) { if (!CheckNumber(numbersArray[i])) { errorTypes.push("bad_number"); break; } } if (!povData.PortOutValidationRequest.AccountNumber) { errorTypes.push("no_account"); } else if (!CheckAccountId(povData.PortOutValidationRequest.AccountNumber[0])) { errorTypes.push("bad_account"); } if (!povData.PortOutValidationRequest.Pin) { errorTypes.push("no_pin"); } else if (!CheckPin(povData.PortOutValidationRequest.Pin[0])) { errorTypes.push("bad_pin"); } if (errorTypes.length > 0) { res.send(ValidationFails(errorTypes, povData.PortOutValidationRequest.PON[0])); } else { res.send(ValidationSucceeds(errorTypes, povData.PortOutValidationRequest.PON[0])); } });
PR Archives: Latest, By Company, By Date