<div id="root">
    <!-- This element's contents will be replaced with your component. -->
</div>
@import url('https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap');
body{
  font-size: 16px;
  font-family: 'Roboto', sans-serif;
}

.pricing-table{
  display: flex;
  flex-direction: row;
  
  h1{
    letter-spacing: 2px;
    text-transform: uppercase;
    font-size: 1.8em;
  }
  .tier{
    text-align: center;
    padding: 10px;
    margin-right: 20px;
  }
}
button{
  margin-top: 20px;
  background: #3434bb;
  color: white;
  padding: 8px 18px;
  border: none;
  line-height: 10px;
  border-radius: 4px;
  text-transform: uppercase;
}



.Checkout {
  margin: 0 auto;
  max-width: 800px;
  box-sizing: border-box;
  padding: 0 5px;
}

.StripeElement {
  display: block;
  margin: 10px 0 20px 0;
  max-width: 500px;
  padding: 10px 14px;
  box-shadow: rgba(50, 50, 93, 0.14902) 0px 1px 3px, rgba(0, 0, 0, 0.0196078) 0px 1px 0px;
  border-radius: 4px;
  background: white;
}

.StripeElement--focus {
  box-shadow: rgba(50, 50, 93, 0.109804) 0px 4px 6px, rgba(0, 0, 0, 0.0784314) 0px 1px 3px;
  -webkit-transition: all 150ms ease;
  transition: all 150ms ease;
}
View Compiled

const STRIPE_PUBLIC_KEY = "pk_test_lfk7VEvgFhqpmd9EFSrbRKVJ00tuCe7h59"
const stripe = Stripe(STRIPE_PUBLIC_KEY);
const CREATE_SUBSCRIPTION = "https://us-central1-servicebot-1556223775953.cloudfunctions.net/create-subscription";
const {useState, useEffect} = React;

function SCAExample({pricingPlans}){
  const [complete, setComplete] = useState(null);
  const [loading, setLoading] = useState(false);
  return <div className="pricing-table">
    {complete === true && <h1>Payment Authorized!</h1>}
    {complete === false && <h1>Payment Authorization Incomplete!</h1>}
    {complete === null && pricingPlans.data.map(({id, interval, amount, product: {name}})=>{
      async function createSubscription(){
        setLoading(true);
        let response = await (await fetch(CREATE_SUBSCRIPTION)).json();
        let {paymentIntent, err} = await stripe.handleCardPayment(response.latest_invoice.payment_intent.client_secret);
        setLoading(false);
        setComplete(!!paymentIntent);
      }
      if(loading){
        return <h1 key={id}>Creating subscription...</h1>
      }
      return <div className="tier" key={1}>
        <h1>{name}</h1>
        <h4>${amount/100}/{interval}</h4>
        <h4>Used stored card ending in 3184</h4>
        <button onClick={createSubscription}>Buy Now</button>
      </div>
    })}</div>
}


//use your REST API to get this payload
const examplePlansPayload = {"object":"list","data":[{"id":"plan_FvnU01xoIPrg9l","object":"plan","active":true,"aggregate_usage":null,"amount":30000,"amount_decimal":"30000","billing_scheme":"per_unit","created":1570215199,"currency":"usd","interval":"month","interval_count":1,"livemode":false,"metadata":{},"nickname":"AcmeBot Premium Monthly","product":{"id":"prod_FvTwoyr6n21fmT","object":"product","active":true,"attributes":[],"caption":null,"created":1570142433,"deactivate_on":[],"description":null,"images":[],"livemode":false,"metadata":{},"name":"AcmeBot Premium","package_dimensions":null,"shippable":null,"statement_descriptor":null,"type":"service","unit_label":null,"updated":1570215201,"url":null},"tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":null,"usage_type":"licensed"}],"has_more":false,"url":"/v1/plans"}

ReactDOM.render(
       <SCAExample pricingPlans={examplePlansPayload} />,
  document.getElementById('root')
);
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/react/umd/react.development.js
  2. https://unpkg.com/react-dom/umd/react-dom.development.js
  3. https://unpkg.com/react-stripe-elements@latest/dist/react-stripe-elements.js
  4. https://js.stripe.com/v3/