Cómo enviar un SMS desde React con Twilio

October 24, 2018
Redactado por
Phil Nash
Twilion

Cómo enviar un SMS desde React con Twilio

Hablamos mucho sobre el envío de mensajes SMS desde aplicaciones web, pero ¿qué sucede con el envío de mensajes SMS desde una aplicación de React? Hay un poco más que solo la versión del lado del servidor, pero no nos llevará mucho tiempo.

¿Por qué no debería utilizar la API REST desde el lado del cliente?

Técnicamente, podría enviar un SMS mediante la API REST de Twilio directamente desde una aplicación en el lado del cliente de JavaScript. Pero (y es un “pero” muy grande) si lo hiciera, expondría sus credenciales de Twilio a cualquiera que utilice su sitio. Un usuario malicioso podría tomar esas credenciales y hacer un mal uso de ellas, lo que genera una factura enorme en su cuenta.

Una animación que muestra a un pirata informático falso, con un pasamontañas y manos adicionales.

Vista en vivo de un hacker con las credenciales de su cuenta

Para evitar esto, crearemos una aplicación de back-end que implemente la API REST de Twilio, cierre sus credenciales y envíe mensajes SMS por usted. Entonces, puede llamar al back-end desde su aplicación React y enviar mensajes SMS sin distribuir sus credenciales en Internet.

Nuestras herramientas

Para que nuestra aplicación envíe mensajes de texto mediante la API REST de Twilio, necesitaremos lo siguiente:

Para comenzar, descargue o clone la aplicación React-Express-Starter que creé en mi última publicación del blog.

git clone https://github.com/philnash/react-express-starter.git

Cambie al directorio e instale las dependencias.

cd react-express-starter
npm install

En el directorio del proyecto, cree un archivo llamado “.env”:

touch .env

Ahora puede probar que el proyecto funciona ejecutando npm run dev. La aplicación se cargará en su explorador en localhost:3000.

Esta aplicación para principiantes está configurada para tener una aplicación React y una Express en el mismo proyecto que se puedan ejecutar de manera simultánea. Si desea averiguar cómo funciona esto, consulte esta publicación del blog.

Creación del lado del servidor

Como se indicó, debemos realizar las llamadas de la API de Twilio desde el servidor. Agregaremos un punto final al servidor Express al que se pueda llamar desde nuestra aplicación de React. Empiece por instalar el módulo Twilio Node.js. Nota: Para los fines de esta aplicación, estoy guardando las dependencias del servidor como dependencias de desarrollo para separarlas de las dependencias del lado del cliente.

npm install twilio --save-dev

A continuación, debemos configurar la aplicación con nuestras credenciales de Twilio. Recopile su SID de cuenta de Twilio y su token de autenticación desde la consola de Twilio junto con un número de teléfono de Twilio que pueda enviar mensajes SMS. Ingrese los tres en el archivo .env que creó anteriormente de la siguiente manera:

TWILIO_ACCOUNT_SID=YOUR_ACCOUNT_SID
TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKEN
TWILIO_PHONE_NUMBER=YOUR_TWILIO_PHONE_NUMBER

Esto establecerá sus credenciales en el entorno. Ahora, abra server/index.js para que podamos comenzar a utilizar el código necesario para enviar el mensaje. En el otro módulo, se necesita, en la parte superior del archivo, solicitar e inicializar la biblioteca de Twilio con las credenciales del entorno.

const express = require('express');
const bodyParser = require('body-parser');
const pino = require('express-pino-logger')();
const client = require('twilio')(
  process.env.TWILIO_ACCOUNT_SID,
  process.env.TWILIO_AUTH_TOKEN
);

Enviaremos los datos al punto final que estamos creando como JSON, por lo que tendremos que analizar el cuerpo JSON. Configure la app Express con el analizador de cuerpo JSON:

const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(pino);

Realice una ruta para una solicitud POST. Agregue lo siguiente debajo de la ruta para /api/greeting:

app.post('/api/messages', (req, res) => {

});

También responderemos con JSON, por lo que debe establecer el encabezado de Content-Type en application/json.

app.post('/api/messages', (req, res) => {
  res.header('Content-Type', 'application/json');

});

Luego, utilizaremos el Twilio Client que inicializamos anteriormente para crear un mensaje. Utilizaremos nuestro número de Twilio como número from y obtendremos el número to y el body del mensaje desde el cuerpo de la solicitud entrante. Esto devuelve una promesa que se cumplirá cuando la solicitud de API se realice correctamente o se rechace si falla. En cualquiera de los casos, devolveremos una respuesta JSON que le dirá al lado del cliente si la solicitud se realizó correctamente o no.

app.post('/api/messages', (req, res) => {
  res.header('Content-Type', 'application/json');
  client.messages
    .create({
      from: process.env.TWILIO_PHONE_NUMBER,
      to: req.body.to,
      body: req.body.body
    })
    .then(() => {
      res.send(JSON.stringify({ success: true }));
    })
    .catch(err => {
      console.log(err);
      res.send(JSON.stringify({ success: false }));
    });
});

Eso es todo lo que necesitamos en el servidor, empecemos con la parte de React.

Creación del lado del cliente

En el lado del cliente, podemos encapsular el formulario para enviar nuestro SMS a través del servidor en solo un componente. Por lo tanto, en el directorio src, cree un nuevo componente llamado SMSForm.js y comience con el texto modelo para un componente:

import React, { Component } from 'react';

class SMSForm extends Component {

}

export default SMSForm;

Vamos a crear un formulario que un usuario puede llenar con un número de teléfono y un mensaje. Cuando se envíe el formulario, se enviarán los detalles a nuestro punto final del servidor y se enviará el mensaje como un SMS al número.

Primero, construyamos el método render para este componente: incluirá un formulario, una entrada para el número de teléfono, un área de texto para el mensaje y un botón para enviar:

  render() {
    return (
      <form>
        <div>
          <label htmlFor="to">To:</label>
          <input
             type="tel"
             name="to"
             id="to"
          />
        </div>
        <div>
          <label htmlFor="body">Body:</label>
          <textarea name="body" id="body"/>
        </div>
        <button type="submit">
          Send message
        </button>
      </form>
    );
  }

Podemos agregar algunas hojas de estilo en cascada (CSS, por sus siglas en inglés) para darle un poco de estilo a este formulario. Cree el archivo src/SMSForm.css y agregue lo siguiente:

.sms-form {
  text-align: left;
  padding: 1em;
}
.sms-form label {
  display: block;
}
.sms-form input,
.sms-form textarea {
  font-size: 1em;
  width: 100%;
  box-sizing: border-box;
}
.sms-form div {
  margin-bottom: 0.5em;
}
.sms-form button {
  font-size: 1em;
  width: 100%;
}
.sms-form.error {
  outline: 2px solid #f00;
}

Importe las CSS en la parte superior del componente SMSForm:

import React, { Component } from 'react';
import './SMSForm.css';

Ahora, importe el componente a src/App.js y reemplace el método render con lo siguiente:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import SMSForm from './SMSForm';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />

          <SMSForm />
        </header>
      </div>
    );
  }
}

export default App;

Inicie su aplicación con npm run dev y verá el formulario en la página.

el formulario en la página

El formulario aún no hace nada, así que arreglemos eso.

Realizar un formulario interactivo en React

Para conectar el formulario HTML con el componente, debemos hacer algunas cosas:

  • Mantener el estado de la entrada y el área de texto al día en el estado del componente
  • Gestionar el envío del formulario y el envío de los datos a la servidor
  • Gestionar la respuesta del servidor y borrar el formulario si el mensaje se envió correctamente, o mostrar un error si no fue así

Comenzaremos estableciendo algún estado inicial en el constructor. Tendremos que almacenar los datos ingresados del formulario, si el formulario se está enviando actualmente (para que podamos desactivar el botón de envío) y si se produjo un error. Cree el constructor para el componente de la siguiente manera:

class SMSForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      message: {
        to: '',
        body: ''
      },
      submitting: false,
      error: false
    };
  }

  // rest of the component
}

Necesitaremos un método que pueda manejar los cambios en los campos del formulario y actualizar el estado. Podríamos crear dos métodos, uno para el ingreso de datos y otro para el área de texto, pero debido a que los nombres de los elementos del formulario y los elementos en el estado coinciden, podemos crear un método para cubrir ambos.

  onHandleChange(event) {
    const name = event.target.getAttribute('name');
    this.setState({
      message: { ...this.state.message, [name]: event.target.value }
    });
  }

Observe que aquí usamos nombres de propiedad computarizada ES2015 para establecer la propiedad correcta en el estado y el operador de propagación para llenar el resto del estado.

Tendremos que vincular este método al objeto para garantizar que this sea correcto cuando lo usemos para recibir un evento. Agregue lo siguiente a la parte inferior del constructor:

  constructor(props) {
    super(props);
    this.state = {
      message: {
        to: '',
        body: ''
      },
      submitting: false,
      error: false
    };
    this.onHandleChange = this.onHandleChange.bind(this);
  }

Ahora podemos actualizar el JSX presentado para establecer el valor de los campos del formulario con el estado actual y manejar las actualizaciones con nuestro método onHandleChange:

  render() {
    return (
      <form>
        <div>
          <label htmlFor="to">To:</label>
          <input
            type="tel"
            name="to"
            id="to"
            value={this.state.message.to}
            onChange={this.onHandleChange}
          />
        </div>
        <div>
          <label htmlFor="body">Body:</label>
          <textarea
            name="body"
            id="body"
            value={this.state.message.body}
            onChange={this.onHandleChange}
          />
        </div>
        <button type="submit">Send message</button>
      </form>
    );
  }

Vuelva a cargar la app y podrá actualizar los campos del formulario. Si tiene las herramientas de desarrollo de React para su navegador, también podrá ver la actualización del estado.

herramientas de desarrollo de React

Ahora tenemos que gestionar el envío del formulario. Cree otra función onSubmit, eso comienza con la actualización de la propiedad del estado submitting (enviando) a true (verdadero). A continuación, utilice la fetch API para realizar la solicitud al servidor. Si la respuesta se realiza correctamente, borre el formulario y establezca el estado submitting (enviando) en false (falso). Si la respuesta no se realiza correctamente, establezca el estado submitting enviando en false (falso), pero establezca error en true (verdadero).

  onSubmit(event) {
    event.preventDefault();
    this.setState({ submitting: true });
    fetch('/api/messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(this.state.message)
    })
      .then(res => res.json())
      .then(data => {
        if (data.success) {
          this.setState({
            error: false,
            submitting: false,
            message: {
              to: '',
              body: ''
            }
          });
        } else {
          this.setState({
            error: true,
            submitting: false
          });
        }
      });
  }

Al igual que con el método onHandleChange, también vinculamos este método con el constructor:

  constructor(props) {
    super(props);
    this.state = {
      message: {
        to: '',
        body: ''
      },
      submitting: false,
      error: false
    };
    this.onHandleChange = this.onHandleChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);
  }

Ahora, en el JSX agregamos el método onSubmit como gestor de envío en el formulario. También establecemos la clase del formulario como “error” si recibimos un error de la solicitud. Y, mientras se envía el formulario, configuramos la propiedad del botón disabled.

  render() {
    return (
      <form
        onSubmit={this.onSubmit}
        className={this.state.error ? 'error sms-form' : 'sms-form'}
      >
        <div>
          <label htmlFor="to">To:</label>
          <input
            type="tel"
            name="to"
            id="to"
            value={this.state.message.to}
            onChange={this.onHandleChange}
          />
        </div>
        <div>
          <label htmlFor="body">Body:</label>
          <textarea
            name="body"
            id="body"
            value={this.state.message.body}
            onChange={this.onHandleChange}
          />
        </div>
        <button type="submit" disabled={this.state.submitting}>
          Send message
        </button>
       </form>
    );
  }

Esto es todo lo que necesitamos, así que actualice la app e ingrese su número de teléfono celular y un mensaje para enviar. Envíe el formulario y, si los detalles son correctos, se enviará el mensaje. De lo contrario, el formulario mostrará que el estado es un error.

Ahora al ingresar valores incorrectos el formulario muestra un error y cuando ingresa los valores correctos se envía el mensaje.

Enviar mensajes y mantener sus credenciales seguras

Enviar mensajes SMS desde una app web es genial. Enviar mensajes SMS desde su app React sin exponer sus credenciales es aún más genial.

Puede revisar todo el código de esta aplicación de ejemplo en el repositorio de GitHub.

Ahora que tiene la base de una app React que puede enviar mensajes SMS, puede hacer algunas mejoras. En primer lugar, es probable que las mejoras se traten de mejor validación y mensajes de error. Con un diseño similar, puede agregar búsquedas de números de teléfono, realizar llamadas telefónicas o implementar la autenticación de dos factores directamente desde su app React.

Este artículo fue traducido del original "How to send an SMS from React with Twilio". Mientras estamos en nuestros procesos de traducción, nos encantaría recibir sus comentarios en help@twilio.com - las contribuciones valiosas pueden generar regalos de Twilio.