Tutorial: Erstellen eines Webhook-Endpunkts mithilfe einer Lambda-Funktions-URL - AWS Lambda

Tutorial: Erstellen eines Webhook-Endpunkts mithilfe einer Lambda-Funktions-URL

In diesem Tutorial erstellen Sie eine Lambda-Funktions-URL, um einen Webhook-Endpunkt zu implementieren. Ein Webhook ist eine einfache, ereignisgesteuerte Kommunikation, die automatisch Daten zwischen Anwendungen über HTTP sendet. Sie können Webhooks verwenden, um sofortige Benachrichtigungen über Ereignisse in einem anderen System zu erhalten, z. B. wenn sich ein neuer Kunde auf einer Website registriert, eine Zahlung verarbeitet wird oder eine Datei hochgeladen wird.

Mit Lambda können Webhooks entweder über Lambda-Funktions-URLs oder API Gateway implementiert werden. Funktions-URLs sind eine gute Wahl für einfache Webhooks, die keine Funktionen wie erweiterte Autorisierung oder Anforderungsvalidierung erfordern.

Tipp

Wenn Sie sich nicht sicher sind, welche Lösung für Ihren speziellen Anwendungsfall am besten geeignet ist, lesen Sie bitte Wählen Sie eine Methode, um Ihre Lambda-Funktion über eine HTTP-Anfrage aufzurufen.

Voraussetzungen

Um dieses Tutorial durchzuführen, muss entweder Python (Version 3.8 oder höher) oder Node.js (Version 18 oder höher) auf Ihrem lokalen Rechner installiert sein.

Um den Endpunkt mit einer HTTP-Anfrage zu testen, verwendet das Tutorial curl, ein Befehlszeilentool, mit dem Sie Daten über verschiedene Netzwerkprotokolle übertragen können. In der curl-Dokumentation erfahren Sie, wie Sie das Tool installieren, falls Sie das noch nicht getan haben.

So erstellen Sie die Lambda-Funktion:

Erstellen Sie zunächst die Lambda-Funktion, die ausgeführt wird, wenn eine HTTP-Anfrage an Ihren Webhook-Endpunkt gesendet wird. In diesem Beispiel sendet die sendende Anwendung bei jeder Zahlung eine Aktualisierung und gibt im Hauptteil der HTTP-Anfrage an, ob die Zahlung erfolgreich war. Die Lambda-Funktion analysiert die Anfrage und ergreift entsprechend dem Status der Zahlung Maßnahmen. In diesem Beispiel gibt der Code lediglich die Bestellnummer für die Zahlung aus, aber in einer realen Anwendung würden Sie die Bestellung möglicherweise einer Datenbank hinzufügen oder eine Benachrichtigung senden.

Die Funktion implementiert auch die gängigste Authentifizierungsmethode für Webhooks, die hashbasierte Nachrichtenauthentifizierung (HMAC). Bei dieser Methode teilen sich sowohl die sendende als auch die empfangende Anwendung einen geheimen Schlüssel. Die sendende Anwendung verwendet einen Hash-Algorithmus, um anhand dieses Schlüssels und des Nachrichteninhalts eine eindeutige Signatur zu generieren, und fügt die Signatur als HTTP-Header in die Webhook-Anfrage ein. Die empfangende Anwendung wiederholt diesen Schritt, generiert die Signatur unter Verwendung des geheimen Schlüssels und vergleicht den resultierenden Wert mit der im Anfrage-Header gesendeten Signatur. Stimmt das Ergebnis überein, wird die Anfrage als legitim angesehen.

Erstellen Sie die Funktion mithilfe der Lambda-Konsole mit der Python- oder Node.js-Laufzeit.

Python
So erstellen Sie die Lambda-Funktion:
  1. Öffnen Sie die Seite Funktionen der Lambda-Konsole.

  2. Erstellen Sie eine einfache „Hello World“-Funktion:

    1. Wählen Sie Funktion erstellen.

    2. Wählen Sie Verfassen von Grund auf aus.

    3. Geben Sie für Function name (Funktionsname) myLambdaWebhook ein.

    4. Wählen Sie für Laufzeit die Option python3.13 aus.

    5. Wählen Sie Funktion erstellen.

  3. Ersetzen Sie im Bereich Codequelle den vorhandenen Code durch Folgendes:

    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
  4. Wählen Sie im Abschnitt BEREITSTELLEN die Option Bereitstellen aus, um den Code Ihrer Funktion zu aktualisieren.

Node.js
So erstellen Sie die Lambda-Funktion:
  1. Öffnen Sie die Seite Funktionen der Lambda-Konsole.

  2. Erstellen Sie eine einfache „Hello World“-Funktion:

    1. Wählen Sie Funktion erstellen.

    2. Wählen Sie Verfassen von Grund auf aus.

    3. Geben Sie für Function name (Funktionsname) myLambdaWebhook ein.

    4. Wählen Sie für Laufzeit nodejs22.x.

    5. Wählen Sie Funktion erstellen.

  3. Ersetzen Sie im Bereich Codequelle den vorhandenen Code durch Folgendes:

    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; } };
  4. Wählen Sie im Abschnitt BEREITSTELLEN die Option Bereitstellen aus, um den Code Ihrer Funktion zu aktualisieren.

Erstellen des geheimen Schlüssels

Damit die Lambda-Funktion die Webhook-Anfrage authentifizieren kann, verwendet sie einen geheimen Schlüssel, den sie mit der aufrufenden Anwendung teilt. In diesem Beispiel wird der Schlüssel in einer Umgebungsvariablen gespeichert. Schließen Sie in einer Produktionsanwendung keine sensiblen Informationen wie Passwörter in Ihren Funktionscode ein. Erstellen Sie stattdessen ein AWS Secrets Manager-Secret und verwenden Sie dann die AWS-Parameter und Secrets-Lambda-Erweiterung, um Ihre Anmeldeinformationen in Ihrer Lambda-Funktion abzurufen.

Erstellen und Speichern des geheimen Webhook-Schlüssels
  1. Generieren Sie eine lange, zufällige Zeichenfolge mit einem kryptografisch sicheren Zufallszahlengenerator. Sie können die folgenden Codeausschnitte in Python oder Node.js verwenden, um einen 32-stelligen geheimen Schlüssel zu generieren und auszudrucken, oder Ihre eigene bevorzugte Methode verwenden.

    Python
    Beispiel Code zum Generieren eines geheimen Schlüssels
    import secrets webhook_secret = secrets.token_urlsafe(32) print(webhook_secret)
    Node.js
    Beispiel Code zum Generieren eines geheimen Schlüssels (ES-Modulformat)
    import crypto from 'crypto'; let webhookSecret = crypto.randomBytes(32).toString('base64'); console.log(webhookSecret)
  2. Speichern Sie Ihre generierte Zeichenfolge als Umgebungsvariable für Ihre Funktion:

    1. Wählen Sie auf der Registerkarte Konfiguration für Ihre Funktion die Option Umgebungsvariablen aus.

    2. Wählen Sie Bearbeiten aus.

    3. Wählen Sie Umgebungsvariablen hinzufügen aus.

    4. Geben Sie für Schlüssel WEBHOOK_SECRET ein und dann für Wert den geheimen Schlüssel, den Sie im vorherigen Schritt generiert haben.

    5. Wählen Sie Speichern.

Sie werden diesen geheimen Schlüssel später im Tutorial erneut verwenden müssen, um Ihre Funktion zu testen. Notieren Sie ihn sich daher jetzt.

Erstellen des Funktions-URL-Endpunkts

Erstellen Sie einen Endpunkt für Ihren Webhook mithilfe einer Lambda-Funktions-URL. Da Sie den Authentifizierungstyp NONE verwenden, um einen Endpunkt mit öffentlichem Zugriff zu erstellen, kann jeder, der über die URL verfügt, Ihre Funktion aufrufen. Weitere Informationen zum Steuern des Zugriffs auf Funktions-URLs finden Sie unter Kontrolle des Zugriffs auf Lambda-Funktions-URLs. Wenn Sie erweiterte Authentifizierungsoptionen für Ihren Webhook benötigen, sollten Sie die Verwendung von API Gateway in Betracht ziehen.

Erstellen des Funktions-URL-Endpunkts
  1. Wählen Sie auf der Registerkarte Konfiguration Ihrer Funktion die Option Funktions-URL aus.

  2. Wählen Sie Funktions-URL erstellen.

  3. Wählen Sie als Authentifizierungstyp die Option KEINEN aus.

  4. Wählen Sie Speichern.

Der Endpunkt für die Funktions-URL, die Sie gerade erstellt haben, wird im Bereich Funktions-URL angezeigt. Kopieren Sie den Endpunkt, um ihn später im Tutorial zu verwenden.

Testen der Funktion in der Konsole

Bevor Sie eine HTTP-Anfrage verwenden, um Ihre Funktion über den URL-Endpunkt aufzurufen, testen Sie sie in der Konsole, um sicherzustellen, dass Ihr Code wie erwartet funktioniert.

Um die Funktion in der Konsole zu überprüfen, berechnen Sie zunächst eine Webhook-Signatur unter Verwendung des zuvor im Tutorial generierten geheimen Schlüssels mit den folgenden Test-JSON-Nutzdaten:

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

Verwenden Sie eines der folgenden Python- oder Node.js-Codebeispiele, um die Webhook-Signatur mit Ihrem eigenen geheimen Schlüssel zu berechnen.

Python
Berechnen der Webhook-Signatur
  1. Speichern Sie den folgenden Code als Datei mit dem Namen calculate_signature.py. Ersetzen Sie den geheimen Webhook-Schlüssel im Code durch Ihren eigenen Wert.

    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)
  2. Berechnen Sie die Signatur, indem Sie den folgenden Befehl aus dem Verzeichnis ausführen, in dem Sie den Code gespeichert haben. Kopieren Sie die Signatur, die der Code ausgibt.

    python calculate_signature.py
Node.js
Berechnen der Webhook-Signatur
  1. Speichern Sie den folgenden Code als Datei mit dem Namen calculate_signature.mjs. Ersetzen Sie den geheimen Webhook-Schlüssel im Code durch Ihren eigenen Wert.

    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);
  2. Berechnen Sie die Signatur, indem Sie den folgenden Befehl aus dem Verzeichnis ausführen, in dem Sie den Code gespeichert haben. Kopieren Sie die Signatur, die der Code ausgibt.

    node calculate_signature.mjs

Sie können Ihren Funktionscode jetzt mit einer Test-HTTP-Anfrage in der Konsole testen.

Testen der Funktion in der Konsole
  1. Wählen Sie die Registerkarte Code für Ihre Funktion aus.

  2. Wählen Sie im Abschnitt TESTEREIGNISSE die Option Neues Testereignis erstellen aus.

  3. Geben Sie als Event name (Ereignisname) die Zeichenfolge myEvent ein.

  4. Ersetzen Sie das vorhandene JSON, indem Sie Folgendes kopieren und in den Bereich Ereignis-JSON einfügen. Ersetzen Sie die Webhook-Signatur durch den im vorherigen Schritt berechneten Wert.

    { "headers": { "Content-Type": "application/json", "x-webhook-signature": "2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a" }, "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}" }
  5. Wählen Sie Speichern.

  6. Wählen Sie Invoke aus.

    Die Ausgabe sollte folgendermaßen oder ähnlich aussehen:

    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

Testen der Funktion mit einer HTTP-Anfrage

Testen Sie Ihren Webhook-Endpunkt mit dem Befehlszeilentool curl.

Testen der Funktion mit HTTP-Anfragen
  1. Führen Sie in einem Terminal- oder Shell-Programm den folgenden curl-Befehl aus. Ersetzen Sie die URL durch den Wert für Ihren eigenen Funktions-URL-Endpunkt und ersetzen Sie die Webhook-Signatur durch die Signatur, die Sie mit Ihrem eigenen geheimen Schlüssel berechnet haben.

    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"}'

    Die Ausgabe sollte folgendermaßen aussehen:

    {"received": true}
  2. Überprüfen Sie die CloudWatch-Protokolle für Ihre Funktion, um sicherzustellen, dass die Nutzdaten korrekt analysiert wurde. Gehen Sie dazu wie folgt vor:

    1. Öffnen Sie in der Amazon-CloudWatch-Konsole die Seite Protokollgruppe.

    2. Wählen Sie die Protokollgruppe Ihrer Funktion (/aws/lambda/myLambdaWebhook).

    3. Wählen Sie den neuesten Protokoll-Stream.

      In den Protokollen Ihrer Funktion sollte eine Ausgabe ähnlich der folgenden zu sehen sein:

      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
  3. Überprüfen Sie, ob Ihr Code eine ungültige Signatur erkennt, indem Sie den folgenden curl-Befehl ausführen. Ersetzen Sie die URL durch Ihren eigenen Funktions-URL-Endpunkt.

    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"}'

    Die Ausgabe sollte folgendermaßen aussehen:

    {"error": "Invalid signature"}

Bereinigen Ihrer Ressourcen

Sie können jetzt die Ressourcen, die Sie für dieses Tutorial erstellt haben, löschen, es sei denn, Sie möchten sie behalten. Durch das Löschen von AWS-Ressourcen, die Sie nicht mehr verwenden, können Sie verhindern, dass unnötige Gebühren in Ihrem AWS-Konto-Konto anfallen.

So löschen Sie die Lambda-Funktion:
  1. Öffnen Sie die Seite Funktionen der Lambda-Konsole.

  2. Wählen Sie die Funktion aus, die Sie erstellt haben.

  3. Wählen Sie Actions, Delete.

  4. Geben Sie confirm in das Texteingabefeld ein und wählen Sie Delete (Löschen) aus.

Als Sie die Lambda-Funktion in der Konsole erstellt haben, hat Lambda auch eine Ausführungsrolle für Ihre Funktion erstellt.

So löschen Sie die Ausführungsrolle
  1. Öffnen Sie die Seite Roles (Rollen) in der IAM-Konsole.

  2. Wählen Sie die von Lambda erstellte Ausführungsrolle aus. Die Rolle weist das Benennungsformat myLambdaWebhook-role-<random string> auf.

  3. Wählen Sie Löschen aus.

  4. Geben Sie den Namen der Rolle in das Texteingabefeld ein und wählen Sie Delete (Löschen) aus.