Commerce : vendre dans ChatGPT
Mis à jour le 29 juillet 2026
Intégrer les paiements dans votre application
Le pilier Commerce permet de monétiser votre application sans jamais sortir l’utilisateur de ChatGPT. La friction disparaît : plus de nouvel onglet, plus de formulaire de carte à ressaisir, plus de compte à créer sur un site inconnu. Cette continuité explique l’essentiel du gain de conversion, et elle vous impose en retour une exigence de clarté — dans une conversation, l’utilisateur doit toujours savoir ce qu’il achète et à quel prix.
Configurer le Commerce
Avant de vendre quoi que ce soit, activez le pilier dans le manifest et raccordez votre compte vendeur. Trois éléments doivent être en place au préalable : un compte Stripe Connect vérifié, puisque OpenAI utilise Stripe en backend ; les informations fiscales de votre entreprise renseignées ; et l’activation du module Commerce dans le portail développeur. Tant que la vérification Stripe n’est pas terminée, vos achats de test échoueront sans message très explicite — vérifiez ce point en premier si rien ne fonctionne.
{
"name": "Mon App Commerce",
"slug": "mon-app-commerce",
"permissions": ["actions", "widgets", "commerce"],
"commerce": {
"stripeAccountId": "${STRIPE_CONNECT_ID}",
"currency": "EUR",
"taxHandling": "inclusive"
}
}
Définir des produits
Vos produits se déclarent dans le code et se synchronisent avec le Store. Deux types couvrent la quasi-totalité des besoins, illustrés ci-dessous : l’abonnement mensuel et l’achat unique. Notez que les montants s’expriment en centimes — 990 signifie 9,90 €, et confondre les deux est l’erreur classique du premier déploiement. Le champ trialDays déclenche la période d’essai sans que vous ayez à gérer vous-même la bascule vers le paiement.
import { defineProduct } from "@openai/apps-sdk";
export const premiumPlan = defineProduct({
id: "premium-monthly",
name: "Premium Mensuel",
description: "Accès illimité à toutes les fonctionnalités avancées",
type: "subscription",
pricing: {
amount: 990, // en centimes
currency: "EUR",
interval: "month",
},
features: [
"Analyses illimitées",
"Export PDF et CSV",
"Support prioritaire",
"Accès API",
],
trialDays: 7,
});
export const singleReport = defineProduct({
id: "single-report",
name: "Rapport Détaillé",
description: "Analyse complète avec recommandations personnalisées",
type: "one_time",
pricing: {
amount: 1490,
currency: "EUR",
},
});
Le flux d’achat
Le SDK prend en charge le tunnel de paiement de bout en bout. Votre action garde toutefois une responsabilité que rien ne remplace : vérifier d’abord si l’utilisateur a déjà payé. Sans ce contrôle, vous facturez deux fois un client qui redemande son rapport trois jours plus tard — et ce genre d’incident vous coûte un avis négatif sur le Store. L’action ci-dessous contrôle l’achat existant, crée le checkout, puis renvoie le widget de paiement.
import { commerceFlow } from "@openai/apps-sdk";
app.action("purchaseReport", {
description: "Lance l'achat d'un rapport détaillé pour l'utilisateur",
parameters: {
reportType: { type: "string", required: true },
},
handler: async ({ reportType }, context) => {
// 1. Vérifier si déjà acheté
const existing = await checkPurchase(context.user.id, reportType);
if (existing) {
return { alreadyPurchased: true, reportUrl: existing.url };
}
// 2. Déclencher le flux de paiement
const checkout = await commerceFlow.createCheckout({
productId: "single-report",
userId: context.user.id,
metadata: { reportType },
});
// 3. Retourner le widget de paiement
return {
_widget: "checkoutWidget",
checkoutId: checkout.id,
product: "Rapport Détaillé",
amount: "14,90 €",
};
},
});
Widget de paiement intégré
Le composant de paiement est fourni par le SDK et sécurisé nativement : les coordonnées bancaires ne transitent jamais par votre code, ce qui vous épargne l’essentiel des contraintes de conformité. Vous déclarez les moyens acceptés — carte, Apple Pay, Google Pay — ainsi que les actions à appeler en cas de succès ou d’abandon. Traitez le cas onCancel avec autant de soin que le succès : un utilisateur qui renonce doit se retrouver dans un état propre, pas devant un widget figé.
export const checkoutWidget = defineWidget({
name: "checkoutWidget",
render: (data) => ({
type: "card",
title: "Finaliser votre achat",
content: [
{ type: "text", value: data.product, style: "heading" },
{ type: "metric", label: "Total", value: data.amount },
{
type: "payment",
checkoutId: data.checkoutId,
methods: ["card", "apple_pay", "google_pay"],
onSuccess: "paymentConfirmed",
onCancel: "paymentCancelled",
},
],
}),
});
Gérer les abonnements
Un abonnement vit longtemps et change d’état sans que l’utilisateur revienne vous voir. Prévoyez donc une action de gestion qui répond dans les deux cas : s’il n’y a pas d’abonnement, on présente la grille tarifaire ; s’il y en a un, on affiche son statut, son échéance et l’éventuelle résiliation programmée. Cacher la résiliation derrière un support par e-mail est le meilleur moyen de collectionner les demandes de remboursement.
app.action("manageSubscription", {
description: "Affiche le statut et les options de gestion de l'abonnement",
handler: async (_, context) => {
const sub = await commerceFlow.getSubscription(context.user.id);
if (!sub) {
return { status: "none", _widget: "pricingTable" };
}
return {
_widget: "subscriptionManager",
status: sub.status,
plan: sub.productId,
currentPeriodEnd: sub.currentPeriodEnd,
cancelAtPeriodEnd: sub.cancelAtPeriodEnd,
};
},
});
Webhooks de paiement
Votre serveur reçoit une notification pour chaque événement de paiement, et c’est là que se joue l’ouverture ou la fermeture des droits. Un renouvellement prolonge l’accès, une résiliation programme sa révocation à la fin de la période payée, un remboursement la déclenche immédiatement. Sans ce traitement, un client remboursé continue d’utiliser votre service, et un abonné qui vient de renouveler se voit refuser l’accès.
app.webhook("commerce", async (event) => {
switch (event.type) {
case "checkout.completed":
await activateAccess(event.userId, event.productId);
break;
case "subscription.renewed":
await extendAccess(event.userId, event.productId);
break;
case "subscription.cancelled":
await scheduleAccessRevocation(event.userId, event.endDate);
break;
case "refund.processed":
await revokeAccess(event.userId, event.productId);
break;
}
});
Vérifier les droits d’accès
Chaque action premium doit contrôler l’habilitation avant de travailler. Le point remarquable de l’exemple suivant tient à sa manière d’échouer : plutôt que de renvoyer une erreur, il affiche un widget d’incitation à l’abonnement avec l’identifiant du produit concerné. Le refus devient une proposition commerciale, au moment précis où l’utilisateur exprime son besoin.
app.action("generateAdvancedReport", {
description: "Génère un rapport avancé (fonctionnalité Premium)",
parameters: {
topic: { type: "string", required: true },
},
handler: async ({ topic }, context) => {
// Vérifier l'abonnement
const hasAccess = await commerceFlow.checkEntitlement(
context.user.id,
"premium-monthly"
);
if (!hasAccess) {
return {
_widget: "upgradePrompt",
message: "Cette fonctionnalité nécessite un abonnement Premium",
productId: "premium-monthly",
};
}
// Générer le rapport
const report = await generateReport(topic);
return { _widget: "reportView", ...report };
},
});
Commission OpenAI
OpenAI prélève une commission sur chaque transaction, selon le barème suivant.
| Type | Commission OpenAI | Vous recevez |
|---|---|---|
| Achat ponctuel | 30 % | 70 % |
| Abonnement (année 1) | 30 % | 70 % |
| Abonnement (année 2+) | 15 % | 85 % |
La dernière ligne oriente toute votre stratégie de prix : un abonné fidèle vaut nettement plus qu’un acheteur ponctuel, puisque votre marge passe de 70 à 85 % dès la deuxième année. Intégrez ce basculement dans vos calculs de rentabilité avant de fixer vos tarifs.
Points clés à retenir
- Le Commerce SDK gère paiements ponctuels, abonnements et essais gratuits
- Stripe Connect est utilisé en backend — configurez votre compte vendeur
- Le widget de paiement natif gère carte, Apple Pay et Google Pay
- Les webhooks vous notifient de chaque événement transactionnel
- Vérifiez les droits d’accès dans chaque action premium avec
checkEntitlement - OpenAI prélève 30 % la première année, 15 % ensuite