# Zahlungsbeträge dynamisch aktualisieren Erfahren Sie, wie Sie die Gesamtbeträge ändern, wenn Kund/innen ihre Auswahl während des Bezahlvorgangs ändern. Aktualisieren Sie den Betrag einer [Checkout-Sitzung](https://docs.stripe.com/api/checkout/sessions.md) oder eines [Payment Intent](https://docs.stripe.com/api/payment_intents.md), wenn Kund/innen ändern, was sie kaufen oder wie viel sie bezahlen. Berechnen Sie die Summen auf Ihrem Server neu und aktualisieren Sie dann den Betrag des PaymentIntent. #### Häufige Anwendungsszenarien - Add-ons hinzufügen oder entfernen (z. B. Geschenkverpackung oder Garantie). - Wählen Sie eine andere Versandmethode oder Liefergeschwindigkeit aus. - Fügen Sie zusätzliche Dienstleistungen oder Gebühren hinzu. - Rabattcode oder Store-Gutschrift vor Steuern anwenden oder entfernen. #### Best Practices für die Sicherheit - Berechnen Sie Beträge auf Ihrem Server neu. Vertrauen Sie nicht auf vom Client angegebene Preise oder Summen. - Autorisieren Sie die Aktualisierung basierend auf Ihren Unternehmensregeln (z. B. Höchstmengen durchsetzen). - Aktualisieren Sie nur Sitzungen, die aktiv und nicht abgeschlossen oder abgelaufen sind. #### Einschränkungen und Verhalten - Sie können den Betrag aktualisieren, während der Payment Intent oder die Checkout-Sitzung auf Zahlung wartet (z. B. `requires_payment_method` oder `requires_confirmation`). - Nach der Bestätigung können Sie den Betrag in der Regel nicht erhöhen. # Checkout Sessions API > This is a Checkout Sessions API for when payment-ui is embedded-components. View the full page at https://docs.stripe.com/payments/advanced/dynamically-update-amounts?payment-ui=embedded-components. ## Client-SDK aktualisieren [Clientseitig] Wenn Sie Elements mit der Checkout Sessions API verwenden, schließen Sie Client-Aufrufe an Ihren Server in `runServerUpdate` ein, damit der Bezahlvorgang-Status und die Gesamtsummen aktualisiert werden. Umschließen Sie `runServerUpdate`-Aufrufe in `try`/`catch`-Blöcken, um Fehler von Ihrem Server und von `runServerUpdate` selbst zu behandeln (z. B. Timeouts). `response.type === 'error'` deckt Fehler bei der internen Abfrage der aktualisierten Sitzung von Stripe ab. Fehler, die von Ihrem eigenen Server zurückgegeben werden (wie 4xx- oder 5xx-Antworten), werden nicht in `response` widergespiegelt, da die `[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)` jede abgeschlossene HTTP-Antwort unabhängig vom Statuscode auflöst. Überprüfen Sie `response.ok` in Ihrer Update-Funktion und lösen Sie bei einem Fehler eine Ausnahme aus, damit der `catch`-Block erreicht wird. #### HTML + JS ```javascript import {loadStripe} from '@stripe/stripe-js'; // Optional: include beta flags if your integration requires them const stripe = await loadStripe('<>', { betas: ['custom_checkout_server_updates_1'], }); const checkout = stripe.initCheckoutElementsSdk({ clientSecret, elementsOptions: {/* ... */}, }); // Example: Add additional service using price_data const loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === 'success') { const actions = loadActionsResult.actions; const session = actions.getSession(); document .getElementById('add-service') .addEventListener('click', async () => { const updateOnServer = async () => { const response = await fetch('/update-custom-amount', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ checkout_session_id: session.id, product_id: 'gift_wrap', // Server looks up actual price }), }); if (!response.ok) { const body = await response.json(); throw new Error(body.message); } }; try { const response = await actions.runServerUpdate(updateOnServer); if (response.type === 'error') { // Handle Stripe API errors (for example, session retrieval failure) } } 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. } }); } ``` #### React ```jsx import React from 'react'; import {useCheckoutElements} from '@stripe/react-stripe-js'; export const AddServiceButton = () => { const checkoutState = useCheckoutElements(); if (checkoutState.type === 'loading') { return (
Loading...
); } else if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } const {runServerUpdate, id} = checkoutState; const addService = async () => { const updateOnServer = async () => { const response = await fetch('/update-custom-amount', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ checkout_session_id: id, product_id: 'gift_wrap', // Server looks up actual price }), }); if (!response.ok) { const body = await response.json(); throw new Error(body.message); } }; try { const res = await runServerUpdate(updateOnServer); if (res.type === 'error') { // Handle Stripe API errors (for example, session retrieval failure) } } 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 ( ); }; ``` ## Server-Endpoints erstellen [Serverseitig] Berechnen Sie Beträge und validieren Sie Eingaben auf Ihrem Server. Anschließend können Sie `line_items` mit [price_data](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items-price_data) aktualisieren, um Ad-hoc-Zahlungen hinzuzufügen. > Durch die Aktualisierung der `line_items` oder `price_data` werden die Gesamtbeträge der Sitzung und die Steuern neu berechnet. #### Node ```node import express from 'express'; import Stripe from 'stripe'; const app = express(); app.use(express.json()); // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = new Stripe('<>'); // Product catalog with prices - store this securely server-side const PRODUCTS = { gift_wrap: { name: 'Gift Wrap', price: 500 }, // $5.00 express_shipping: { name: 'Express Shipping', price: 1500 }, // $15.00 warranty: { name: 'Extended Warranty', price: 2000 }, // $20.00 }; app.post('/update-custom-amount', async (req, res) => { try { const {checkout_session_id, product_id} = req.body; const session = await stripe.checkout.sessions.retrieve(checkout_session_id); if (session.status === 'complete' || session.expires_at * 1000 < Date.now()) { return res.status(400).json({error: 'Session is no longer updatable.'}); } // Look up product price server-side const product = PRODUCTS[product_id]; if (!product) { return res.status(400).json({error: 'Invalid product ID'}); } // Add the additional product via price_data const updated = await stripe.checkout.sessions.update(checkout_session_id, { line_items: [ { price_data: { currency: 'usd', product_data: {name: product.name}, unit_amount: product.price, }, quantity: 1, }, ], }); return res.json({id: updated.id, amount_total: updated.amount_total}); } catch (err) { return res.status(400).json({error: err.message}); } }); app.listen(4242, () => console.log('Server running on port 4242')); ``` # Payment Intents API > This is a Payment Intents API for when payment-ui is elements. View the full page at https://docs.stripe.com/payments/advanced/dynamically-update-amounts?payment-ui=elements. ## Gesamtbeträge auf dem Server neu berechnen und aktualisieren [Serverseitig] So aktualisieren Sie den Gesamtbetrag: 1. Rufen Sie die Änderungen am Warenkorb oder an der Auswahl vom Client ab. 1. Berechnen Sie den neuen Gesamtbetrag auf Ihrem Server neu. 1. Den PaymentIntent mit dem neuen Betrag aktualisieren. 1. Übergeben Sie den PaymentIntent (oder sein `client_secret`) an den Client. #### Node ```node import express from 'express'; import Stripe from 'stripe'; const app = express(); app.use(express.json()); // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = new Stripe('<>'); function computeOrderAmount(items, options = {}) { // ToDo: Your logic to compute an order total } app.post('/update-payment-intent', async (req, res) => { try { const {payment_intent_id, items, shipping_cents, service_cents, discount_cents} = req.body; // Compute amount on server const amount = computeOrderAmount(items, {shipping_cents, service_cents, discount_cents}); // Update the amount if the PaymentIntent can be updated const pi = await stripe.paymentIntents.update(payment_intent_id, { amount, }); return res.json({id: pi.id, amount: pi.amount, client_secret: pi.client_secret}); } catch (err) { return res.status(400).json({error: err.message}); } }); app.listen(4242, () => console.log('Server running on port 4242')); ``` ## Client aktualisieren und bestätigen [Clientseitig] > Sie sind dafür verantwortlich, Client und Server zu synchronisieren. Aktualisieren Sie nach der Aktualisierung des PaymentIntent-Betrags auf dem Server die Nutzeroberfläche und bestätigen Sie, wenn der Kunde bereit ist.