
Enviar mensajes con Nexmo a través de Golang y AWS Lambda
Tiempo de lectura: 6 minutos
Hace poco vi un tutorial de Tom Morris en el blog de Nexmo titulado Envío de SMS desde Python con Google Cloud Functionsy me pareció un ejemplo y un uso interesantes de la mensajería SMS, a pesar de que Python y Google Cloud Functions no son lo mío.
Después de leer el blog, pensé que sería interesante ampliarlo a AWS Lambda como proveedor de funciones y cambiar el lenguaje a Golang, algo que me apasiona.
En este tutorial, vamos a crear una API utilizando AWS Lambda y AWS API Gateway que envíe un mensaje SMS con la API de mensajería Nexmo, pero con el lenguaje de programación Go.
Requisitos
Hay algunos requisitos que deben cumplirse antes de trabajar a través de este tutorial:
Necesitas tener Go instalado y estar al menos algo familiarizado con el lenguaje.
Necesitas tener una cuenta de desarrollador Nexmo.
Necesita tener una Account de Amazon Web Services.
Como Go es un lenguaje compilado, necesitamos poder desarrollar y compilar localmente. Nuestras compilaciones se subirán a AWS, de ahí la necesidad de una AWS Account. Estas Aplicaciones harán uso de la API de Mensajería Nexmo.
Creación de una función de mensajería con Go y el SDK de AWS Lambda
Cuando se trata del desarrollo de la aplicación Go, no hay mucho que hacer. En términos de flujo de eventos, que se verá algo como esto:
El usuario realizará una petición a la función.
La función enviará una petición HTTP a la API de Messages API de Nexmo.
La función responderá con el id de error o mensaje de la API.
Mientras que la lógica central girará en torno a una solicitud HTTP, habrá un poco de configuración en lo que respecta al modelo de datos de solicitud y respuesta.
Dentro del $GOPATHcree un nuevo proyecto con un archivo main.go que contenga lo siguiente:
package main
var NEXMO_API_KEY string = "API_KEY_HERE"
var NEXMO_API_SECRET string = "API_SECRET_HERE"
func main() {}Tanto la clave como el secreto de la API pueden obtenerse desde el portal para desarrolladores de Nexmo.
Como este va a ser un proyecto AWS Lambda, el Go SDK para Lambda debe ser instalado. Desde la línea de comandos, ejecuta lo siguiente:
go get github.com/aws/aws-lambda-go/lambdaCon el SDK instalado a través del gestor de paquetes Go, se puede utilizar dentro del proyecto. Para utilizarlo dentro del proyecto, podemos hacer los siguientes cambios:
package main
import "github.com/aws/aws-lambda-go/lambda"
var NEXMO_API_KEY string = "API_KEY_HERE"
var NEXMO_API_SECRET string = "API_SECRET_HERE"
func Handler() {}
func main() {
lambda.Start(Handler)
}Como probablemente puedas sospechar, toda nuestra lógica de mensajería aparecerá en la función Handler ya que es lo que se ejecutará cuando el cliente haga una petición Lambda.
Antes de entrar en la lógica, necesitamos definir algunos modelos de datos para las distintas peticiones y respuestas. Go requiere que definamos explícitamente nuestros modelos de datos mediante variables struct para que JSON pueda ser marshaled correctamente entre peticiones.
Añada lo siguiente al archivo main.go :
type NexmoMessageContent struct {
Type string `json:"type"`
Text string `json:"text"`
}
type NexmoMessage struct {
Content NexmoMessageContent `json:"content"`
}
type NexmoMessageService struct {
Type string `json:"type"`
Number string `json:"number"`
}
type NexmoMessagesRequest struct {
From NexmoMessageService `json:"from"`
To NexmoMessageService `json:"to"`
Message NexmoMessage `json:"message"`
}
type NexmoMessagesResponse struct {
Id string `json:"message_uuid"`
}Si alguna vez has utilizado la API Messages API de Nexmo, estarás familiarizado con el JSON que se espera que se envíe con cada solicitud a la API. Las estructuras de datos anteriores representan los datos que se enviarán. Con las anotaciones JSON en su lugar, el JSON se vería algo como esto:
{
"from": { "type": "sms", "number": "SENDER_NUMBER_HERE" },
"to": { "type": "sms", "number": "RECIPIENT_NUMBER_HERE" },
"message": {
"content": {
"type": "text",
"text": "Hello World"
}
}
}Al enviar una solicitud a la API de Nexmo Messages, se devolverá una respuesta con un UUID si tuvo éxito. Hemos escrito una estructura NexmoMessagesResponse struct que contiene estos datos y planeamos enviarlos de vuelta al cliente.
Lo único que nos falta ahora es la solicitud que el cliente hará a la función Lambda. Si nuestro ejemplo intenta imitar el ejemplo de Google Cloud Functions, esperamos un número de teléfono del destinatario y la plataforma móvil que utiliza.
Con esta información en mente, podemos crear una estructura de datos con el siguiente aspecto:
type LambdaRequest struct {
Platform string `json:"platform"`
Recipient string `json:"recipient"`
}Con todos los modelos de datos elaborados, podemos centrar el resto de nuestro esfuerzo en realizar la solicitud de mensajería.
Hacer peticiones HTTP en Go no es un proceso difícil. Expliqué algunos de los enfoques en profundidad, en un tutorial anterior que escribí titulado Consume RESTful API Endpoints dentro de una Aplicación Golangaunque mi opción personal sería utilizar una estructura Go http.Client . En este ejemplo en particular, vamos a tener que hacer una solicitud POST como se indica en la documentación de Nexmo.
Empecemos creando una función SendMessage que esencialmente construirá una petición como la de los muchos ejemplos cURL de Nexmo:
func SendMessage(body map[string]string) (NexmoMessagesResponse, error) {
nexmoMessagesRequest := &NexmoMessagesRequest{
From: NexmoMessageService{
Type: "sms",
Number: body["from"],
},
To: NexmoMessageService{
Type: "sms",
Number: body["to"],
},
Message: NexmoMessage{
Content: NexmoMessageContent{
Type: "text",
Text: body["message"],
},
},
}
bodyData, _ := json.Marshal(nexmoMessagesRequest)
request, _ := http.NewRequest("POST", "https://api.nexmo.com/v0.1/messages", bytes.NewBuffer(bodyData))
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Accept", "application/json")
request.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(NEXMO_API_KEY+":"+NEXMO_API_SECRET)))
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
return NexmoMessagesResponse{}, err
} else {
data, _ := ioutil.ReadAll(response.Body)
var result NexmoMessagesResponse
json.Unmarshal(data, &result)
return result, nil
}
}
La función anterior tomará un map[string]string y devolverá un NexmoMessagesResponse o un error. La primera parte de la función toma los datos del mapa y construye un objeto que se convertirá en JSON. Cuando se trata de construir la petición HTTP, el objeto se utiliza como cuerpo y se definen varias cabeceras, una de las cuales es una cabecera de autorización.
Con Nexmo se puede utilizar un JSON Web Token (JWT) o la clave y el secreto de la API. En este ejemplo, se utilizarán la clave y el secreto de la API.
La función SendMessage función es la que realiza la mayor parte del trabajo.
Dado que estamos utilizando el SDK de AWS Lambda para Go y tenemos una función Handler el siguiente paso es definir qué hay en la función Handler función. Debería ser algo como esto:
func Handler(request LambdaRequest) (NexmoMessagesResponse, error) {
return SendMessage(
map[string]string{
"from": "15404161937",
"to": request.Recipient,
"message": request.Platform,
},
)
}Recuerde que el cliente que accede a nuestra API debe proporcionar la información sobre la plataforma y el destinatario. Recuerde que deben definir qué plataforma móvil utilizan y el número de teléfono al que debe enviarse el mensaje SMS.
Si puedes creerlo, la función AWS Lambda está completa. Cuando se active con la información adecuada del destinatario y la plataforma, se enviará el mensaje SMS y se devolverá el id del mensaje.
A continuación, tenemos que obtener la función en AWS Lambda y hacer que la función sea accesible como parte de las solicitudes HTTP estándar, típicas en una API.
Configuración de AWS Lambda y AWS API Gateway como API web escalable
Antes de entrar en el portal de AWS, probablemente deberíamos construir nuestro proyecto Go. Desde la línea de comandos, mientras que en la ruta del proyecto, ejecute lo siguiente:
GOOS=linux go buildAWS requiere que nuestra aplicación sea compatible con Linux. Por suerte para nosotros, Go viene con todas las cadenas de herramientas correctas para la compilación cruzada. Para obtener más información sobre la compilación cruzada con Go, echa un vistazo a mi tutorial anterior sobre el tema.
Como parte de un requisito de Lambda, el binario debe estar comprimido. Toma nota del nombre del archivo y añádelo a un archivo ZIP en la raíz del archivo. El nombre de archivo del binario representa el nombre del manejador.
A continuación, acceda a la Consola de desarrollador de AWS y elige crear una nueva función Lambda. El nombre no es demasiado importante, solo asegúrate de que utiliza el tiempo de ejecución Go.
AWS Developer Console
En el panel de control de la función en cuestión, elija cargar el archivo ZIP que acaba de crear. Recuerde proporcionar el nombre de archivo correcto para la información del controlador.
También vamos a querer añadir API Gateway como un disparador para la función.
Entre en la parte de API Gateway de la consola de desarrollador de AWS. Aquí es donde se creará un endpoint público para apuntar a la función. En el panel de control de API Gateway, seleccione Crear método dentro de la sección Recursos pestaña.
Create Method
El método creado debe ser una solicitud POST y debe hacer referencia al valor ARN de la función AWS Lambda cuando se le pregunte. Cuando haya terminado, no se olvide de desplegar la API a través del mismo menú que la creación de un nuevo método.
En este punto, la función Lambda debería ser accesible a través de la API Gateway que se configuró. Podemos obtener la URL a través de Etapas si no se ha configurado un dominio personalizado.
Conclusión
Acabamos de ver cómo enviar mensajes a dispositivos móviles utilizando AWS Lambda y el lenguaje de programación Go. Resumiendo, si un usuario realizara una solicitud a la API, gestionada con API Gateway, la solicitud fluiría a AWS Lambda, se enviaría a Nexmo y, a continuación, se enviaría al dispositivo del usuario. Un caso de uso, como se mencionó anteriormente, podría ser enviar el enlace de la tienda de aplicaciones, ya sea Google Play o iTunes, al teléfono del usuario a través de SMS.
Aunque no se explora en este ejemplo, podemos añadir fácilmente a este proyecto mediante la creación de un front-end para sus usuarios a participar en lugar de tener estrictamente una API RESTful.