Tous les articles
Une séquence d’événements de cycle de vie de facturation simulés passant par un tunnel sécurisé vers un gestionnaire de webhook Paddle local.
Paddlewebhook simulatorbillinglocal testing

Utilisez le simulateur Paddle Webhook sur Localhost

Pour utiliser le simulateur de webhook Paddle avec localhost, exposez votre gestionnaire local via un tunnel HTTPS, créez une destination de notification sandbox qui pointe vers l'URL publique, puis exécutez une simulation d'événement unique ou de cycle de vie sur cette destination. Paddle envoie une demande réaliste avec un Paddle-Signature en-tête, afin que le même chemin de vérification du corps brut puisse s'exécuter localement et en production.

Pourquoi le simulateur de Paddle est plus qu'un exemple de charge utile

Un appareil JSON copié teste votre instruction switch. Le simulateur de Paddle teste ensemble la destination réseau, les en-têtes du fournisseur, le secret de signature, l'état de la réponse et le schéma d'événement. Le fonctionnaire Présentation du simulateur de webhook prend en charge des événements et des scénarios uniques réutilisables. Les événements uniques ciblent un type d'événement et peuvent être personnalisés après une exécution. Les scénarios envoient une séquence prédéfinie pour un cycle de vie tel que la création ou le renouvellement d'un abonnement.

La configuration du scénario peut remplir les charges utiles avec des entités Paddle existantes et faire varier le flux. Chaque exécution produit des enregistrements d'événements d'exécution de simulation dans lesquels vous pouvez inspecter la charge utile, la demande sortante et la réponse du point de terminaison. Cela rend le simulateur utile pour déboguer les transitions d’état, et pas seulement pour prouver qu’un itinéraire est en ligne.

Connecter un point de terminaison local au bac à sable Paddle

  1. Démarrez votre candidature, par exemple sur http://localhost:3000.
  2. Ajoutez une route POST telle que /api/webhooks/paddle.
  3. Courir npx portpreview 3000 et copiez l'adresse HTTPS.
  4. Dans Paddle sandbox, créez une destination de notification en utilisant https://your-subdomain.portpreview.dev/api/webhooks/paddle.
  5. Révélez et copiez le secret du point de terminaison de cette destination dans PADDLE_WEBHOOK_SECRET. Ce n'est pas votre clé API.
  6. Ouvrez Outils de développement → Simulations, choisissez un seul événement ou scénario, sélectionnez la destination, configurez-la et exécutez-la.
  7. Comparez la réponse de simulation de Paddle avec vos journaux locaux et le reçu de webhook persistant.

Utilisez les ressources et les informations d'identification du bac à sable partout. Mélanger un secret de destination en direct avec une demande de simulateur de bac à sable garantit un échec de signature même si les deux chaînes semblent plausibles.

Vérifiez le Paddle-Signature en-tête

Paddle signe chaque webhook avec le secret appartenant à la destination de la notification. L'en-tête contient des composants, notamment un horodatage Unix identifié par ts et une ou plusieurs signatures identifiées par h1. Paddle peut ajouter des versions de signature, alors analysez l'en-tête plutôt que de supposer qu'il contient un seul hachage.

La charge utile signée est l'horodatage, deux points et le corps de la demande intact. Paddle applique HMAC-SHA256 avec le secret du point de terminaison. C'est documentation de vérification de signature recommande un SDK officiel lorsqu'il est disponible et documente l'algorithme manuel. Appliquez toujours la tolérance d'horodatage du SDK ou une tolérance explicite dans votre vérificateur pour limiter les attaques par réexécution.

Préférez le SDK officiel dans Node

import express from 'express';
import { Environment, Paddle } from '@paddle/paddle-node-sdk';

const app = express();
const paddle = new Paddle(process.env.PADDLE_API_KEY, {
  environment: Environment.sandbox,
});

app.post(
  '/api/webhooks/paddle',
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    const signature = req.header('paddle-signature') ?? '';
    const rawBody = req.body.toString('utf8');

    try {
      const event = await paddle.webhooks.unmarshal(
        rawBody,
        process.env.PADDLE_WEBHOOK_SECRET,
        signature,
      );

      await acceptOnce(event.eventId, event);
      return res.status(200).send('accepted');
    } catch (error) {
      return res.status(400).send('invalid webhook');
    }
  },
);

app.listen(3000);

Monter express.raw() avant toute mondialisation express.json() middleware pour cette route. Dans un framework de style Fetch tel que Next.js App Router, utilisez await request.text() une fois et transmettez cette chaîne exacte au SDK. Le fonctionnaire démarrage rapide du webhook démontre cette exigence corporelle brute.

Ce que doit faire la vérification manuelle

  1. Lisez le corps brut sans normalisation JSON.
  2. Analysez chaque composant d'en-tête séparé par un point-virgule et collectez les éléments pris en charge h1 valeurs.
  3. Rejeter un élément manquant, mal formé ou excessivement ancien ts.
  4. Calculer HMAC_SHA256(secret, ts + ':' + rawBody).
  5. Comparez le résumé attendu avec les signatures candidates à l'aide d'une comparaison sécurisée dans le temps.
  6. Seulement après un match, analysez JSON et envoyez-le sur event_type.

L’acceptation de toute signature valide prise en charge est importante lors de la rotation secrète, lorsque plusieurs signatures peuvent être présentes. Ne divisez pas l'en-tête et prenez aveuglément le deuxième élément. Ne consignez pas le secret du point de terminaison et ne complétez pas la charge utile du client lors du diagnostic d'une incompatibilité.

Concevoir des simulations autour des invariants de facturation

Création d'abonnement

Exécutez un scénario de création d'abonnement et vérifiez que votre base de données peut recevoir des événements de transaction et d'abonnement associés sans assumer un seul ordre d'arrivée sur le réseau. Stockez les ID d’entité Paddle et mettez à jour les enregistrements de manière idempotente. La demande doit accorder exactement un droit, même si la demande est renvoyée.

Renouvellement et échec de paiement

Exercez les chemins de renouvellement, de retard et de récupération réussis disponibles dans la configuration de votre scénario. Séparez le statut de facturation de la politique d'accès au produit : votre délai de grâce peut intentionnellement maintenir l'accès actif pendant que Paddle signale un problème de collecte.

Annulation et modifications programmées

Distinguer un abonnement dont l'annulation est programmée de celui qui a atteint son annulation effective. Préserver next_billed_at, les données de modification planifiée et le statut du fournisseur plutôt que de réduire le cycle de vie en is_active.

Mises à jour des entités

Simulez les mises à jour de produits, de prix, de clients et d'abonnements consommées par votre cache. Un gestionnaire doit ignorer les types d'événements inconnus en toute sécurité et les reconnaître si la signature est valide ; Les futurs ajouts de Paddle ne devraient pas se transformer en une boucle d’échec sans fin.

Idempotence et ordre à chaque passage

Utilisez l'ID stable de l'événement webhook comme clé unique dans une table de réception. En une seule transaction, insérez le reçu, appliquez le changement d'état et mettez les effets secondaires en file d'attente. En cas de conflit d'insertion, renvoyez le succès sans répéter le travail. Ne effectuez pas de déduplication uniquement par ID d'entité, car de nombreuses mises à jour légitimes peuvent cibler un seul abonnement.

Les événements peuvent arriver dans le désordre. Comparez l'heure d'occurrence de l'événement ou récupérez la dernière entité Paddle avant d'appliquer une transition destructrice. Stockez l’état et l’horodatage du fournisseur et rejetez une ancienne mise à jour qui écraserait une plus récente. Les scénarios de simulation sont idéaux pour tester ces hypothèses car ils produisent des séquences connectées plutôt que des montages isolés.

Résoudre les échecs du simulateur vers l'hôte local

La destination renvoie 404 ou 405

Vérifiez que l'URL publique inclut la route complète et que la route exporte le POST. Un navigateur GET n'est pas un test valide d'un webhook POST uniquement. Utiliser curl -X POST par rapport à l'URL publique pour distinguer le routage du tunnel de la configuration Paddle.

La destination renvoie 400

Inspecter si Paddle-Signature arrivé et confirmez que le secret du point de terminaison appartient à la destination de notification sélectionnée. Assurez-vous qu’aucun analyseur de corps, enregistreur de requêtes ou middleware n’a consommé ou reformaté le corps. Le simulateur envoie des signatures vérifiables, comme indiqué dans Guide de simulation de Paddle.

La destination renvoie 500 ou expire

Persistez rapidement et déplacez les e-mails, les appels d'approvisionnement et les appels d'API sortants vers une file d'attente. Retour 2xx après acceptation durable. Lancer un type d'événement inconnu est une cause fréquente d'échecs inutiles ; utilisez une branche par défaut qui l'enregistre et le reconnaît.

Le scénario utilise des données inattendues

Vérifiez si la simulation utilise des valeurs générées automatiquement ou si elle est remplie de véritables entités sandbox. Inspectez les options de scénario configurées et la charge utile de l'événement d'exécution plutôt que de supposer qu'elle reflète une exécution précédente.

Liste de contrôle de sécurité avant la production

  • Conservez les clés API et les secrets de destination des notifications séparés et réservés au serveur.
  • Vérifiez le corps brut, la signature d'en-tête et l'horodatage avant le traitement.
  • Utilisez une comparaison sécurisée ou un vérificateur SDK officiel.
  • Dédupliquez les ID d’événement et gérez les mises à jour dans le désordre.
  • Appliquez des limites de corps, un routage POST uniquement, une journalisation rédigée et des contrôles de débit.
  • Utilisez des destinations sandbox et en direct distinctes, puis répétez les simulations et les flux sandbox réels avant de changer l'URL de production.

Le simulateur prouve votre intégration sous des séquences de cycle de vie contrôlées ; une véritable vérification sandbox prouve en outre les relations de paiement entre les entités. Utilisez les deux, puis consultez le général guide de signature de webhooks et guide d'idempotence avant le lancement.

Questions fréquentes

Le simulateur de webhook de Paddle peut-il envoyer des événements à localhost ?
Oui, via un tunnel HTTPS public. Configurez une destination de notification sandbox avec l'URL et l'itinéraire du tunnel, puis sélectionnez cette destination lors de l'exécution de la simulation.
Les signatures des webhooks du simulateur Paddle sont-elles réelles ?
Oui. Paddle indique que le simulateur envoie une demande de réplique de webhook incluant Paddle-Signature. Vérifiez-le avec le secret de la destination de notification sélectionnée, tout comme un webhook normal.
Quelle est la différence entre une simulation Paddle mono-événement et un scénario ?
Une simulation à événement unique envoie un événement personnalisable. Un scénario envoie une séquence prédéfinie représentant un cycle de vie tel que la création ou le renouvellement d'un abonnement et peut utiliser des entités sandbox existantes.
Pourquoi la vérification de la signature Paddle échoue-t-elle localement ?
Les causes habituelles sont l'utilisation d'un mauvais secret de destination, l'analyse du corps avant la vérification, l'omission de Paddle-Signature, le mélange du bac à sable et de la configuration en direct, ou la transmission d'un horodatage obsolète à un vérificateur avec une tolérance de relecture.