0.13.17 : make the Stripe webhook say when it credits nothing
Un abonnement premium souscrit en test aboutissait chez Stripe sans qu'aucune commande ni aucun droit n'apparaisse en base — et sans la moindre trace côté serveur. - `metadata.userId` absent faisait sortir le handler en silence avec un 200 : c'est désormais journalisé en erreur, avec l'id de session Stripe - l'utilisateur est résolu une fois par `documentId` (ce que le front envoie) : la relation `user` d'une commande attend un id numérique, elle recevait un documentId - un utilisateur introuvable est journalisé au lieu d'échouer plus loin - les types d'événements ignorés sont tracés, pour distinguer « Stripe n'appelle pas » de « Stripe appelle sans checkout.session.completed » Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "harmony-back",
|
"name": "harmony-back",
|
||||||
"version": "0.13.16",
|
"version": "0.13.17",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "A Strapi application",
|
"description": "A Strapi application",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -42,15 +42,37 @@ export default factories.createCoreController(
|
|||||||
premium: 5,
|
premium: 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (userId) {
|
if (!userId) {
|
||||||
|
// Sans `userId` dans les métadonnées, l'ancien code sortait en
|
||||||
|
// silence avec un 200 : le paiement aboutissait chez Stripe sans
|
||||||
|
// qu'aucune commande ni aucun droit n'apparaisse, et sans trace.
|
||||||
|
strapi.log.error(
|
||||||
|
`❌ Webhook ${event.type} sans metadata.userId (session ${session.id}) : aucun droit crédité`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
|
// Les métadonnées portent un `documentId` (cf. le front,
|
||||||
|
// UserSubscriptionTab). La relation `user` d'une commande attend
|
||||||
|
// un id numérique : on résout l'utilisateur une fois pour les deux.
|
||||||
|
const user = await strapi.db
|
||||||
|
.query("plugin::users-permissions.user")
|
||||||
|
.findOne({ where: { documentId: userId } });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
strapi.log.error(
|
||||||
|
`❌ Webhook : aucun utilisateur pour documentId ${userId} (session ${session.id})`,
|
||||||
|
);
|
||||||
|
ctx.send({ received: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Création de la commande
|
// Création de la commande
|
||||||
await strapi.documents("api::order.order").create({
|
await strapi.documents("api::order.order").create({
|
||||||
data: {
|
data: {
|
||||||
stripeId: session.id,
|
stripeId: session.id,
|
||||||
amount: session.amount_total ? session.amount_total / 100 : 0,
|
amount: session.amount_total ? session.amount_total / 100 : 0,
|
||||||
planType: planType,
|
planType: planType,
|
||||||
user: userId,
|
user: user.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -74,6 +96,10 @@ export default factories.createCoreController(
|
|||||||
// On répond quand même 200 à Stripe pour éviter les retries infinis
|
// On répond quand même 200 à Stripe pour éviter les retries infinis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Permet de distinguer « Stripe n'appelle pas le webhook » de
|
||||||
|
// « Stripe appelle mais n'envoie pas checkout.session.completed ».
|
||||||
|
strapi.log.info(`ℹ️ Événement ${event.type} ignoré`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// INDISPENSABLE : Répondre 200 OK à Stripe pour TOUS les événements
|
// INDISPENSABLE : Répondre 200 OK à Stripe pour TOUS les événements
|
||||||
|
|||||||
Reference in New Issue
Block a user