Галоўная / Артыкулы

Адрасаванне і прыём SMS у Node.js за дапамою Twilio Webhooks і Express

Створыце маленькі сервер Express, який адправляе тэксты через Twilio, прымае адпаведзі за дапамою webhook, які ўвідны ў сеть через ngrok, і автаматычна адпавядае на яны за дапамою TwiML.

Выдавец: REACTAPP.TOP6 хв чытання1483 слоў

Крыніцы: **Build a Two-Way SMS with Node.js and Twilio (Full Code Included)**

Большасць інструкцый з SMS заканчваюцца тады, калі паведамленне паказваецца з вашага сервера. Найболей корыстныя — это тые, якія стосуюцца прыему паведамленняў: фіксацыя таго, што корыстнік адпаведзеў, чытанне тексту і адпаведзь. Гэты цыкл ўтварае аснову для процесаў OTP, ботаў падтрымкі і напамінанняў пра запланаваныя зустрэчы, якія падтверджуюцца адзінам словам. Пасля завершэння гэтага карысавання у вас будзе сервер Express, які надае паведамленні на тэлефон і реагуе кожны раз, калі тэлефон адпавядае.

Прыямыя патрабаванні

  • Акаунт у Twilio. На момент напісання безплатны прыемлівач включае адпрыяж у розмерзе прыблізна $15, што цалкам дастаткова для експерыментаў.
  • Postman або будзь-які іншы HTTP-кліент.
  • Node.js, установлены на вашам комп’ютеры.
  • ngrok, які дае Twilio публічную адресу, якая перадае трафік на ваш ноутбук.

Мінімальны сервер Express

Створыце папку з файлам server.js. Сервер налажоўвае звязак з localhost па порту 3000, увімкнюе парсаванне тэла запыту у формате JSON і URL-кодаванні, а таксама выдае маршрут для перагляду стану пад /api/v1/. Парсаванне у формате URL-кодавання мае важлівэ значэнне: Twilio прыносіць уваходзячыя запыты у формате POST з кодаваннем типу form, таму без яго req.body пазней будзе порожнім.

const express = require("express");
const bodyParser = require("body-parser");
const hostname = "127.0.0.1";
const port = 3000;
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const baseUrl = "/api/v1/";

app.get(`${baseUrl}`, (req, res) => {
  res.status(200).json({ message: "Hello World" });
});
app.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Установіце неабходныя залежнасці:

npm init -y
npm install express body-parser

Запускніце node server.js і ачыніце http://127.0.0.1:3000/api/v1/; адпаведны адказ „Hello World“ параджуе, што всё працюе правільна. У версіях Express 4.16+ таксама ўключаныя функціі express.json() і express.urlencoded(), таму у новых проектах викорыстанне body-parser є неабяжным.

Актываўанне доступу да localhost за дапамогою ngrok

Twilio работае на публічнай інтэрнет-сети, а ваш сервер — на прыватным апаратах, таму Twilio не можа яго безпасэродна прабавіцца. ngrok стварае тунель і дае вам публічны HTTPS-адрэс, які пераказвае трафік на локальны порт. Раней Heroku быў безплатным варыянтом для гэтага, але яго безплатны ўровень больш не існуе.

З’явіце та автентыфікуйце ngrok за дапамою інструкцый ngrok, а пасля дадзіце скрыпт у package.json:

"scripts": {
  "ngrok": "ngrok http http://127.0.0.1:3000/"
}

Закінчыце працю сервера ў аднай тэрмінале, а пасля запусціце тунель у другай:

npm run ngrok

ngrok выводзіць адрэс у формате https://abcd-1234.ngrok-free.app. Залейце гэты тэрмінал ачытым.

Увага: у безплатнай версіи ствароўваны URL зазвычай меняецца ў кожны раз, калі ngrok перазапускаецца. Калі работаючы webhook раптам перестае працаваць, верагодная прычына — застарэлы URL у консолі Twilio, таму апдейтаваць я трэба пасля кожнага перазапуску.

Настройка Twilio

У панелі кансоłu скопіюйте SID свайго абанку і токен аутэнтыфікацыі у файл .env. Цей токен ўважаецца секрэтным: ніколі не дадзейте яго да паведамленняў, а таксама дадзіце файл .env у список .gitignore.

ACCOUNT_SID_TWILIO=your_account_sid
AUTH_TOKEN_TWILIO=your_auth_token

У бокавай навігацыі можна прыкрепіць продукты; тут значэнне маюць толькі Месажы і Номеры тэлефонаў.

Атрыманне номера тэлефона

  1. Ачыніце раздел Номеры тэлефонаў, а потым — Купіць номер.
  2. Выберыце будзь-які доступны номер; номеры з США зазвычай ўсё дашчэцей.
  3. Кошты выкарыстоўваецца з тэстовага балансу, а номер прадстаўляецца сярод вашых актываўных номераў.

Стварэнне службы месажаў

  1. У разделе Месажы створыце новую Службу месажаў.
  2. На кроку Пул адправнікаў дадзіце свой номер.
  • У кроку Інтеграцыя выберыце Адправіць webhook і задаце як URL запиту, так і URL альтэрнатывы вашай адресе ngrok, дадаўшы до неё шлях /api/v1/sms. Гэты шлях будуе створаны нижэй.
  • Праскочыце неабяжны крок і завершыце роботу.
  • Зберагучы Messaging Service SID і ваш номер у файле .env:

    FROM_TWILIO=+1XXXXXXXXXX
    MESSAGING_SERVICE_SID_TWILIO=your_messaging_service_sid
    

    Падключэнне SDK Twilio да Node

    Зінсталюйце SDK асоўна з dotenv, які чытае данні з файла .env і запішвае іх у process.env:

    npm install twilio dotenv
    

    Размістыце гэты код на самай верхней часткі файла server.js. Порядак мае значэнне: кліент чытае аутантыфікацыйныя данні пад час стварэння, таму якщо dotenv будзе чытана пазней, оба значэння будуць undefined, і кожны вызов завершыцца непаводлівасцю аутантыфікаціі.

    require("dotenv").config();
    
    const client = require("twilio")(
      process.env.ACCOUNT_SID_TWILIO,
      process.env.AUTH_TOKEN_TWILIO
    );
    

    Адправа текставага поведамлення

    Этый маршрут вызвае client.messages.create() і прадаёць рэзультат у формате JSON. Блок try/catch вяртае памылкі Twilio, такія як некоректны номер, адвокацу, замест таго каб процес зламаўся.

    app.post(`${baseUrl}sendSms`, async (req, res) => {
      try {
        await client.messages.create({
          body: "Hello",
          from: process.env.FROM_TWILIO,
          messagingServiceSid: process.env.MESSAGING_SERVICE_SID_TWILIO,
          to: "+92XXXXXXXXXX", // whoever you're texting
        });
        res.status(200).json({ message: "Text sent successfully" });
      } catch (err) {
        res.status(500).json({ error: err.message });
      }
    });
    

    Значэнне поль:

    • body: тэкст паведамлення.
    • from: ваш номер у Twilio.
    • messagingServiceSid: спаявае паведамленне з сервісам і пулом адправнікаў.
    • to: аблекач у формате E.164 (+1..., +92...).

    Выклікайце POST /api/v1/sendSms з Postman, і тэлефон должен прыняць „Hello“. У рэальным кодзе чытайце значэння to і body з запыту і пераканаўваеце іх, а не вводзіце як сталявыя значэння.

    Тэстовыя абанкі можаюць надсылать тэкставаныя паведамленні толькі на номеры, якія былі паверыжаны ў консолі Twilio. Якщо запит успех, але нічога не прыходзіць, пераканайцеся, што адресат правыльны, або апградуйце пакет.

    Прыем адпаведзей через webhook

    Калі хтось надсылае тэкставанае паведамленне на ваш номер у Twilio, Twilio надсылае яго на webhook, настроены ў Службе перадачы паведамленняў. Ваш сервер яго прыме і адпаведзіць за дапамойкай TwiML — XML-формата Twilio для апісання наступных дзеянь. З'ядучы гэты калекцыя разам з іншымі неабходнымі элементамі:

    const MessagingResponse = require("twilio").twiml.MessagingResponse;
    

    Потым дадзіце слухача. Класычная памылка — несупаданне шляху: маршрут должен быць такім жа, як і шлях, уведзены ў консолі, тут /api/v1/sms. Обробнік запісвае req.body.Body і вяртае порожні дакумент TwiML у формате text/xml, што означае, што адпаведзі не будзе.

    app.post(`${baseUrl}sms`, (req, res) => {
      // Fires every time someone replies to your number
      const twiml = new MessagingResponse();
    console.log("INCOMING ----->", req.body.Body);
      res.writeHead(200, { "Content-Type": "text/xml" });
      res.end(twiml.toString());
    });
    

    Указайце свой номер у Twilio, і прымэтка паказаецца ў тэрмінале; цыкл завершаецца. У пакете таксама ўключаны параметр From, які паказвае номер адправальніка, і які вам патрэбен калі трэба стежыць за размовамі па адзінам корыстніку.

    Паколькі канец-тэп яўляецца публічным, кожны, хто знайдзе URL, можа адправіць фальшывыя прымэткі. Twilio падпісвае кожны webhook вашым Auth Token у заголовку X-Twilio-Signature, а Node SDK мае інструменты для пераканання. Увімкніце іх пры розгортанні паza местныя тэсты.

    Автаматычна адпаведзь

    Сервер праслухоўвае, але не робіць нічога. Даданне прымэткі ў адпаведзь у формате TwiML ператварае яе на бота, які рэагуе на ключовыя словы. Разместіце гэта ў працоўніку /sms пасля стварэння twiml; гэта код зменшыць і пераканае текст, прычым выберучы адпаведзь:

    const incoming = req.body.Body.trim().toLowerCase();
    if (incoming === "hi") {
      twiml.message("Hey there! How can I help?");
    } else {
      twiml.message("Hmm, I didn't catch that.");
    }
    

    Twilio адрасуе вярнутую адпаведзь падаўшаму, таму не трэба додатковага вызову messages.create().

    Полны сервер

    Усё ў аднам файле, пры чым функцыя автадзвянка залишылася закоментаваная:

    require("dotenv").config();
    
    const express = require("express");
    const bodyParser = require("body-parser");
    const MessagingResponse = require("twilio").twiml.MessagingResponse;
    const client = require("twilio")(
      process.env.ACCOUNT_SID_TWILIO,
      process.env.AUTH_TOKEN_TWILIO
    );
    const hostname = "127.0.0.1";
    const port = 3000;
    const app = express();
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    
    const baseUrl = "/api/v1/";
    // Health check
    app.get(`${baseUrl}`, (req, res) => {
      res.status(200).json({ message: "Hello World" });
    });
    
    // Goal 1: Send an SMS
    app.post(`${baseUrl}sendSms`, async (req, res) => {
      try {
        await client.messages.create({
          body: "Hello",
          from: process.env.FROM_TWILIO,
          messagingServiceSid: process.env.MESSAGING_SERVICE_SID_TWILIO,
          to: "+92XXXXXXXXXX", // whoever you're texting
        });
        res.status(200).json({ message: "Text sent successfully" });
      } catch (err) {
        res.status(500).json({ error: err.message });
      }
    });
    
    // Goal 2: Receive replies (this endpoint must match your Twilio webhook)
    app.post(`${baseUrl}sms`, (req, res) => {
      const twiml = new MessagingResponse();
      console.log("INCOMING ----->", req.body.Body);
      // Optional auto-reply:
      // const incoming = req.body.Body.trim().toLowerCase();
      // if (incoming === "hi") {
      //   twiml.message("Hey there! How can I help?");
      // } else {
      //   twiml.message("Hmm, I didn't catch that.");
      // }
      res.writeHead(200, { "Content-Type": "text/xml" });
      res.end(twiml.toString());
    });
    
    app.listen(port, hostname, () => {
      console.log(`Server running at http://${hostname}:${port}/`);
    });
    

    Галоўныя выводы

    • Вызначэнне SMS — це адны вызов SDK; прыйманне SMS адбываецца через webhook, таму сервер павінен быць доступны і розумець TwiML.
    • Twilio адправляе даныя у формате form-encoded, таму викорыстоўваецца парсер для URL-кодавання.
    • Шлях webhook у консолі і маршрут у Express павінны збігацца, а перзапуск бесплатнага тунелю значыць новы URL.
    • Беззвучныя неудачы тэста часта є наследкам обмежэнняў па перавераных номерах, а не багу.
    • Перад практычным выкарыстоўваннем трэба пераканацца ў правядзімасці падпісаў і адмахнуцца ад жорсткая заданых значэнняў.

    Здесь вы можете зберагаць співарозмовы, развиваць бота на адпаведных ключоўых словах чыста дадаць можлівасць заходу праз OTP. Па большым прыкладам, якія стосуюцца вызоваў праз калбэкі і перапрыбуткаў, адзірніце шасць шаблонаў інтэграцыі для надзеямага з’ѐеднання служб Node.js.