https://d226lax1qjow5r.cloudfront.net/blog/blogposts/manage-a-pool-of-phone-numbers-with-node-js/Dev_Numbers_Node-js_1200x600.png

Verwalten eines Pools von Telefonnummern mit Node.js

Zuletzt aktualisiert am May 5, 2021

Lesedauer: 7 Minuten

Möglicherweise sind Sie nicht immer in der Nähe Ihres Bürotelefons, und wenn das der Fall ist, haben Kunden Schwierigkeiten, Sie zu erreichen. In diesem Tutorial werden wir eine Anwendung erstellen, die die Numbers Management API für Vonage APIs verwendet, um mehrere maskierte Numbers zu verwalten. Jede Numbers leitet Anrufe an eine andere Nummer weiter, z. B. an ein privates Mobiltelefon, das von zu Hause aus genutzt werden kann.

Wir stellen auch sicher, dass die Nutzer unserer Anwendung nur die von ihr gekauften und verwalteten Numbers sehen können und nicht alle Numbers in Ihrem Vonage API Account. Schließlich werden wir dafür sorgen, dass nur Benutzer, die Sie kennen, Zugang erhalten und dass die Anwendung nicht über das öffentliche Web ohne Passwort zugänglich ist.

The final application screenshot, showing a pool of phone numbers and management options including update and delete

Kann ich dieses Projekt jetzt verwenden?

Der fertige Code für dieses Projekt ist in Glitch. Sie können das das Projektbesuchen, auf den Remixen zum Bearbeiten oben rechts klicken und Ihre eigenen Anmeldeinformationen in die 🔑.env Datei hinzufügen. Sie können das Projekt dann sofort verwenden, indem Sie auf die Schaltfläche anzeigen oben auf der Seite klicken.

Sie finden den fertigen Code auch auf GitHub.

Voraussetzungen

Hinweis: Nexmo hat sich kürzlich in Vonage umbenannt, nachdem es 2016 übernommen wurde. Sie werden feststellen, dass wir in diesem Tutorial Anrufe an eine Nexmo-URL tätigen, also lassen Sie sich davon nicht beunruhigen.

Vonage API-Konto

Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.

Erstellen eines Basisprojekts

Es gibt eine Kesselsteinvorlage Glitch Projekt, mit dem Sie schnell loslegen können. Diese Anwendung hat:

  • Installieren und binden Sie unsere Abhängigkeiten ein, was Sie in einem neuen Express-Projekt tun können, indem Sie das Glitch-Terminal öffnen und Folgendes eingeben pnpm install express body-parser cors nedb-promises axios qs express-basic-auth.

  • Erstellt eine neue nedb Datenbank im Ordner .data Ordner in Glitch. Dieser Ordner ist spezifisch für Ihre Version der Anwendung und kann nicht von anderen eingesehen oder kopiert werden.

  • Initialisierung einer einfachen Express-Anwendung und Auslieferung der views/index.html Datei, wenn die Benutzer zu unserer Projekt-URL navigieren

  • Ich habe Vue.js und die Axios-Bibliotheken in die index.html Datei ein, erstellte eine neue Vue.js-Anwendung und fügte einige grundlegende Gestaltungselemente in der public/style.css Datei.

Loggen Sie sich in Ihren Glitch Account ein, und klicken Sie auf diesen Link, um die (kopieren) Sie unsere Vorlage in Ihren Account.

Unabhängig davon, ob Sie von Grund auf neu beginnen oder unser Boilerplate verwenden, müssen Sie zu Ihrem Vonage API Dashboard gehen, Ihren API-Schlüssel und Ihr Geheimnis abrufen und sie in die 🔑.env Datei. Diese Werte sind nicht öffentlich sichtbar, aber Sie können in Ihrer Anwendung darauf zugreifen, indem Sie process.env.PROPERTY.

Erstellen eines Endpunkts für den Kauf von Numbers

Für diesen Endpunkt muss ein country zur Verfügung gestellt werden, da dies die API für die Nummernverwaltung erfordert.

Fügen Sie oberhalb der letzten Zeile Ihrer Anwendung den folgenden Code ein:

app.post('/numbers', async (req, res) => {
    try {
        const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
        const availableNumbers = await axios.get(`https://rest.nexmo.com/number/search?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}&country=${req.body.country}&features=SMS,VOICE`);
        const msisdn = availableNumbers.data.numbers[0].msisdn;
        res.send(msisdn);
    } catch (err) {
        res.send(err);
    }
});

Wenn Sie eine POST-Anfrage an /numberssenden, stellt die Anwendung eine GET-Anfrage an die API für die Nummernverwaltung, um eine verfügbare MSISDN (Telefonnummer) zu finden, und gibt die erste Nummer zurück.

Öffnen Sie Ihr Terminal und führen Sie den folgenden Befehl aus, um den neuen API-Endpunkt zu testen: curl -H "Content-Type: application/json" -X POST -d '{"country": "GB"}' https://YOUR_GLITCH_PROJECT_NAME.glitch.me/numbersAchten Sie darauf, dass Sie den Namen Ihres Glitch-Projekts ersetzen. Bei Erfolg sollte eine verfügbare Telefonnummer zurückgegeben werden.

Ersetzen Sie res.send(msisdn) durch den folgenden Text:

await axios({
    method: 'POST',
    url: `https://rest.nexmo.com/number/buy?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`,
    data: qs.stringify({ country: req.body.country, msisdn }),
    headers: { 'content-type': 'application/x-www-form-urlencoded' }
});
await db.insert({ msisdn });
res.send('Number successfully bought');

Dabei wird die erste MSISDN aus den Ergebnissen entnommen, von einem verfügbaren Account-Guthaben gekauft und ein neuer Datenbankeintrag für die MSISDN gespeichert. Das qs Paket formatiert die Daten als x-www-form-encoded Zeichenkette, die von der Number Management API benötigt wird.

Kontrollpunkt! Wiederholen Sie den API-Aufruf an Ihre Anwendung über das Terminal. Sie sollten eine Erfolgsmeldung erhalten, und eine neue Nummer sollte in Ihrem Vonage API Account zugänglich sein.

Hinweis: Es gibt mehrere Gründe, warum der Aufruf der Vonage API in Ihrer Anwendung fehlschlagen kann, die nichts mit Ihrem Code zu tun haben. Prüfen Sie, ob Sie die API für die Nummernverwaltung verwenden können verwenden können, um eine Nummer in Ihrem Land zu erhalten. Wenn es immer noch nicht funktioniert, benötigen Sie benötigen Sie möglicherweise eine Adresse und bedeutet, dass Sie die Nummer über das Vonage API Dashboard abrufen müssen

Erstellen eines Frontends zum Kauf von Numbers

Ihr POST-Anfrageendpunkt funktioniert vielleicht gut, aber es ist an der Zeit, ein benutzerfreundlicheres Frontend zu erstellen, um ihn zu verwenden. Öffnen Sie views/index.html und fügen Sie das Folgende zu Ihrem HTML hinzu:

<div id="app">
    <h1>Number Manager</h1>
    <section>
        <h2>Buy New Number</h2>
        <input type="text" v-model="country" placeholder="Country Code" />
        <button @click="buyNumber">Buy new number</button>
    </section>
</div>

Aktualisieren Sie den Inhalt Ihrer <script> auf den folgenden Stand:

const app = new Vue({
    el: '#app',
    data: {
        country: ''
    },
    methods: {
        async buyNumber() {
            try {
                if(this.country && confirm('Are you sure you would like to buy a number?')) {
                    await axios.post('/numbers', {
                        country: this.form.country
                    })
                    alert('Successfully bought new number');
                }
            } catch(err) {
                alert('Error buying new number', err);
            }
        }
    }
})

Öffnen Sie die Anwendung, indem Sie auf anzeigen am oberen Rand Ihres Glitch-Fensters klicken. Geben Sie "GB" in das Feld ein und klicken Sie auf "Neue Nummer kaufen". confirm() Funktion fordert den Benutzer mit einem Popup-Fenster auf und ist eine gute Methode, um versehentliche Käufe zu vermeiden. Obwohl diese Anwendung Vue.js verwendet, können Sie jede Anwendung erstellen, die HTTP-Anfragen stellen kann.

Erstellen eines Endpunkts zum Auflisten von Numbers

Erstellen Sie einen neuen Endpunkt in Ihrer Express-Anwendung vor der letzten Codezeile:

app.get("/numbers", async (req, res) => {
    try {
        res.send('ok');
    } catch (err) {
        res.send(err);
    }
});

Am Anfang des try Blocks alle lokalen Datenbankeinträge und alle Numbers aus der Vonage Number Management API für Vonage APIs abrufen.

const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
const dbNumbers = await db.find();
const vonageNumbers = await axios.get(`https://rest.nexmo.com/account/numbers?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`);

Erstellen Sie dann ein neues Array, das vonageNumbers nur die Nummern herausfiltert, die auch in der lokalen Datenbank vorkommen. Auf diese Weise wird sichergestellt, dass nur Numbers in diesem Vonage API Account zurückgegeben werden, die von dieser Anwendung verwaltet werden.

const numbersInBothResponses = vonageNumbers.data.numbers.filter(vonageNumber => {
    return dbNumbers.map(dbNumber => dbNumber.msisdn).includes(vonageNumber.msisdn)
});

Als nächstes erstellen Sie ein Objekt, das beide Datenquellen für jede Nummer zusammenfasst:

const combinedResponses = numbersInBothResponses.map(vonageNumber => {
    return {
        ...vonageNumber,
        ...dbNumbers.find(dbNumber => dbNumber.msisdn == vonageNumber.msisdn)
    }
})

combinedResponses enthält nun Daten, die an den Benutzer gesendet werden können, also ersetzen Sie res.send('ok'); durch res.send(combinedResponses);.

Ein Frontend zum Auflisten von Numbers erstellen

In Ihrer index.html Datei eine neue Methode, um die Numbers von unserem Express-Endpunkt abzurufen:

async getNumbers() {
    const { data } = await axios.get('/numbers')
    this.numbers = data;
}

Aktualisieren Sie das data Objekt wie folgt:

data: {
    numbers: [],
    country: ''
}

Laden Sie diese Daten, indem Sie eine created() Funktion direkt unter Ihrem data Objekt:

created() {
    this.getNumbers();
}

Fügen Sie den folgenden HTML-Code hinzu, um die Numbers anzuzeigen:

<section>
    <h2>Current Numbers</h2>
    <div class="number" v-for="number in numbers" :key="number.msisdn">
        <h3>{{number.msisdn}}</h3>
        <label for="name">Friendly Name</label>
        <input type="text" v-model="number.name" placeholder="New name">
        <label for="forward">Forwarding Number</label>
        <input type="text" v-model="number.voiceCallbackValue" placeholder="Update forwarding number">
    </div>
</section>

Kontrollpunkt! Klicken Sie auf anzeigen oben in Ihrem Glitch-Editor und öffnen Sie Ihre Frontend-Anwendung. Wenn sie geladen wird, sollten Sie Ihre verwalteten Telefonnummern sehen.

Schließlich aktualisieren Sie für diesen Abschnitt die buyNumber() Methode, um die this.getNumbers(); nach dem Erfolg alert(). Sobald Sie eine neue Nummer kaufen, wird die Liste nun ohne einen Seitenabruf aktualisiert.

Erstellen eines Endpunkts und eines Frontends zur Aktualisierung von Numbers

Diese Anwendung unterstützt zwei Arten von Rufnummernaktualisierungen. Bei der Aktualisierung des Eigennamens einer Nummer werden Sie Einträge in der lokalen Datenbank bearbeiten, und bei der Aktualisierung der Weiterleitungsnummer werden Sie die Nummer über die API der Nummernverwaltung aktualisieren. Unser Endpunkt muss beides unterstützen und wird anhand der übergebenen Daten entscheiden, welche aktualisiert werden soll. In server.js fügen Sie Folgendes hinzu:

app.patch("/numbers/:msisdn", async (req, res) => {
    try {
        const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
        if(req.body.name) {
            await db.update({ msisdn: req.params.msisdn }, { $set: { name: req.body.name } })
        }
        if(req.body.forward) {
            await axios({
                method: "POST",
                url: `https://rest.nexmo.com/number/update?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`,
                data: qs.stringify({ 
                    country: req.body.country, 
                    msisdn: req.params.msisdn,
                    voiceCallbackType: 'tel',
                    voiceCallbackValue: req.body.forward
                }),
                headers: { "content-type": "application/x-www-form-urlencoded" }
            })
        }
        res.send('Successfully updated')
    } catch(err) {
        res.send(err)
    }
})

Dieser PATCH-Endpunkt enthält die Telefonnummer, die Sie aktualisieren möchten. Wenn der Körper eine name Eigenschaft enthält, wird die lokale Datenbank aktualisiert, und wenn sie forwardenthält, werden die Einstellungen der Nummer über die API der Nummernverwaltung aktualisiert.

In index.htmlerstellen Sie die folgende Methode:

async updateNumber(number) {
    try {
        const { msisdn, country, name, voiceCallbackValue } = number
        const payload = { country }
        if(name) payload.name = name
        if(voiceCallbackValue) payload.forward = voiceCallbackValue
        await axios.patch(`/numbers/${msisdn}`, payload)
        alert('Successfully updated number');
        this.getNumbers(); 
    } catch(err) {
        alert('Error updating number', err);
    }
}

Sie müssen diese Methode auch von der Vorlage aus aufrufen - was geschieht, wenn ein Benutzer die Eingabetaste drückt, während er sich auf eine der Texteingaben konzentriert. Aktualisieren Sie die Eingaben wie folgt:

<label for="name">Friendly Name</label>
<input type="text" v-model="number.name" @keyup.enter="updateNumber(number)" placeholder="New name">
<label for="forward">Forwarding Number</label>
<input type="text" v-model="number.voiceCallbackValue" @keyup.enter="updateNumber(number)" placeholder="Update forwarding number">

Kontrollpunkt! Aktualisieren Sie einen freundlichen Namen einer Nummer. Versuchen Sie dann, die Weiterleitungsnummer zu aktualisieren (denken Sie daran, dass sie in einem einem gültigen Format)

Erstellen eines Endpunkts und eines Frontends für die Stornierung von Numbers

Wenn eine Nummer nicht mehr benötigt wird, können Sie sie kündigen, wodurch sie sofort aus Ihrem Account entfernt wird. Dies ist der letzte wichtige Teil der Verwaltung Ihres virtuellen Rufnummernpools. In server.js fügen Sie oberhalb der letzten Code-Zeile Folgendes ein:

app.delete("/numbers/:msisdn", async (req, res) => {
    try {
        const { NEXMO_API_KEY, NEXMO_API_SECRET } = process.env;
        await axios({
            method: "POST",
            url: `https://rest.nexmo.com/number/cancel?api_key=${NEXMO_API_KEY}&api_secret=${NEXMO_API_SECRET}`,
            data: qs.stringify({ 
                country: req.body.country, 
                msisdn: req.params.msisdn
            }),
            headers: { "content-type": "application/x-www-form-urlencoded" }
        })
        res.send('Successfully cancelled')
    } catch(err) {
        res.send(err)
    }
})

Unter index.html einfügen deleteNumber() Methode:

async deleteNumber(number) {
    try {
        if(confirm('Are you sure you would like to delete this number?')) {
            const { msisdn, country } = number
            await axios.delete(`/numbers/${msisdn}`, { data: { country } })
            alert('Successfully deleted number')
            this.getNumbers()
        }
    } catch(err) {
        alert('Error deleting number', err);
    }
}

Fügen Sie schließlich eine Schaltfläche in der Vorlage direkt unter der Eingabe der Weiterleitungsnummer hinzu:

<button @click="deleteNumber(number)">Delete number</button>

Kontrollpunkt! Löschen Sie eine Nummer.

Sie haben vielleicht bemerkt, dass Sie die Nummer nicht aus der lokalen Datenbank löschen. Sie können dies implementieren, aber da der Endpunkt GET numbers nur Nummern zurückgibt, die sowohl in Ihrem Vonage API Account als auch in der lokalen Datenbank vorhanden sind, werden die gelöschten Nummern nicht zurückgegeben.

Hauswirtschaft

Diese Anwendung ist fast vollständig, aber es sind noch ein paar Kleinigkeiten zu erledigen.

Nur API-Aufrufe von unserem Frontend zulassen

Gegenwärtig kann jeder sein Terminal öffnen und Ihre Numbers ohne Erlaubnis verwalten. In der Nähe des oberen Bereichs von server.jsdirekt unter den app.use() Anweisungen, fügen Sie Folgendes hinzu:

app.use(cors({ origin: `https://${process.env.PROJECT_NAME}.glitch.me` }));

process.env.PROJECT_NAME ist eine von Glitch bereitgestellte Umgebungsvariable, die dem Namen dieses Projekts entspricht. Diese Einstellung lässt nur Anfragen von unserer Glitch-URL zu.

Hinzufügen der Basisauthentifizierung

Selbst wenn Personen nicht über ihre eigenen Anwendungen auf Ihre API zugreifen können, können sie dennoch auf Ihre Live-Site stoßen. Zum Glück besteht die Einrichtung der grundlegenden HTTP-Authentifizierung aus nur zwei Schritten.

Fügen Sie zunächst eine Passphrase in Ihre 🔑.env Datei hinzu. Als nächstes fügen Sie die folgende Zeile am Ende der app.use() Anweisungen:

app.use(basicAuth({ users: { admin: process.env.ADMIN_PASSWORD }, challenge: true }));

Wenn Sie nun Ihre Anwendung laden, müssen Sie Folgendes eingeben admin als Benutzernamen und das von Ihnen angegebene Passwort eingeben.

Wie geht es weiter?

Diese einfache Anwendung wird den Anforderungen der meisten Teams gerecht, aber es gibt sicherlich einige Verbesserungen, die Sie vornehmen könnten:

  • Nur bestimmten Nutzern die Möglichkeit geben, Numbers zu kaufen

  • Bestätigung der Kosten für jede Nummer vor dem Kauf

  • Hinzufügen weiterer Daten zu jeder Nummer in unserer lokalen Datenbank

  • Bessere Fehlerbehandlung

Denken Sie daran, dass der fertige Code für dieses Projekt auch auf GitHub.

Weitere Informationen über die Numbers Management API für Vonage APIs finden Sie in unsere Dokumentationlesen, und wenn Sie zusätzliche Unterstützung benötigen, können Sie sich gerne an unser Team wenden. Vonage Entwickler Twitter Account oder den Vonage Gemeinschaft Slack.

Teilen Sie:

https://a.storyblok.com/f/270183/400x400/c822f15b89/kevinlewis.png
Kevin LewisVonage Ehemalige

Ehemaliger Developer Advocate bei Vonage, wo seine Aufgabe darin bestand, die lokale Tech-Community in London zu unterstützen. Er ist ein erfahrener Veranstaltungsorganisator, Brettspieler und Vater eines süßen kleinen Hundes namens Moo. Er ist auch der Hauptorganisator von You Got This - einem Netzwerk von Veranstaltungen zu den Kernkompetenzen, die für ein glückliches, gesundes Arbeitsleben erforderlich sind.