Payment Request Button in an iFrame

The Payment Request Button inside different iframe elements

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

⚙️ Integration

Same Origin iFrame

Cross-Origin iFrame

Things to note

🧑‍💻 Code

<h3>Same Origin iFrame</h3>

<iframe src="iframe.html"></iframe>

<h3>Cross-Origin iFrame</h3>

<iframe src="https://foo.4242.io/test/payment-request-button-iframe/iframe.html" allow="payment *"></iframe>

<h4>Things to note</h4>

<ul>
  <li>The <code>allow="payment *"</code> attribute is only required for cross-origin iframes</li>
  <li>To get Apple Pay working <strong>both</strong> the top-level and iframe domains need to be <a href="https://docs.stripe.com/payments/payment-methods/pmd-registration?dashboard-or-api=dashboard#verify-domain-with-apple">verified with Apple</a></li>
</ul>
iframe {
  width: 100%;
  height: 26em;
  border: solid black 1px;
  margin: 0 0 1rem 0;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="color-scheme" content="light dark">
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
    <link rel="stylesheet" href="/css/common.css">
    <link rel="stylesheet" href="/test/css/style.css">
    <title>Payment Request Button iFrame</title>
  </head>
  <body>
    <header>
      <h1>iFrame</h1>
    </header>
    <main>
      <script src="https://js.stripe.com/v3/"></script>
      
      <p id="payment-request-button"></p>
      
      <pre id="output"></pre>
      
      <script>
        const stripe = Stripe('pk_test_51O2hxMC4JnNRtz8VToJJbGHrFTPPr6TkP09h7ql3YJaqpNcxoSNxtk38glyzi9VrZKStns858YynOO2ZyGmU7VRi00CIUWuUdk');
        
        const output = document.querySelector('#output');
        
        const paymentRequest = stripe.paymentRequest({
          country: 'US',
          currency: 'usd',
          total: {
            label: 'Total label',
            amount: 4200,
          },
        });
        
        const elements = stripe.elements();
        
        const paymentRequestButton = elements.create('paymentRequestButton', {
          paymentRequest: paymentRequest,
        });
        
        (async () => {
          const result = await paymentRequest.canMakePayment();
          
          output.textContent += "canMakePayment result:\n\n" + JSON.stringify(result, null, 2);
          
          if (result) {
            paymentRequestButton.mount('#payment-request-button');
          } else {
            document.getElementById('payment-request-button').style.display = 'none';
          }
        })();
        
        paymentRequest.on('paymentmethod', function(event) {
          output.textContent = "paymentmethod event:\n\n" + JSON.stringify(event, null, 2);
          event.complete('success');
        });
      </script>
    </main>
  </body>
</html>