
Compartir:
Tonya es una antigua defensora de los desarrolladores de Python en Vonage.
Cómo enviar SMS con Python, FastAPI y Vonage
Tiempo de lectura: 24 minutos
Imagina que estás en una isla, varado. Sólo tienes tu ordenador y WiFi. Las aguas del océano empiezan a subir y te preocupa quedar bajo el agua si no actúas con rapidez.
La única salida es crear un sitio web en Python y enviar un mensaje de texto a alguien. Por suerte, eres un programador y has jugueteado recientemente con el nuevo framework web FastAPI. También has probado la API Messages API de Vonage para enviar mensajes SMS.
Equipado con todos estos nuevos conocimientos, sacas el portátil para ponerte manos a la obra.
Instalación de la CLI de Vonage
Lo primero que debes hacer es instalar la nueva CLI de Vonage. Te permite crear una aplicación de tablero rápidamente. Necesitas una aplicación de Vonage para interactuar con Messages API. Desde tu terminal, ejecuta estos comandos y habla contigo mismo durante la instalación:
Tienes NodeJS y npm instalados, así que el primer comando debería funcionar dependiendo de si tu $PATH es correcto o no.
¡Bam! ¡Funcionó! Ahora tienes la CLI de Vonage instalada en tu equipo.
Quieres asegurarte de que la instalación se ha realizado correctamente, así que tecleas:

A continuación, vaya al panel para obtener tu API Key y tu API Secret. Ya estás registrado. Todo lo que tienes que hacer es iniciar sesión.
A continuación, configure sus teclas haciendo lo siguiente:
Éxito, ¡lo tienes! En caso de que hayas olvidado un comando de Vonage, puedes usar el indicador de ayuda:
Uso de la CLI de Vonage
Ahora viene la parte divertida. Tienes que crear tu aplicación, así que ejecuta este comando:
Usted le da un Nombre de aplicación de enviar sms y pulsas Retorno.

A continuación, en la opción Select App Capabilities, elija Mensajes.

Ahora crea tus webhooks de entrada y de estado.
Usted elige "Y" para Crear Webhooks de mensajes.

A continuación, siga utilizando los valores predeterminados pulsando Retorno para cada opción hasta que cree su aplicación.

Ahora tienes una aplicación y estás muy contento. Podrás ver Loki en un santiamén. Quieres confirmar su creación, así que vuelves al salpicadero. Haz clic en Tus Applications y lo ves.

Comprueba si la opción de alternar está activada para Messages API. También quieres verificar que tus webhooks lo han hecho, así que seleccionas editar.


Todo tiene muy buena pinta. También te das cuenta de que no necesitas hacer este paso cada vez, ya que es sólo para volver a comprobarlo.
El agua te sube por encima de las rodillas. Tu mayor miedo es quedarte solo en esta isla con una pelota de voleibol. Odiabas esa película.
Ahora es el momento de que escribas tu aplicación FastAPI para poder enviar tus SMS.
Has aprendido que FastAPI ofrece una maravillosa experiencia al desarrollador y acelera el tiempo de codificación. También es súper rápido en rendimiento debido a su naturaleza asíncrona.
Perfecto.
Creación del entorno virtual de Python
Lo primero que hay que hacer es navegar hasta o cd en el directorio donde quieras crear tu proyecto Python.
A continuación, cree una nueva carpeta llamada send_sms ejecutando este comando desde tu directorio:
Se cambia a ese directorio haciendo esto:
Piensas para tus adentros que éste sería un buen momento para crear un entorno virtual, así que echas a correr:
Para verificar que este nuevo entorno virtual ha sido creado, comprueba si se ha creado uno llamado venv está en tu nuevo directorio, así que tecleas
¡Voilà! Ya está.
Ahora es el momento de activarlo para poder instalar FastAPI y tus otros paquetes, así que lo haces:
Usted ve que (venv) está al principio de tu usuario en tu terminal, así que sabes que ha sido activado.
Caramba, el sol te da en la cara y hay un resplandor en la pantalla del ordenador. Apenas puedes ver nada y desearías tener tus gafas de sol. Recuerdas que justo antes de salir de casa y quedarte tirado, ¡tu perro se las comió!
Instalación de FastAPI
Ahora es el momento de instalar FastAPI.
La última vez que se instaló había que actualizar pip primero así:
Ahora instala FastAPI así:
Ahora tienes FastAPI instalado y estás encantado de haberlo instalado con el comando [todo] porque te da todas las dependencias y características como async-generators, el módulo requests, JSON, Jinja2 para plantillas en HTML, Pydantic, etc.
Hola mundo rápido FastAPI
Quieres tener un ejemplo de Hola Mundo funcionando rápidamente, para poder probar si tu instalación ha funcionado. Creas un archivo main.py en el directorio de tu proyecto.
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def home():
return {"hello": "world"}La línea from fastapi import FastAPI importa FastAPI como una clase Python.
app = FastAPI() crea una instancia de FastAPI llamada app.
Aquí @app.get("/") crea una operación de ruta. Una ruta se refiere a dónde quieres dirigirte cuando llegues a tu punto final. También puedes pensar en ella como una URL. La raíz de la página o localhost (http://127.0.0.1:8000) es a donde te diriges. La operación se refiere al método HTTP. Para manejar un GET usa el decorador @app.getque le dice que lea los datos y vaya a la ruta. La ruta aquí es ("/") o la página raíz.
He aquí una función asíncrona async def home():. Pueden procesar peticiones antes de que otras las hayan completado. Se ejecutan en paralelo, que es bastante dulce porque hace las cosas mucho más rápido que se ejecuta de forma sincrónica, o en orden. También puedes definir una función aquí con just: def home(): si no te importa el código asíncrono.
Esta línea return {"hello": "world"} devuelve un diccionario al navegador.
Ejecute su código en modo de desarrollo haciendo lo siguiente:
Puedes pensar en uvicorn como una implementación de servidor ASGI (Asynchronous Server Gateway Interface) súper rápida. En main:appmain es el nombre de tu archivo main.py. El nombre de tu instancia FastAPI es app. El comando --reload le permite utilizar la recarga en caliente, lo que le permite realizar cambios en el código en tiempo real.
En el terminal, vaya a su localhost http://127.0.0.1:8000/ en el navegador y ves {"hola": "mundo"}. Perfecto.
Envío de SMS
Ahora es el momento de escribir el código para enviar el SMS.
El cielo está oscuro y sopla un fuerte viento. Se avecina un tornado.
¡Tienes que darte prisa!
En tu main.py sustituye tu código de Hola Mundo por esto:
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def get_message(request: Request):
return templates.TemplateResponse("index.html", {"request": request})Aquí también estás importando Request así:from fastapi import FastAPI, Request. Este Solicitud te permite obtener detalles o peticiones entrantes a tu función.
Importa Jinja para poder utilizar su motor de plantillas from fastapi.templating import Jinja2Templates.
En esta línea from fastapi.responses import HTMLResponse necesitas permitir una HTMLResponse.
Aquí montas la carpeta templates (crearás una dentro de un rato) y le dices que contenga todos tus archivos HTML en un directorio llamado plantillas. Su línea de código se parece a esto: templates = Jinja2Templates(directory="templates").
En el decorador de ruta @app.get("/", response_class=HTMLResponse). El HTMLResponse indica que la respuesta que se obtiene contiene HTML.
Esta es otra función asíncrona async def get_message(request: Request):. Se declara una función de operación de ruta con un parámetro de tipo Request.
Por último, return templates.TemplateResponse("index.html", {"request": request}) renderiza tu plantilla o tu respuesta. Toma argumentos en el archivo HTML (index.html) y el contexto, que mantiene un registro de los datos que obtenemos de nuestra solicitud.
Usted creó la ruta que hace el GET anteriormente. También tienes que crear una ruta POST porque necesitas enviar datos a un formulario. Antes de eso, decides hacer las plantillas en el directorio de tu proyecto para guardar tus archivos HTML. Creas dos archivos HTML dentro de templates: index.html y sent_sms.html.
A continuación, en su index.html, incluyes esta marca:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Send a Text Message</h1>
<form action="/sent_sms" method="POST" novalidate>
<input type="text" placeholder="Enter number to text" name="to_number">
<button type=submit">Send Text</button>
</form>
</body>
</html>
Esta línea es crucial: <form action="/sent_sms" method="POST" novalidate>. El método método le indica cómo enviar los datos del formulario como POST. El atributo acción especifica a qué página enviar los datos del formulario. Se envía a sent_sms.html. Tenga en cuenta que el método POST aquí no muestra los datos en la URL como lo haría un GET. En su lugar, añade los datos dentro del cuerpo de la petición HTTP.
En <input type="text" placeholder="Enter number to text" name="to_number" > se define un elemento de entrada de tipo text y se le asigna un texto de marcador de posición que se mostrará dentro del cuadro de texto. A continuación, proporcione un atributo de nombre llamado to_number que especifica el nombre del elemento de entrada. Es importante que cuando hagas referencia al atributo obtengas el número al que vas a enviar el SMS.
En esta línea <button type=submit">Send Text</button> se define un botón con type=”submit". El texto se enviará al hacer clic en el botón.
A continuación, construye la página de SMS enviados.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Send a Text Message</h1>
<h3>Thank you {{ number }} | {{ error}}!</h3>
</body>
</html>
Si el SMS se envía correctamente, verás esta página. Lo único complicado es esto: {{ number }} | {{ error}}, que es el lenguaje de plantillas Jinja. Te mostrará el número de teléfono que has puesto en el formulario o un error. El número de teléfono es el que quieres enviar el SMS. Ahora vas a escribir la ruta POST y verás cómo funciona.
Ahora te sientes bastante bien porque estás en la recta final. Pero ahora está lloviendo y te preocupa que se te estropee el portátil. Así que tus dedos se ponen a codificar.
Continúa en el archivo main.py añadiendo este método POST:
from fastapi import FastAPI, Request, Form
from base64 import b64encode
import requests
import json
@app.post("/send_sms", response_class=HTMLResponse)
async def send_message(request: Request, to_number: str = Form(...)):
payload = {
"to": {
"type": "sms",
"number": to_number
},
"from": {
"type": "sms",
"number": [YOUR_VONAGE_NUMBER]
},
"message": {
"content": {
"type": "text",
"text": "Help me! I need to watch Loki!"
}
}
}
key = 'abcde'
secret = '12345'
encoded_credentials = b64encode(bytes(f'{key}:{secret}',
encoding='ascii')).decode('ascii')
auth_header = f'Basic {encoded_credentials}'
headers = {"content-type": "application/json", "Authorization": auth_header}
response = requests.post("https://api.nexmo.com/v0.1/messages",
auth=(key, secret),
headers=headers,
data=json.dumps(payload))
if response:
return templates.TemplateResponse("send.html", {"request": request, "number": to_number})
return templates.TemplateResponse("send.html", {"request": request, "error": "There is an error!"})Aquí se importa el Formulario objeto from fastapi import FastAPI, Request. Formulario le permite recibir datos de campos de formulario.
Esta línea, from base64 import b64encode, es necesaria para codificar la clave y el secreto de la API.
Usted import requests para enviar peticiones HTTP y import JSON porque tienes que hacer algunas cosas con JSON.
Esta línea debería resultarle familiar @app.post("/send_sms", response_class=HTMLResponse). Aquí tiene una operación @app.post y pasas una respuesta HTML.
Usted tiene su función async de nuevo async def send_message(request: Request, to_number: str = Form(...)): . Defines los parámetros del formulario como una sugerencia de tipo y lo lees usando Form(...).
La carga útil o cuerpo de datos que enviará a su solicitud:
payload = {
"to": {
"type": "sms",
"number": to_number
},
"from": {
"type": "sms",
"number": [YOUR_VONAGE_NUMBER]
},
"message": {
"content": {
"type": "text",
"text": "Help me! I need to watch Loki!"
}
}
}Algunas cosas a tener en cuenta sobre este par clave/valor en la carga útil: "number": to_number. to_number es el mismo valor que en nuestro index.html con el atributo name establecido en to_number. Para utilizarlo, tendrás que usar su clave: número.
"to": {
"type": "sms",
"number": to_number
},Otra cosa a notar en el payload es el número: [YOUR_VONAGE_NUMBER]que será tu número de teléfono de Vonage que compraste aquí.
"from": {
"type": "sms",
"number": [YOUR_VONAGE_NUMBER]
},Por último, en la carga útil, deje el tipo establecido en texto de la siguiente manera "tipo": "texto" y proporcione un mensaje para su texto como este "text": "¡Ayúdame! Necesito ver a Loki!".
"message": {
"content": {
"type": "text",
"text": "Help me! I need to watch Loki!"
}A continuación, se definen las cabeceras de la solicitud, lo que indica que el formato del cuerpo de la solicitud es JSON:
headers = {"content-type": "application/json"}Aquí haces una pausa de un segundo y recuerdas que necesitarás usar autenticación para la siguiente línea de código. Puedes elegir entre usar un JWT o Autenticación Básicay eliges esta última.
En estas variables se almacenan la clave y el secreto de la API:
key = 'abcde'
secret = '12345'A continuación, crea una variable llamada encoded_credentials y realiza la codificación Base64 utilizando una cadena f y pasando tu clave y secreto.
encoded_credentials = b64encode(bytes(f'{key}:{secret}',
encoding='ascii')).decode('ascii')Usted crea su cabecera de autorización, un par clave/valor que incluye su nombre de usuario y contraseña codificados en Base64. Este par autentica sus solicitudes y le permite acceder a la API.
auth_header = f'Basic {encoded_credentials}'A continuación, introduzca el encabezado de autorización:
headers = {"content-type": "application/json", "Authorization": auth_header}¡Ahora la parte divertida! Aquí usas el módulo requests y envías una solicitud de publicación requests.post a la API de Vonage. Pasas la URL de la API (https://api.nexmo.com/v0.1/messages) y usas HTTP Basic Auth desde el módulo requests. La palabra clave auth proporciona un acceso directo y te permite realizar Autenticación básica. Luego pasas las cabeceras headers=headers y el cuerpo de la petición, un objeto diccionario Python. Lo conviertes en una cadena JSON data=json.dumps(payload).
response = requests.post("https://api.nexmo.com/v0.1/messages",
auth=(key, secret),
headers=headers,
data=json.dumps(payload))El último paso es renderizar la plantilla. Aquí se comprueba si la respuesta es 200 o ok con if response. Luego pasas send.html, la petición y el contexto. El contexto "número": a_número mostrará el número en send.html. Por último, se muestra el mensaje de error si algo va mal.
if response:
return templates.TemplateResponse("send.html", {"request": request, "number": to_number})
return templates.TemplateResponse("send.html", {"request": request, "error": "There is an error!"})Es el momento de hacerlo o morir.
Ponga en marcha su servidor:
Usted navega a su localhost http://127.0.0.1:8000/
Introduce un número de teléfono para enviar un SMS a tu amigo.

Estás supernervioso y te preguntas si recibirán el SMS. Buenas noticias. ¡Han recibido el SMS!


Ves acercarse un barco y te das cuenta de que es para ti.
Te subes y te pone a salvo.
Más tarde, por la noche, te tumbas en la cama a ver Loki, pensando para ti mismo: Gracias a Dios por Python.
El final.
Dime si has enviado un SMS con este tutorial. Puedes tuitearme en @tonyasims.