

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Didacticiel : création d’un point de terminaison webhook à l’aide d’une URL de fonction Lambda
<a name="urls-webhook-tutorial"></a>

Dans ce didacticiel, vous créez une URL de fonction Lambda pour implémenter un point de terminaison webhook. Un webhook est une communication légère pilotée par les événements qui envoie automatiquement des données entre applications via HTTP. Vous pouvez utiliser un webhook pour recevoir des mises à jour immédiates sur les événements survenant dans un autre système, par exemple lorsqu’un nouveau client s’inscrit sur un site Web, qu’un paiement est traité ou qu’un fichier est chargé.

Avec Lambda, les webhooks peuvent être implémentés à l'aide de la fonction Lambda ou d'API Gateway. URLs URLs Les fonctions sont un bon choix pour les webhooks simples qui ne nécessitent pas de fonctionnalités telles que l'autorisation avancée ou la validation des demandes.

**Astuce**  
Si vous ne savez pas quelle est la solution la mieux adaptée à votre cas d’utilisation particulier, consultez [Sélection d’une méthode pour invoquer votre fonction Lambda à l’aide d’une requête HTTP](furls-http-invoke-decision.md).

## Conditions préalables
<a name="urls-webhook-tutorial-prereqs"></a>

Pour terminer ce didacticiel, Python (version 3.8 ou ultérieure) ou Node.js (version 18 ou ultérieure) doit être installé sur votre machine locale.

Pour tester le point de terminaison à l’aide d’une requête HTTP, le didacticiel utilise [curl](https://curl.se/), un outil de ligne de commande que vous pouvez utiliser pour transférer des données à l’aide de différents protocoles réseau. Reportez-vous à la [documentation curl](https://curl.se/docs/install.html) pour savoir comment installer l’outil si vous ne l’avez pas déjà.

## Créer la fonction Lambda
<a name="urls-webhook-tutorial-function"></a>

Créez d’abord la fonction Lambda qui s’exécute lorsqu’une requête HTTP est envoyée à votre point de terminaison webhook. Dans cet exemple, l’application d’envoi envoie une mise à jour chaque fois qu’un paiement est soumis, et indique dans le corps de la requête HTTP si le paiement a été effectué avec succès. La fonction Lambda analyse la demande et agit en fonction du statut du paiement. Dans cet exemple, le code imprime simplement l’ID de commande pour le paiement, mais dans une application réelle, vous pouvez ajouter la commande à une base de données ou envoyer une notification.

La fonction implémente également la méthode d’authentification la plus couramment utilisée pour les webhooks, l’authentification des messages basée sur le hachage (HMAC). Avec cette méthode, les applications d’envoi et de réception partagent une clé secrète. L’application d’envoi utilise un algorithme de hachage pour générer une signature unique à l’aide de cette clé associée au contenu du message, et inclut la signature dans la demande de webhook sous forme d’en-tête HTTP. L’application réceptrice répète ensuite cette étape en générant la signature à l’aide de la clé secrète, et compare la valeur obtenue avec la signature envoyée dans l’en-tête de la demande. Si le résultat correspond, la demande est considérée comme légitime. 

Créez la fonction à l’aide de la console Lambda avec l’environnement d'exécution Python ou Node.js.

------
#### [ Python ]

**Créer la fonction Lambda**

1. Ouvrez la [page Functions](https://console.aws.amazon.com/lambda/home#/functions) (Fonctions) de la console Lambda.

1. Créez une fonction de type « Hello World » de base en procédant comme suit :

   1. Choisissez **Créer une fonction**.

   1. Sélectionnez **Créer à partir de zéro**.

   1. Sous **Nom de la fonction**, saisissez **myLambdaWebhook**.

   1. Pour **Runtime**, sélectionnez **python3.14**.

   1. Choisissez **Créer une fonction**.

1. Dans le volet **Source du code**, remplacez le code existant en copiant et en collant ce qui suit :

   ```
   import json
   import hmac
   import hashlib
   import os
   
   def lambda_handler(event, context):
       
       # Get the webhook secret from environment variables
       webhook_secret = os.environ['WEBHOOK_SECRET']
       
       # Verify the webhook signature
       if not verify_signature(event, webhook_secret):
           return {
               'statusCode': 401,
               'body': json.dumps({'error': 'Invalid signature'})
           }
       
       try:
           # Parse the webhook payload
           payload = json.loads(event['body'])
           
           # Handle different event types
           event_type = payload.get('type')
           
           if event_type == 'payment.success':
               # Handle successful payment
               order_id = payload.get('orderId')
               print(f"Processing successful payment for order {order_id}")
               
               # Add your business logic here
               # For example, update database, send notifications, etc.
               
           elif event_type == 'payment.failed':
               # Handle failed payment
               order_id = payload.get('orderId')
               print(f"Processing failed payment for order {order_id}")
               
               # Add your business logic here
               
           else:
               print(f"Received unhandled event type: {event_type}")
           
           # Return success response
           return {
               'statusCode': 200,
               'body': json.dumps({'received': True})
           }
           
       except json.JSONDecodeError:
           return {
               'statusCode': 400,
               'body': json.dumps({'error': 'Invalid JSON payload'})
           }
       except Exception as e:
           print(f"Error processing webhook: {e}")
           return {
               'statusCode': 500,
               'body': json.dumps({'error': 'Internal server error'})
           }
   
   def verify_signature(event, webhook_secret):
       """
       Verify the webhook signature using HMAC
       """
       try:
           # Get the signature from headers
           signature = event['headers'].get('x-webhook-signature')
   
           if not signature:
               print("Error: Missing webhook signature in headers")
               return False
           
           # Get the raw body (return an empty string if the body key doesn't exist)
           body = event.get('body', '')
           
           # Create HMAC using the secret key
           expected_signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
           
           # Compare the expected signature with the received signature to authenticate the message
           is_valid = hmac.compare_digest(signature, expected_signature)
           if not is_valid:
               print(f"Error: Invalid signature. Received: {signature}, Expected: {expected_signature}")
               return False
               
           return True
       except Exception as e:
           print(f"Error verifying signature: {e}")
           return False
   ```

1. Dans la section **DÉPLOYER**, choisissez **Déployer** pour mettre à jour le code de votre fonction.

------
#### [ Node.js ]

**Créer la fonction Lambda**

1. Ouvrez la [page Functions](https://console.aws.amazon.com/lambda/home#/functions) (Fonctions) de la console Lambda.

1. Créez une fonction de type « Hello World » de base en procédant comme suit :

   1. Choisissez **Créer une fonction**.

   1. Sélectionnez **Créer à partir de zéro**.

   1. Sous **Nom de la fonction**, saisissez **myLambdaWebhook**.

   1. Pour **Runtime**, sélectionnez **nodejs24.x**.

   1. Choisissez **Créer une fonction**.

1. Dans le volet **Source du code**, remplacez le code existant en copiant et en collant ce qui suit :

   ```
   import crypto from 'crypto';
   
   export const handler = async (event, context) => {
       // Get the webhook secret from environment variables
       const webhookSecret = process.env.WEBHOOK_SECRET;
   
       // Verify the webhook signature
       if (!verifySignature(event, webhookSecret)) {
           return {
               statusCode: 401,
               body: JSON.stringify({ error: 'Invalid signature' })
           };
       }
   
       try {
           // Parse the webhook payload
           const payload = JSON.parse(event.body);
   
           // Handle different event types
           const eventType = payload.type;
   
           switch (eventType) {
               case 'payment.success': {
                   // Handle successful payment
                   const orderId = payload.orderId;
                   console.log(`Processing successful payment for order ${orderId}`);
   
                   // Add your business logic here
                   // For example, update database, send notifications, etc.
                   break;
               }
   
               case 'payment.failed': {
                   // Handle failed payment
                   const orderId = payload.orderId;
                   console.log(`Processing failed payment for order ${orderId}`);
   
                   // Add your business logic here
                   break;
               }
   
               default:
                   console.log(`Received unhandled event type: ${eventType}`);
           }
   
           // Return success response
           return {
               statusCode: 200,
               body: JSON.stringify({ received: true })
           };
   
       } catch (error) {
           if (error instanceof SyntaxError) {
               // Handle JSON parsing errors
               return {
                   statusCode: 400,
                   body: JSON.stringify({ error: 'Invalid JSON payload' })
               };
           }
   
           // Handle all other errors
           console.error('Error processing webhook:', error);
           return {
               statusCode: 500,
               body: JSON.stringify({ error: 'Internal server error' })
           };
       }
   };
   
   // Verify the webhook signature using HMAC
   
   const verifySignature = (event, webhookSecret) => {
       try {
           // Get the signature from headers
           const signature = event.headers['x-webhook-signature'];
     
           if (!signature) {
               console.log('No signature found in headers:', event.headers);
               return false;
           }
     
           // Get the raw body (return an empty string if the body key doesn't exist)
           const body = event.body || '';
     
           // Create HMAC using the secret key
           const hmac = crypto.createHmac('sha256', webhookSecret);
           const expectedSignature = hmac.update(body).digest('hex');
     
           // Compare expected and received signatures
           const isValid = signature === expectedSignature;
           if (!isValid) {
               console.log(`Invalid signature. Received: ${signature}, Expected: ${expectedSignature}`);
               return false;
           }
           
           return true;
       } catch (error) {
           console.error('Error during signature verification:', error);
           return false;
       }
     };
   ```

1. Dans la section **DÉPLOYER**, choisissez **Déployer** pour mettre à jour le code de votre fonction.

------

## Créer la clé de secret
<a name="urls-webhook-tutorial-key"></a>

Pour que la fonction Lambda authentifie la demande de webhook, elle utilise une clé secrète qu’elle partage avec l’application appelante. Dans cet exemple, la clé est stockée dans une variable d’environnement. Dans une application de production, n’incluez pas d’informations sensibles telles que des mots de passe dans votre code de fonction. [Créez plutôt un AWS Secrets Manager secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html), puis [utilisez l'extension Lambda AWS Parameters and Secrets](with-secrets-manager.md) pour récupérer vos informations d'identification dans votre fonction Lambda.

**Créer et stocker la clé secrète du webhook**

1. Générez une longue chaîne aléatoire à l’aide d’un générateur de nombres aléatoires sécurisé par cryptographie. Vous pouvez utiliser les extraits de code suivants en Python ou Node.js pour générer et imprimer un secret de 32 caractères, ou utiliser votre propre méthode préférée.

------
#### [ Python ]

**Example code pour générer un secret**  

   ```
   import secrets
   webhook_secret = secrets.token_urlsafe(32)
   print(webhook_secret)
   ```

------
#### [ Node.js ]

**Example code pour générer un secret (format du module ES)**  

   ```
   import crypto from 'crypto';
   let webhookSecret = crypto.randomBytes(32).toString('base64');
   console.log(webhookSecret)
   ```

------

1. Stockez la chaîne générée en tant que variable d’environnement pour votre fonction en procédant comme suit :

   1. Dans l’onglet **Configuration** de votre fonction, sélectionnez **Variables d’environnement**.

   1. Choisissez **Modifier**.

   1. Choisissez **Ajouter une variable d’environnement**.

   1. Pour **Clé**, saisissez **WEBHOOK\$1SECRET**, puis pour **Valeur**, saisissez le secret que vous avez généré à l’étape précédente.

   1. Choisissez **Enregistrer**.

Vous devrez réutiliser ce secret ultérieurement dans le didacticiel pour tester votre fonction. Veillez donc à le noter dès maintenant.

## Créer le point de terminaison d’URL de fonction
<a name="urls-webhook-tutorial-furl"></a>

Créez un point de terminaison pour votre webhook à l’aide d’une URL de fonction Lambda. Comme vous utilisez le type d’authentification `NONE` pour créer un point de terminaison avec accès public, toute personne disposant de l’URL peut invoquer votre fonction. Pour en savoir plus sur le contrôle de l'accès aux fonctions URLs, voir[Contrôler l'accès à la fonction Lambda URLs](urls-auth.md). Si vous avez besoin d’options d’authentification plus avancées pour votre webhook, pensez à utiliser API Gateway.

**Créer le point de terminaison d’URL de fonction**

1. Dans l’onglet **Configuration** de votre fonction, sélectionnez **URL de la fonction**.

1. Choisissez **Create function URL** (Créer une URL de fonction).

1. Pour **Type d’authentification**, sélectionnez **NONE**.

1. Choisissez **Enregistrer**.

Le point de terminaison de l’URL de fonction que vous venez de créer s’affiche dans le volet **URL de fonction**. Copiez le point de terminaison ; vous l’utiliserez ultérieurement dans le didacticiel.

## Tester la fonction dans console
<a name="urls-webhook-tutorial-test-console"></a>

Avant d’utiliser une requête HTTP pour invoquer votre fonction à l’aide du point de terminaison d’URL, testez-la dans la console pour vérifier que votre code fonctionne comme prévu.

Pour vérifier la fonction dans la console, vous devez d’abord calculer une signature de webhook à l’aide du secret que vous avez généré plus tôt dans le didacticiel avec les données utiles JSON de test suivantes :

```
{
    "type": "payment.success", 
    "orderId": "1234",
    "amount": "99.99"
}
```

Utilisez l’un des exemples de code Python ou Node.js suivants pour calculer la signature du webhook à l’aide de votre propre secret.

------
#### [ Python ]

**Calculer la signature du webhook**

1. Enregistrez le code suivant dans un fichier nommé `calculate_signature.py`. Remplacez le secret de webhook dans le code par votre propre valeur.

   ```
   import secrets
   import hmac
   import json
   import hashlib
   
   webhook_secret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   
   body = json.dumps({"type": "payment.success", "orderId": "1234", "amount": "99.99"})
   
   signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
   
   print(signature)
   ```

1. Calculez la signature en exécutant la commande suivante à partir du répertoire où vous avez enregistré le code. Copiez la signature émise par le code.

   ```
   python calculate_signature.py
   ```

------
#### [ Node.js ]

**Calculer la signature du webhook**

1. Enregistrez le code suivant dans un fichier nommé `calculate_signature.mjs`. Remplacez le secret de webhook dans le code par votre propre valeur.

   ```
   import crypto from 'crypto';
   
   const webhookSecret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   const body = "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}";
   
   let hmac = crypto.createHmac('sha256', webhookSecret);
   let signature = hmac.update(body).digest('hex');
   
   console.log(signature);
   ```

1. Calculez la signature en exécutant la commande suivante à partir du répertoire où vous avez enregistré le code. Copiez la signature émise par le code.

   ```
   node calculate_signature.mjs
   ```

------

Vous pouvez désormais tester le code de votre fonction à l’aide d’une requête HTTP de test dans la console.

**Tester la fonction dans console**

1. Sélectionnez l’onglet **Code** correspondant à votre fonction.

1. Dans la section **ÉVÉNEMENTS DE TEST**, choisissez **Créer un nouvel événement de test**.

1. Dans **Event Name (Nom de l'événement)**, saisissez **myEvent**.

1. Remplacez le JSON existant en copiant et en collant ce qui suit dans le volet **JSON d’événement**. Remplacez la signature de webhook par la valeur calculée à l’étape précédente.

   ```
   {
     "headers": {
       "Content-Type": "application/json",
       "x-webhook-signature": "2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a"
     },
     "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}"
   }
   ```

1. Choisissez **Enregistrer**.

1. Sélectionnez **Invoquer **.

   Vous devez voir des résultats similaires à ce qui suit :

------
#### [ Python ]

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\": true}"
   }
   
   Function Logs:
   START RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Version: $LATEST
   Processing successful payment for order 1234
   END RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6
   REPORT RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6	Duration: 1.55 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 36 MB	Init Duration: 136.32 ms
   ```

------
#### [ Node.js ]

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\":true}"
   }
   
   Function Logs:
   START RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 Version: $LATEST
   2025-01-10T18:05:42.062Z	e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	INFO	Processing successful payment for order 1234
   END RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   REPORT RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	Duration: 60.10 ms	Billed Duration: 61 ms	Memory Size: 128 MB	Max Memory Used: 72 MB	Init Duration: 174.46 ms
   
   Request ID: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   ```

------

## Tester la fonction avec une requête HTTP
<a name="urls-webhook-tutorial-test-curl"></a>

Utilisez l’outil de ligne de commande curl pour tester votre point de terminaison webhook.

**Tester la fonction avec des requêtes HTTP**

1. Dans un terminal ou un programme shell, exécutez la commande curl suivante. Remplacez l’URL par la valeur du point de terminaison de votre URL de fonction et remplacez la signature du webhook par la signature que vous avez calculée à l’aide de votre propre clé secrète.

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: d5f52b76ffba65ff60ea73da67bdf1fc5825d4db56b5d3ffa0b64b7cb85ef48b" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   Vous devriez voir la sortie suivante :

   ```
   {"received": true}
   ```

1. Examinez les CloudWatch journaux de votre fonction pour confirmer qu'elle a correctement analysé la charge utile en procédant comme suit :

   1. Ouvrez la page du [groupe Logs](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) dans la CloudWatch console Amazon.

   1. Sélectionnez le groupe de journaux de votre fonction (`/aws/lambda/myLambdaWebhook`).

   1. Sélectionnez le flux de journaux le plus récent.

      Vous devez voir des résultats similaires à ce qui suit dans les journaux de votre fonction :

------
#### [ Python ]

      ```
      Processing successful payment for order 1234
      ```

------
#### [ Node.js ]

      ```
      2025-01-10T18:05:42.062Z e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 INFO Processing successful payment for order 1234
      ```

------

1. Confirmez que votre code détecte une signature non valide en exécutant la commande curl suivante. Remplacez l’URL par le point de terminaison de l’URL de votre propre fonction.

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: abcdefg" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   Vous devriez voir la sortie suivante :

   ```
   {"error": "Invalid signature"}
   ```

## Nettoyage de vos ressources
<a name="urls-webhook-tutorial-cleanup"></a>

Vous pouvez maintenant supprimer les ressources que vous avez créées pour ce didacticiel, sauf si vous souhaitez les conserver. En supprimant AWS les ressources que vous n'utilisez plus, vous évitez des frais inutiles pour votre Compte AWS.

**Pour supprimer la fonction Lambda**

1. Ouvrez la [page Functions (Fonctions)](https://console.aws.amazon.com/lambda/home#/functions) de la console Lambda.

1. Sélectionnez la fonction que vous avez créée.

1. Sélectionnez **Actions**, **Supprimer**.

1. Saisissez **confirm** dans la zone de saisie de texte et choisissez **Delete** (Supprimer).

Lorsque vous avez créé la fonction Lambda dans la console, Lambda a également créé un [rôle d’exécution](lambda-intro-execution-role.md) pour votre fonction.

**Pour supprimer le rôle d’exécution**

1. Ouvrez la [page Roles (Rôles)](https://console.aws.amazon.com/iam/home#/roles) de la console IAM.

1. Sélectionnez le rôle d’exécution que Lambda a créé. Le nom du rôle est au format `myLambdaWebhook-role-<random string>`.

1. Sélectionnez **Delete (Supprimer)**.

1. Saisissez le nom du rôle dans le champ de saisie de texte et choisissez **Delete** (Supprimer).