Build fast checkout with SMS verification using Stripe and Twilio

April 17, 2020
Written by
Thor 雷神 Schaeff
Contributor
Opinions expressed by Twilio contributors are their own

stripe fast checkout

Stripe and Twilio have teamed up to build a sample application that shows you how to securely collect and store payment details from your customers and use Twilio Verify to send returning customers an authentication code before charging their saved card details.

Demo and resources

- View the sample on the Twilio CodeExchange If you prefer to watch this tutorial, you can find a recording of how to set up the sample application on the Stripe Developers YouTube channel: ![Youtube video recording of a code walkthrough](https://www.youtube.com/watch?v=gjh5gOalYcM)
The sample application comes with two backend implementations one in JavaScript (Node) and one in Python (Flask). In this tutorial we outline how to set up the Node.js backend. You can find instructions for running the Python Flask server here.

Creating the sample with the Stripe CLI

stripe login

Setting up the environment variables

NOTE: All values in the .env file except for the STRIPE_PUBLISHABLE_KEY must be kept secret. Therefore always double check that you're not committing the .env file to git!

npm start

A look at the source code

Setting up an international phone number input field

// client/script.js

// Format phone number input field
const phoneInputField = document.querySelector('#phone');
const phoneInput = window.intlTelInput(phoneInputField, {
  separateDialCode: true,
  utilsScript: 'build/js/utils.js',
});
// Validate input
phoneInput.isValidNumber();
// Format input
phoneInput.getNumber();

Look up the phone number on the server

// server/server.js

try {
  // Validate the phone number input
  const number = await client.lookups.phoneNumbers(phone).fetch();
  number.phoneNumber; // Is valid number
} catch (error) {
  // Not a valid number
}

Collect and store the customer's payment details

// server/server.js

// Create a new customer object
const customer = await stripe.customers.create({
  phone: number.phoneNumber,
  email,
});

// Create a CheckoutSession to set up our payment methods recurring usage
const checkoutSession = await stripe.checkout.sessions.create({
  payment_method_types: ['card'],
  mode: 'setup',
  customer: customer.id,
  success_url: `${req.headers.origin}?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${req.headers.origin}/`,
});

Send the verification code

// server/server.js

// Start Twilio verify
const verification = await client.verify
  .services(process.env.VERIFY_SERVICE_SID)
  .verifications.create({ to: customer.phone, channel: 'sms' });

Check the verification code

// server/server.js

try {
  // Check Twilio verify code
  const verificationCheck = await client.verify
    .services(process.env.VERIFY_SERVICE_SID)
    .verificationChecks.create({ to: customer.phone, code });

  // Check the status
  if (verificationCheck.status === 'approved') {
    // Verification code is valid
  }
} catch (error) {
  // Incorrect code
}

Charge the customer

// server/server.js

// Charge the stored method
const paymentIntent = await stripe.paymentIntents.create({
  amount,
  currency,
  customer: customerId,
  payment_method: paymentMethods.data[0].id,
  off_session: false, // Customer is on-session during checkout
  confirm: true, // Confirm and charge payment immediately
});

Listen to Stripe webhook events

stripe listen --forward-to localhost:4242/webhook
We hope you found this tutorial helpful ❤️ If you have any feedback or questions you can reach the authors on Twitter: