Payment Element: Deferred with update-end Event

A single Payment Element which uses the deferred flow, calls elements.update in the pay button click handler, and handles the update-end event to proceed with the payment process

⚠️ Note: This integration is not production ready and should only be used as a reference.

⚙️ Integration


      

🧑‍💻 Code

<?php

if (isset($_GET['createPaymentIntent'])) {
  $stripeConfiguration = [
    'api_key' => 'sk_•••',
    'stripe_version' => '2023-10-16',
  ];
  
  $stripe = new \Stripe\StripeClient($stripeConfiguration);
  
  $paymentIntent = $stripe->paymentIntents->create([
    'amount' => 4200,
    'currency' => 'usd',
  ]);
  
  header('Content-Type: application/json');
  echo json_encode([
    'clientSecret' => $paymentIntent->client_secret,
  ]);
  exit;
}
<script src="https://js.stripe.com/v3/"></script>

<p id="payment-element"></p>

<p><button type="button" id="payButton">Pay</button></p>

<pre id="output"></pre>
#payment-element {
  /* Provides a visual outline of the Element */
  border: solid 1px;
  /* Required for dark mode legibility */
  background-color: white;
  /* Aesthetics */
  padding: 1rem;
  border-radius: .25rem;
}
const outputElement = document.querySelector('#output');

const stripe = Stripe('pk_test_51O2hxMC4JnNRtz8VToJJbGHrFTPPr6TkP09h7ql3YJaqpNcxoSNxtk38glyzi9VrZKStns858YynOO2ZyGmU7VRi00CIUWuUdk');

const elements = stripe.elements({
  mode: 'payment',
  amount: 4200,
  currency: 'usd',
});

const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');

elements.on('update-end', async event => {
  const {error: submitError} = await elements.submit();
  
  if (submitError) {
    output.textContent = JSON.stringify(submitError, null, 2);
    return;
  }
  
  const response = await fetch('?createPaymentIntent');
  
  const {clientSecret} = await response.json();
  
  const {error} = await stripe.confirmPayment({
    elements,
    clientSecret,
    confirmParams: {
      return_url: window.location.href,
    },
  });
  
  if (error) {
    outputElement.textContent = 'Error confirming payment: ' . error.message;
  }
});

const payButton = document.querySelector('#payButton');

payButton.addEventListener('click', async event => {
  // This will trigger the update-end event handler above which handles the rest of the flow
  elements.update({
    amount: 4700,
  });
});

// If the URL contains a Payment Intent's client secret, retrieve the Payment Intent and display it
const urlSearchParams = new URLSearchParams(window.location.search);

if (urlSearchParams.has('payment_intent_client_secret')) {
  stripe.retrievePaymentIntent(urlSearchParams.get('payment_intent_client_secret')).then(result => {
    if (result.error) {
      output.textContent = 'Unable to retrieve Payment Intent using client secret in URL: ' + JSON.stringify(result.error, null, 2);
      return;
    }
    
    output.textContent = "Payment Intent retrieved using client secret in URL:\n\n" + JSON.stringify(result.paymentIntent, null, 2);
  });
}