# Mettre à jour dynamiquement les postes Mettez à jour les postes en réponse aux modifications apportées lors du paiement. # Page entièrement hébergée > This is a Page entièrement hébergée for when payment-ui is stripe-hosted. View the full page at https://docs.stripe.com/payments/checkout/dynamically-update-line-items?payment-ui=stripe-hosted. Ajoutez, supprimez ou mettez à jour dynamiquement les postes inclus dans une [Session Checkout](https://docs.stripe.com/api/paiement/sessions/object.md). Cela vous permet de : - **Vérifier l’inventaire** : effectuez une vérification de vos stocks et réservez des articles lorsque les clients tentent de modifier des quantités d’articles. - **Ajout de nouveaux produits** : ajoutez un produit gratuit si le total de la commande dépasse un certain montant. - **Mise à jour des frais de livraison** : Si le total de la commande change, mettez à jour les frais de livraison en combinant la méthode décrite dans ce guide avec celle indiquée dans la rubrique [Personnalisation des options de livraison au cours du paiement](https://docs.stripe.com/payments/checkout/custom-shipping-options.md). - **Mise à jour des taux de taxe** : si vous n’utilisez pas [Stripe Tax](https://docs.stripe.com/tax/checkout.md), vous pouvez mettre à jour de manière dynamique les [taux de taxe](https://docs.stripe.com/billing/taxes/collect-taxes.md?tax-calculation=tax-rates#adding-tax-rates-to-checkout) appliqués aux postes en fonction de l’adresse de livraison saisie. Les mises à jour dynamiques ne sont pas prises en charge pour les pages hébergées. Vous pouvez utiliser cette fonctionnalité avec [Elements avec l’API Checkout Sessions](https://docs.stripe.com/payments/advanced/dynamically-update-line-items.md). # Page entièrement intégrée > This is a Page entièrement intégrée for when payment-ui is embedded-page. View the full page at https://docs.stripe.com/payments/checkout/dynamically-update-line-items?payment-ui=embedded-page. Ajoutez, supprimez ou mettez à jour dynamiquement les postes inclus dans une [Session Checkout](https://docs.stripe.com/api/paiement/sessions/object.md). Cela vous permet de : - **Vérifier l’inventaire** : effectuez une vérification de vos stocks et réservez des articles lorsque les clients tentent de modifier des quantités d’articles. - **Ajout de nouveaux produits** : ajoutez un produit gratuit si le total de la commande dépasse un certain montant. - **Mise à jour des frais de livraison** : Si le total de la commande change, mettez à jour les frais de livraison en combinant la méthode décrite dans ce guide avec celle indiquée dans la rubrique [Personnalisation des options de livraison au cours du paiement](https://docs.stripe.com/payments/checkout/custom-shipping-options.md). - **Mise à jour des taux de taxe** : si vous n’utilisez pas [Stripe Tax](https://docs.stripe.com/tax/checkout.md), vous pouvez mettre à jour de manière dynamique les [taux de taxe](https://docs.stripe.com/billing/taxes/collect-taxes.md?tax-calculation=tax-rates#adding-tax-rates-to-checkout) appliqués aux postes en fonction de l’adresse de livraison saisie. Nous travaillons à ajouter la prise en charge de cette fonctionnalité lors de l’utilisation d’un formulaire intégré. pour recevoir une notification lors de sa sortie ou utilisez plutôt cette fonctionnalité avec [Elements avec l’API session Checkout](https://docs.stripe.com/payments/advanced/dynamically-update-line-items.md) à la place. # Formulaire intégré > This is a Formulaire intégré for when payment-ui is checkout-form. View the full page at https://docs.stripe.com/payments/checkout/dynamically-update-line-items?payment-ui=checkout-form. > En savoir plus sur [l’intégration d’un formulaire intégré](https://docs.stripe.com/payments/checkout/how-checkout-works.md?payment-ui=checkout-form). Découvrez comment ajouter, supprimer ou mettre à jour dynamiquement les postes inclus dans une [session Checkout](https://docs.stripe.com/api/checkout/sessions/object.md). ### Cas d’usage Ce guide vous explique comment mettre à jour des postes pour augmenter la vente d’un abonnement, mais vous pouvez également : - **Vérifier l’inventaire** : effectuez une vérification de vos stocks et réservez des articles lorsque les clients tentent de modifier des quantités d’articles. - **Ajout de nouveaux produits** : Ajoutez un produit gratuit si le total de la commande dépasse un certain montant. - **Mise à jour des tarifs de livraison** : Si le total de la commande change, mettez à jour les frais de livraison en combinant la méthode décrite dans ce guide avec celle indiqués à la rubrique [Personnalisation des options de livraison lors du paiement](https://docs.stripe.com/payments/checkout/custom-shipping-options.md). - **Mise à jour des taux de taxe** : Si vous n’utilisez pas [Stripe Tax](https://docs.stripe.com/tax/checkout.md), vous pouvez mettre à jour de manière dynamique les [taux de taxe](https://docs.stripe.com/billing/taxes/collect-taxes.md?tax-calculation=tax-rates#adding-tax-rates-to-checkout) appliqués aux postes de facture en fonction de l’adresse de livraison saisie. ## Créer une session Checkout [Côté serveur] Sur votre serveur, créez une *session Checkout* (A Checkout Session represents your customer's session as they pay for one-time purchases or subscriptions through Checkout. After a successful payment, the Checkout Session contains a reference to the Customer, and either the successful PaymentIntent or an active Subscription). > Pour utiliser cette fonctionnalité, assurez-vous que la version de votre SDK est`2025-03-31.basil` ou une version plus récente. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Version: 2026-04-22.preview; custom_checkout_payment_form_preview=v1" \ -d ui_mode=form \ -d mode=subscription \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ --data-urlencode "return_url=https://example.com/return" ``` ## Mise à jour dynamique des postes [Côté serveur] Créez un endpoint sur votre serveur pour mettre à jour les postes pendant la session Checkout. Vous l’appellerez à partir de l’interface dans une étape ultérieure. > Le code côté client s’exécute dans un environnement contrôlé par l’utilisateur. Un utilisateur malveillant peut contourner votre validation côté client, intercepter et modifier des requêtes, ou créer de nouvelles requêtes vers votre serveur. Lors de la création d’un endpoint, nous vous recommandons ce qui suit : - Créez des endpoints pour des interactions spécifiques avec les clients au lieu de les rendre génériques. Par exemple, « ajouter des éléments de vente croisée » au lieu d’une action générale de « mise à jour ». Des endpoints spécifiques peuvent faciliter l’écriture et la maintenance de la logique de validation. - Ne transmettez pas les [ données de session](https://docs.stripe.com/js/custom_checkout/session_object) directement du client à votre endpoint. Des clients malveillants peuvent modifier les données de requête, ce qui en fait une source peu fiable pour déterminer l’état d’une session de paiement. Au lieu de cela, transmettez l’[identifiant de session](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-id) à votre serveur et utilisez-le pour récupérer en toute sécurité les données à partir de l’API Stripe. #### Ruby ```ruby require 'sinatra' require 'json' require 'stripe' set :port, 4242 # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new( '<>', stripe_version: '2026-04-22.dahlia; custom_checkout_payment_form_preview=v1;', ) MONTHLY_PRICE_ID = '{{MONTHLY_PRICE}}' YEARLY_PRICE_ID = '{{YEARLY_PRICE}}' post '/change-subscription-interval' do content_type :json request.body.rewind request_data = JSON.parse(request.body.read) checkout_session_id = request_data['checkout_session_id'] interval = request_data['interval'] if checkout_session_id.nil? || !['yearly', 'monthly'].include?(interval) status 400 return { type: 'error', message: "We couldn't process your request. Please try again later." }.to_json end begin # 1. Create the new line items for the Checkout Session. new_price = interval == 'yearly' ? YEARLY_PRICE_ID : MONTHLY_PRICE_ID line_items = [{ price: new_price, quantity: 1, }] # 2. Update the Checkout Session with the new line items. client.v1.checkout.sessions.update(checkout_session_id, { line_items: line_items, }) # 3. Return a success response. { type: 'success' }.to_json rescue Stripe::StripeError # Handle Stripe errors with a generic error message status 400 { type: 'error', message: "We couldn't process your request. Please try again later." }.to_json rescue StandardError # Handle unexpected errors status 500 { type: 'error', message: 'Something went wrong on our end. Please try again later.' }.to_json end end ``` Lors de la mise à jour des postes, vous devez retransmettre l’ensemble du tableau des postes. - Pour conserver un poste existant, indiquez son `id`. - Pour mettre à jour un poste existant, indiquez son `id` ainsi que les nouvelles valeurs des champs à mettre à jour. - Pour ajouter un nouvel élément, indiquez un `price` et une `quantity` sans `id`. - Pour supprimer un poste existant, omettez l’identifiant du poste dans le tableau retransmis. - Pour réorganiser un poste, indiquez son `id` à la position souhaitée dans le tableau retransmis. ## Mettre à jour le SDK client [Côté client] #### HTML + JS Initialiser Stripe.js. ```javascript const stripe = Stripe('<>', { betas: ['custom_checkout_payment_form_1'] }); ``` #### React Initialiser l’instance `stripe`. ```javascript import {loadStripe} from '@stripe/stripe-js'; const stripe = loadStripe("<>", { betas: ['custom_checkout_payment_form_1'] }); ``` ## Requête de mise à jour du serveur [Côté client] #### HTML + JS À partir de votre interface, créez une fonction pour envoyer une requête de mise à jour à votre serveur et encapsulez-la dans [ runServerUpdate ](https://docs.stripe.com/js/custom_checkout/run_server_update) Une requête réussie met à jour l’objet [ Session ](https://docs.stripe.com/js/custom_checkout/session_object) avec les nouveaux postes. `runServerUpdate` impose un délai d’attente de 20 secondes pour votre fonction de mise à jour. Si votre fonction ne se résout pas dans ce délai, `runServerUpdate` renvoie une erreur. Encadrez les appels à `runServerUpdate` dans des blocs `try`/`catch` afin de gérer les erreurs et enregistrez des métriques pour diagnostiquer les délais d’attente et autres échecs. Encapsulez les appels `runServerUpdate` dans des blocs `try`/`catch` pour gérer les erreurs provenant de votre serveur et de `runServerUpdate` lui-même (par exemple, les délais d’expiration). `response.type === 'error'` couvre les échecs lors de la récupération interne par Stripe de la session mise à jour. Les erreurs renvoyées par votre propre serveur (telles que les réponses 4xx ou 5xx) ne sont pas reflétées dans `response`, car l’[API Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) se résout pour toute réponse HTTP complète, quel que soit le code d’état. Vérifiez `response.ok` dans votre fonction de mise à jour et levez une exception en cas d’échec pour que le bloc `catch` soit atteint. ```html ``` ```javascript document.getElementById('change-subscription-interval') .addEventListener("click", async (event) => { const button = event.target; const isCurrentSubscriptionMonthly = button.getAttribute("aria-checked") === "false"; const updateCheckout = async () => { const response = await fetch("/change-subscription-interval", { method: "POST", headers: { "Content-type": "application/json", }, body: JSON.stringify({ checkout_session_id: actions.getSession().id, interval: isCurrentSubscriptionMonthly ? "yearly" : "monthly", }) }); if (!response.ok) { const body = await response.json(); throw new Error(body.message); } }; try {const response = await checkout.runServerUpdate(updateCheckout); if (response.type === 'error') { // Handle Stripe API errors (for example, session retrieval failure) return; } } catch (error) { // Handle promise rejection from your server (4xx/5xx errors) or // from runServerUpdate itself (for example, timeouts). // error.message contains the message thrown from your update function. return; } // Update toggle state on success const isNewSubscriptionMonthly = !isCurrentSubscriptionMonthly; button.setAttribute("aria-checked", !isNewSubscriptionMonthly); button.textContent = isNewSubscriptionMonthly ? "Save with a yearly subscription" : "Use monthly subscription"; }); ``` #### React À partir de votre interface, envoyez une requête de mise à jour à votre serveur et encapsulez-la dans [ runServerUpdate ](https://docs.stripe.com/js/custom_checkout/run_server_update) Une requête réussie met à jour l’objet [ Session ](https://docs.stripe.com/js/custom_checkout/session_object) avec les nouveaux postes. `runServerUpdate` impose un délai d’attente de 20 secondes pour votre fonction de mise à jour. Si votre fonction ne se résout pas dans ce délai, `runServerUpdate` renvoie une erreur. Encadrez les appels à `runServerUpdate` dans des blocs `try`/`catch` afin de gérer les erreurs et enregistrez des métriques pour diagnostiquer les délais d’attente et autres échecs. Encapsulez les appels `runServerUpdate` dans des blocs `try`/`catch` pour gérer les erreurs provenant de votre serveur et de `runServerUpdate` lui-même (par exemple, les délais d’expiration). `response.type === 'error'` couvre les échecs lors de la récupération interne par Stripe de la session mise à jour. Les erreurs renvoyées par votre propre serveur (telles que les réponses 4xx ou 5xx) ne sont pas reflétées dans `response`, car l’[API Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) se résout pour toute réponse HTTP complète, quel que soit le code d’état. Vérifiez `response.ok` dans votre fonction de mise à jour et levez une exception en cas d’échec pour que le bloc `catch` soit atteint. ```jsx import React from 'react'; import {useCheckoutElements} from '@stripe/react-stripe-js/checkout'; const ChangeSubscriptionInterval = () => { const [isSubscriptionMonthly, setIsSubscriptionMonthly] = React.useState(false); const checkoutState = useCheckoutElements(); if (checkoutState.type === 'loading') { return (
Loading...
); } else if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } let actions = null; const loadActionsResult = await checkoutState.loadActions(); if (loadActionsResult.type === 'success') { actions = loadActionsResult.actions; } else { return (
Error: {loadActionsResult.error.message}
); } const updateCheckout = async () => { const response = await fetch("/change-subscription-interval", { method: "POST", headers: { 'Content-type': 'application/json', }, body: JSON.stringify({ checkout_session_id: actions?.getSession()?.id, interval: isSubscriptionMonthly ? 'yearly' : 'monthly' }) }); if (!response.ok) { const body = await response.json(); throw new Error(body.message); } }; const handleClick = async () => { try {const response = await actions?.runServerUpdate(updateCheckout); if (response.type === 'error') { // Handle Stripe API errors (for example, session retrieval failure) return; } } catch (error) { // Handle promise rejection from your server (4xx/5xx errors) or // from runServerUpdate itself (for example, timeouts). // error.message contains the message thrown from your update function. return; } // Update toggle state on success setIsSubscriptionMonthly(!isSubscriptionMonthly); }; return ( ); }; ```