PR Archives:  LatestBy Company By Date


Press Release -- March 22nd, 2020
Source: Bandwidth.com
Tags:

Port Out Validation Implementation Example in NodeJS

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