Alle Artikel
Abonnement- und Lizenz-Webhook-Ereignisse fließen durch einen HTTPS-Tunnel in einen verifizierten lokalen Entwicklungs-Handler.
Lemon Squeezywebhookssubscriptionslocal testing

Lemon-Squeezy-Webhooks auf localhost testen

Um Lemon Squeezy Webhooks auf localhost zu testen, starten Sie Ihre App, machen Sie ihre Webhook-Route über einen öffentlichen HTTPS-Tunnel zugänglich, erstellen Sie einen Testmodus-Webhook in Einstellungen → Webhooks und überprüfen Sie den rohen Anforderungskörper gegen den X-Signature Kopfzeile. Verwenden Sie eine Testkasse für echte Bestelldaten und die Abo-Simulationssteuerungen von Lemon Squeezy für Lebenszyklusereignisse, auf die nur schwer zu warten ist.

Wie ein korrektes lokales Setup aussieht

Lemon Squeezy sendet ein HTTP POST von seiner Infrastruktur, sodass es nicht erreichen kann localhost auf Ihrem Computer. Der Tunnel beendet öffentliches TLS und leitet die unveränderte Methode, den Body und die Header an eine lokale Route wie http://localhost:3000/api/webhooks/lemonsqueezy.

Ein vollständiger Test hat vier Teile: Lemon Squeezy Testmodus, eine öffentliche Callback-URL, dasselbe Signaturgeheimnis im Dashboard und in der lokalen Umgebung, und einen Handler, der überprüft, bevor er den Abonnement- oder Lizenzstatus ändert. Dies ist nützlicher, als kopiertes JSON zu posten mit curl, weil eine echte Lieferung sowohl die Zustellung als auch die vom Anbieter erzeugte Unterschrift testet.

Erstellen Sie das Webhook und senden Sie ein Testereignis

  1. Führen Sie Ihre App auf Port 3000 aus und überprüfen Sie, ob die Route akzeptiert POST.
  2. Starte den Tunnel mit npx portpreview 3000.
  3. Schalten Sie das Lemon Squeezy-Dashboard in den Testmodus.
  4. Öffnen Sie Einstellungen → Webhooks und hinzufügen https://your-subdomain.portpreview.dev/api/webhooks/lemonsqueezy.
  5. Erzeugen Sie ein starkes zufälliges Signaturgeheimnis und speichern Sie es als LEMONSQUEEZY_WEBHOOK_SECRET, und wählen Sie nur die Ereignisse aus, die Ihre Anwendung verarbeitet.
  6. Erstellen Sie einen Testkauf oder verwenden Sie die verfügbare Testmodus-Abonnementsimulation, und prüfen Sie dann das Lieferprotokoll sowie Ihre lokale Antwort.

Der Offizielle Lemon Squeezy Webhook-Dokumentation ermöglicht es Ihnen, kürzlich empfangene Payloads zu überprüfen und aufgezeichnete Webhooks von der Einstellungsseite erneut zu senden. Ein erneutes Senden ist für Regressionstests wertvoll, aber Ihre Anwendung muss es als Duplikat und nicht als zweites Geschäftereignis behandeln.

Überprüfen X-Signature vor dem Parsen von JSON

Lemon Squeezy berechnet einen HMAC-SHA256-Digest über die Anfrage-Nutzlast unter Verwendung des Signierungsgeheimnisses und sendet den hexadezimalen Digest in X-Signature. Berechnen Sie die Prüfsumme über genau die rohen Körperbytes und vergleichen Sie Puffer gleicher Länge mit einer Konstantzeit-Funktion. Die Haupt Dokumentation der Anforderungsunterzeichnung beinhaltet Beispiele für Node, PHP, Python und Ruby.

// app/api/webhooks/lemonsqueezy/route.ts
import crypto from 'node:crypto';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const secret = process.env.LEMONSQUEEZY_WEBHOOK_SECRET;
  if (!secret) return new NextResponse('server misconfigured', { status: 500 });

  const rawBody = await request.text();
  const suppliedHex = request.headers.get('x-signature') ?? '';

  if (!/^[0-9a-f]{64}$/i.test(suppliedHex)) {
    return new NextResponse('invalid signature', { status: 401 });
  }

  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest();
  const supplied = Buffer.from(suppliedHex, 'hex');

  if (supplied.length !== expected.length ||
      !crypto.timingSafeEqual(supplied, expected)) {
    return new NextResponse('invalid signature', { status: 401 });
  }

  const event = JSON.parse(rawBody);
  await acceptEvent(event);
  return NextResponse.json({ received: true });
}

Nicht anrufen request.json() Zuerst. Das erneute Serialisieren des resultierenden Objekts kann unscheinbar aussehende Bytes ändern und die HMAC zerstören. Die Längenprüfung ist ebenfalls wesentlich, weil Node's timingSafeEqual wirft, wenn die Pufferlängen unterschiedlich sind. Offiziell von Lemon Squeezy Next.js Webhook-Anleitung folgt der gleichen Rohkörpersequenz.

Verstehen Sie die Nutzlast, bevor Sie Ihre Datenbank aktualisieren

Der Körper ist ein JSON:API-Ressourcenobjekt. meta.event_name identifiziert das Ereignis, meta.custom_data überträgt durch den Checkout weitergegebene Daten, und data enthält die Bestell-, Abonnement- oder Lizenzschlüssel-Ressource. Lemon Squeezy sendet auch X-Event-Name; Behandeln Sie den signierten Inhalt als die maßgebliche Eingabe und verwenden Sie den Header für Routing-Diagnosen.

Bestellungen und Kundenidentität

Für order_created, ordnen Sie den Kauf einem internen Benutzer mithilfe einer servergenerierten Kennung in den benutzerdefinierten Checkout-Daten zu. Vertrauen Sie einer vom Client bereitgestellten Benutzer-ID nicht, ohne die Eigentümerschaft zu überprüfen. Speichern Sie die Ressourcen-ID und Varianten-ID von Lemon Squeezy, damit spätere Abonnement- oder Rückerstattungsereignisse abgeglichen werden können.

Abonnements sind eine Zustandsmaschine

Griff subscription_created, subscription_updated, subscription_cancelled, subscription_resumed, und subscription_expired als unterschiedliche Übergänge. Stornierung kann bedeuten, dass der Zugang bis zum Ende eines Abrechnungszeitraums gültig bleibt; Ablauf ist das stärkere Signal dafür, dass das Abonnement beendet ist. Modellieren Sie Daten und Status, anstatt einen booleschen Wert umzuschalten.

Zahlungsausfälle und Wiederherstellung

Test fehlgeschlagene und wiederhergestellte Verlängerungsabläufe, bei denen der Testmodus sie unterstützt. Eine fehlgeschlagene Zahlung sollte den Zugriff nicht unbedingt sofort widerrufen; wenden Sie die in Ihrer Produktpolitik definierte Nachfrist an und lassen Sie spätere Zahlungen oder Abonnementereignisse das Konto auf den neuesten Anbieterstatus bringen.

Wiederholungen erfordern idempotente Verarbeitung

Laut Lemon Squeezy's Webhook-Anfrage-Referenz, ein 200 Antwortmarkierungen erfassen als erfolgreich. Andere Status werden bis zu drei weitere Male mit exponentiellen Verzögerungen erneut versucht, die ungefähr 5, 25 und 125 Sekunden betragen. Erneute Sendungen auf dem Dashboard schaffen einen weiteren Grund, dass dasselbe logische Ereignis mehr als einmal eintreffen kann.

Erstellen Sie einen Idempotenzschlüssel aus stabilen signierten Nutzlastfeldern. Ein praktischer Ansatz ist eine eindeutige Datenbankzeile für die Ressourcen-ID des Webhooks, den Ereignisnamen und den Ereigniszeitstempel oder ein Hash des rohen signierten Inhalts, wenn keine eigene Ereignis-ID vorhanden ist. Fügen Sie dieses Receipt ein und aktualisieren Sie den Anwendungszustand in einer Transaktion. Zurückgeben 200 für ein zuvor abgeschlossenes Duplikat.

BEGIN;
INSERT INTO webhook_receipts (fingerprint, received_at)
VALUES ($1, now())
ON CONFLICT DO NOTHING;
-- Continue only if one row was inserted.
UPDATE subscriptions SET provider_status = $2 WHERE provider_id = $3;
COMMIT;

Machen Sie die E-Mail-Zustellung oder einen langsamen Drittanbieter-API-Aufruf nicht zum Teil des Bestätigungspfads. Speichern Sie einen Auftrag in derselben Transaktion, antworten Sie und lassen Sie einen Worker Nebenwirkungen behandeln. Das weitere Webhook-Wiederholungs- und Idempotenz-Leitfaden deckt dieses Muster ab.

Fehlerbehebung bei Lemon Squeezy Webhook-Localhost-Tests

Keine Anfrage erreicht die App

Überprüfen Sie, ob der Tunnel noch läuft, dass der Callback den Routen-Suffix enthält und Ihr Framework einen POST-Handler an genau diesem Pfad hat. Rufen Sie selbst den öffentlichen Endpunkt auf. Ein Tunnel-502 weist auf den lokalen Port hin; ein Framework-404 deutet auf die Platzierung der Route hin.

Jede Unterschrift ist ungültig

Bestätigen Sie, dass Testmodus und Live-Modus nicht unterschiedliche Webhook-Datensätze oder Geheimnisse verwenden. Lesen Sie den Body einmal als Text oder Bytes, schneiden Sie weder den Body noch das Geheimnis ab und stellen Sie sicher, dass die globale JSON-Middleware nicht zuerst ausgeführt wird. Prüfen Sie, ob X-Signature angekommen, aber drucken Sie niemals das Signaturgeheimnis.

Die Lieferung versucht es immer wieder

Lemon Squeezy erwartet 200, keine Weiterleitung auf eine Anmeldeseite. Schließe den Webhook-Pfad von CSRF- und Benutzersitzungs-Middleware aus, während die Signaturüberprüfung beibehalten wird. Fange Datenbankfehler ab, halte die Arbeit kurz und stelle sicher, dass auf jedem behandelten Ereigniszweig tatsächlich eine Erfolgsantwort zurückgegeben wird.

Abonnementsimulation ist nicht verfügbar

Die Simulationssteuerung erfordert geeignete Testmodus-Abonnementdaten. Einige Zahlungssimulationen benötigen Verlaufsdaten für die Erneuerung. Erstellen Sie zunächst das erforderliche Testabonnement oder den Testkauf und verwenden Sie dann das im Lemon Squeezy beschriebene Abonnementaktionsmenü. Webhook-Entwicklerhandbuch.

Sicherheits- und Go-Live-Checkliste

  • Generieren Sie ein zufälliges Signaturgeheimnis, speichern Sie es in der Umgebungs-Konfiguration und wechseln Sie es, wenn es offengelegt wird.
  • Überprüfen Sie HMAC über den Rohinhalt, bevor Sie JSON parsen, Datenbankeinträge vornehmen, Lizenzen erstellen oder Zugriffsänderungen vornehmen.
  • Verwenden Sie einen zeitlich sicheren Vergleich und lehnen Sie fehlende oder fehlerhafte Signaturen ab.
  • Halten Sie Testmodus- und Live-Webhook-Geheimnisse und -Aufzeichnungen getrennt.
  • Erlaube nur POST, setze eine vernünftige Größenbegrenzung für den Inhalt durch, rate-limit für ungültige Anfragen und schwärze Kundendaten in den Protokollen.
  • Testen Sie Duplikate, nicht in der richtigen Reihenfolge auftretende Lebenszyklusereignisse, Datenbankausfälle und Timeout-Wiederherstellung, bevor Sie den Tunnel durch Ihre Produktions-URL ersetzen.

Ein erfolgreicher Checkout auf dem Happy Path beweist nur, dass ein Ereignis angekommen ist. Eine produktionsbereite Integration beweist Signaturablehnung, Sicherheit gegen Duplikate, Lebenszyklus-Konvergenz und Wiederherstellung nach einer Nicht-200-Antwort. Für die zugrunde liegenden kryptografischen Fallstricke siehe die Anleitung zur Unterschriftsprüfung.

Häufig gestellte Fragen

Wie teste ich Lemon Squeezy Webhooks auf localhost?
Machen Sie Ihre lokale Webhook-Route mit einem HTTPS-Tunnel zugänglich, erstellen Sie einen Webhook, während das Dashboard im Testmodus ist, verwenden Sie lokal dasselbe Signatur-Geheimnis und lösen Sie eine Testkasse oder eine unterstützte Abonnementsimulation aus.
Wie wird eine Lemon Squeezy Webhook-Signatur überprüft?
Berechnen Sie einen HMAC-SHA256-Digest über den genauen rohen Anfragekörper mit Ihrem Signaturgeheimnis, dekodieren Sie den hexadezimalen X-Signature-Wert und vergleichen Sie gleich lange Puffer mit einer zeitlich sicheren Funktion.
Versucht Lemon Squeezy fehlgeschlagene Webhooks erneut?
Ja. In der Dokumentation heißt es, dass Antworten, die nicht 200 sind, bis zu drei zusätzliche Male mit exponentiellem Backoff erneut versucht werden, ungefähr nach 5, 25 und 125 Sekunden.
Kann ich die Verlängerungen von Lemon Squeezy-Abonnements im Testmodus simulieren?
Der Testmodus bietet Simulationsaktionen für unterstützte Abonnementereignisse. Einige zahlungsbezogene Simulationen erfordern ein bestehendes Testabonnement und Verlängerungsdaten, daher erstellen Sie zunächst den notwendigen Testzustand.