https://d226lax1qjow5r.cloudfront.net/blog/blogposts/send-messages-with-nexmo-through-golang-and-aws-lambda-dr/AWS_SMS_1200x675.jpg

Envoyer des messages avec Nexmo via Golang et AWS Lambda

Publié le May 21, 2021

Temps de lecture : 6 minutes

J'ai récemment vu un tutoriel de Tom Morris sur le blog de Nexmo intitulé Envoyer des SMS depuis Python avec Google Cloud Functionset j'ai pensé qu'il s'agissait d'un exemple et d'une utilisation intéressants de la messagerie SMS, même si Python et Google Cloud Functions ne sont pas dans mes habitudes.

Après avoir lu le blog, j'ai pensé qu'il serait intéressant de l'étendre à AWS Lambda en tant que fournisseur de fonctions et de changer le langage pour Golang, quelque chose qui me passionne.

Dans ce tutoriel, nous allons créer une API à l'aide d'AWS Lambda et d'AWS API Gateway qui envoie un SMS avec l'API Nexmo Messaging, mais avec le langage de programmation Go.

Les exigences

Quelques conditions doivent être remplies avant de suivre ce tutoriel :

  • Vous devez avoir installé Go et être au moins un peu familier avec le langage.

  • Vous devez disposer d'un Account de développeur Nexmo.

  • Vous devez disposer d'un compte Amazon Web Services.

Go étant un langage compilé, nous devons pouvoir développer et construire localement. Nos builds seront téléchargés sur AWS, d'où la nécessité d'un compte AWS. Ces Applications utiliseront l'API Nexmo Messaging.

Construire une fonction de messagerie avec Go et le SDK AWS Lambda

En ce qui concerne le développement de l'application Go, il ne se passe pas grand-chose. En termes de flux d'événements, ils ressembleront à peu près à ceci :

  1. L'utilisateur adresse une demande à la fonction.

  2. Cette fonction envoie une requête HTTP à l'API Messages Nexmo.

  3. La fonction répondra avec l'identifiant de l'erreur ou du message provenant de l'API.

Bien que la logique de base s'articule autour d'une requête HTTP, il y aura un peu de configuration en ce qui concerne le modèle de données de la requête et de la réponse.

Dans le répertoire $GOPATHcréez un nouveau projet avec un fichier main.go qui contient les éléments suivants :

package main

var NEXMO_API_KEY string = "API_KEY_HERE"
var NEXMO_API_SECRET string = "API_SECRET_HERE"

func main() {}

La clé et le secret de l'API peuvent être obtenus à partir du portail des développeurs Nexmo.

Comme il s'agira d'un projet AWS Lambda, le SDK Go pour Lambda doit être installé. À partir de la ligne de commande, exécutez ce qui suit :

go get github.com/aws/aws-lambda-go/lambda

Une fois le SDK installé via le gestionnaire de paquets Go, il peut être utilisé dans le projet. Pour l'utiliser dans le projet, nous pouvons effectuer les changements suivants :

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)
}

Comme vous pouvez probablement vous en douter, toute notre logique de messagerie apparaîtra dans la fonction Handler puisque c'est ce qui sera exécuté lorsque le client fera une requête Lambda.

Avant d'entrer dans la logique, nous devons définir des modèles de données pour les différentes requêtes et réponses. Go exige que nous définissions explicitement nos modèles de données par le biais de struct afin que JSON puisse être correctement marshallé entre les requêtes.

Ajoutez ce qui suit au fichier main.go le texte suivant :

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 vous avez déjà utilisé l'API Messages Nexmo, vous connaissez le JSON qui doit être envoyé avec chaque demande à l'API. Les structures de données ci-dessus représentent les données qui seront envoyées. Avec les annotations JSON en place, le JSON ressemblerait à ceci :

{
    "from": { "type": "sms", "number": "SENDER_NUMBER_HERE" },
    "to": { "type": "sms", "number": "RECIPIENT_NUMBER_HERE" },
    "message": {
        "content": {
            "type": "text",
            "text": "Hello World"
        }
    }
}

Lorsque vous envoyez une demande à l'API Messages Nexmo, une réponse avec un UUID sera renvoyée si elle a réussi. Nous avons écrit une NexmoMessagesResponse qui contient ces données et nous prévoyons de les renvoyer au client.

La seule chose qui nous manque maintenant est la requête que le client fera à la fonction Lambda. Si notre exemple tente d'imiter celui de Google Cloud Functions, nous attendons un numéro de téléphone du destinataire et la plateforme mobile qu'il utilise.

En gardant ces informations à l'esprit, nous pouvons créer une structure de données qui ressemble à ce qui suit :

type LambdaRequest struct {
	Platform  string `json:"platform"`
	Recipient string `json:"recipient"`
}

Une fois tous les modèles de données élaborés, nous pouvons consacrer le reste de nos efforts à l'élaboration de la demande de messagerie.

Faire des requêtes HTTP en Go n'est pas un processus difficile. J'ai expliqué quelques approches en profondeur, dans un tutoriel précédent que j'ai écrit et qui s'intitule Consommer des points d'extrémité d'API RESTful au sein d'une application Golangbien que mon choix personnel soit d'utiliser une structure Go http.Client . Dans cet exemple particulier, nous allons avoir besoin de faire une requête POST comme indiqué dans la documentation Nexmo.

Commençons par créer une fonction SendMessage qui construira essentiellement une requête comme celle des nombreux exemples 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 fonction ci-dessus prend un map[string]string et renvoie un NexmoMessagesResponse ou une erreur. La première partie de la fonction prend les données de la carte et construit un objet qui sera transformé en JSON. Lorsqu'il s'agit de construire la requête HTTP, l'objet est utilisé comme corps et divers en-têtes sont définis, dont un en-tête d'autorisation.

Nexmo peut utiliser un jeton Web JSON (JWT) ou la clé et le secret de l'API. Dans cet exemple, la clé et le secret de l'API seront utilisés.

La fonction SendMessage est la plus grande partie du travail effectué.

Puisque nous utilisons le SDK AWS Lambda pour Go et que nous avons une fonction Handler l'étape suivante consiste à définir le contenu de la fonction Handler . Cela devrait ressembler à ceci :

func Handler(request LambdaRequest) (NexmoMessagesResponse, error) {
	return SendMessage(
		map[string]string{
			"from":    "15404161937",
			"to":      request.Recipient,
			"message": request.Platform,
		},
	)
}

N'oubliez pas que le client qui accède à notre API doit fournir les informations relatives à la plate-forme et au destinataire. N'oubliez pas qu'ils doivent définir la plateforme mobile qu'ils utilisent et le numéro de téléphone auquel le message SMS doit être envoyé.

Si vous pouvez le croire, la fonction AWS Lambda est complète. Lorsqu'elle est déclenchée avec les informations appropriées sur le destinataire et la plateforme, le SMS sera envoyé et l'identifiant du message sera renvoyé.

Ensuite, nous devons intégrer la fonction dans AWS Lambda et la rendre accessible dans le cadre de requêtes HTTP standard, typiquement dans une API.

Configurer AWS Lambda et AWS API Gateway en tant qu'API Web évolutive

Avant même d'entrer dans le portail AWS, nous devrions probablement construire notre projet Go. À partir de la ligne de commande, dans le chemin du projet, exécutez ce qui suit :

GOOS=linux go build

AWS exige que notre application soit compatible avec Linux. Heureusement pour nous, Go est livré avec toutes les chaînes d'outils nécessaires à la compilation croisée. Pour plus d'informations sur la compilation croisée avec Go, consultez mon précédent tutoriel sur le sujet.

Dans le cadre d'une exigence Lambda, le binaire doit être zippé. Notez le nom du fichier et ajoutez-le à une archive ZIP à la racine de l'archive. Le nom de fichier du binaire représente le nom du gestionnaire.

Ensuite, il faut se rendre dans la AWS Developer Console et choisissez de créer une nouvelle fonction Lambda. Le nom n'est pas très important, assurez-vous simplement qu'elle utilise le runtime Go.

AWS Developer ConsoleAWS Developer Console

Dans le tableau de bord de la fonction concernée, choisissez de télécharger l'archive ZIP que vous venez de créer. N'oubliez pas de fournir le nom de fichier correct pour les informations relatives au gestionnaire.

Nous allons également vouloir ajouter API Gateway comme déclencheur de la fonction.

Entrez dans la partie API Gateway de la AWS Developer Console. C'est là qu'un point final public sera créé pour pointer vers la fonction. Dans le tableau de bord de la passerelle API, choisissez Créer une méthode dans la section Ressources dans l'onglet Ressources.

Create MethodCreate Method

La méthode créée doit être une requête POST et doit faire référence à la valeur ARN de la fonction AWS Lambda lorsqu'elle est demandée. Lorsque vous avez terminé, n'oubliez pas de déployer l'API par le même menu que pour la création d'une nouvelle méthode.

À ce stade, la fonction Lambda devrait être accessible via la passerelle API qui a été configurée. Nous pouvons obtenir l'URL par l'intermédiaire de l'élément Étapes si un domaine personnalisé n'est pas configuré.

Conclusion

Nous venons de voir comment envoyer des messages à des appareils mobiles en utilisant AWS Lambda et le langage de programmation Go. Pour résumer, si un utilisateur devait faire une demande à l'API, gérée avec API Gateway, la demande passerait par AWS Lambda, serait envoyée à Nexmo, puis serait envoyée à l'appareil de l'utilisateur. Un cas d'utilisation, comme mentionné précédemment, pourrait être d'envoyer le lien du magasin d'applications, qu'il s'agisse de Google Play ou d'iTunes, au téléphone de l'utilisateur par SMS.

Bien qu'il ne soit pas abordé dans cet exemple, nous pouvons facilement compléter ce projet en créant un front-end avec lequel vos utilisateurs peuvent s'engager plutôt que d'avoir strictement une API RESTful.

Partager:

https://a.storyblok.com/f/270183/384x384/5b89273998/nraboy.png
Nic Raboy