<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 stripePublicKey = "pk_test_lfk7VEvgFhqpmd9EFSrbRKVJ00tuCe7h59"
const {useState, useEffect} = React;
const {
  CardElement,
  StripeProvider,
  Elements,
  injectStripe,
} = ReactStripeElements

class _CardForm extends React.Component {
  render() {
    return (
     <form onSubmit={(e) =>{
       const {stripe, setComplete} = this.props;
       e.preventDefault();  
       stripe.createToken().then(payload => {console.log(payload) //send this back to your server and create a subscription
         setComplete(payload);
                                             
                                                      }
)}}>
        <CardElement />
        <button>Pay</button>
      </form>
    )
  }
}
const CardForm = injectStripe(_CardForm)

function Checkout({planId, setComplete}){
  
    return (
      <div className="Checkout">
        <Elements>
          <CardForm setComplete={setComplete} planId={planId} />
        </Elements>
      </div>
    )
  
}


function Pricing({pricingPlans, onPlanSelect}){
  return <div  className="pricing-table">{pricingPlans.data.map(({id, interval, amount, product: {name}})=>{
      return <div className="tier" key={id}>
        <h1>{name}</h1>
        <h4>${amount/100}/{interval}</h4>
        <button onClick={onPlanSelect(id)}>Get Started</button>
      </div>
    })}</div>
}
const App = () => {
  const [checkoutPlan, setCheckoutPlan] = useState(null);
  const [complete, setComplete] = useState(false);
  if(complete){
    return <h1>Card Token - {complete.token.id}</h1>
  }else if(checkoutPlan){
   return (
    <StripeProvider apiKey={stripePublicKey}>
      <Checkout setComplete={setComplete} plan={checkoutPlan}/>
    </StripeProvider>
  )}else{
     return(<Pricing
              onPlanSelect={(planId) => () => {
                              setCheckoutPlan(planId)
         }}
    pricingPlans={examplePlansPayload}
                            />)
   }
}

//use your REST API to get this payload
const examplePlansPayload = {"object":"list","data":[{"id":"plan_FvTvGSPxWqstmU","object":"plan","active":true,"aggregate_usage":null,"amount":5000,"amount_decimal":"5000","billing_scheme":"per_unit","created":1570142400,"currency":"usd","interval":"month","interval_count":1,"livemode":false,"metadata":{},"nickname":"AcmeBot Basic Monthly","product":{"id":"prod_FvTv1AXgDxCZ7w","object":"product","active":true,"attributes":[],"caption":null,"created":1570142365,"deactivate_on":[],"description":null,"images":[],"livemode":false,"metadata":{},"name":"AcmeBot Basic","package_dimensions":null,"shippable":null,"statement_descriptor":null,"type":"service","unit_label":null,"updated":1570142401,"url":null},"tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":null,"usage_type":"licensed"},{"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(
  <App/>,
  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/[email protected]/dist/react-stripe-elements.js
  4. https://js.stripe.com/v3/