How to Accept PCI-Compliant Payments Over the Phone with Stripe and Twilio

Have you moved lately? Did you call the utility company to set up your account? Chances are someone on the other end of the line accepted your credit card information over the phone. That action of accepting PCI-compliant payments can be vital to your business. Believe it or not, there are still people who would just rather call and speak to a person rather than filling out a form on a landing page. Right now, I'm going to show you how, in under five minutes, to capture payment details and charge a credit card using Twilio's <Pay> TwiML verb and Stripe.

The Set Up

First things first, head over to Stripe to set up an account if you haven't already. Next, you need to authorize Twilio to create charges and tokens on your behalf by connecting your Stripe account to Twilio's Stripe Connect Platform.

To start, head over to the Twilio Voice Settings Console Page and enable PCI mode, opt-in to Twilio's Terms of Service and click save.

The Twilio Voice Settings Console Page

Now, Navigate to <Pay> Connectors under Programmable Voice and click on the Stripe tile and install.

Navigate to &lt;Pay&gt; Connectors under Programmable Voice
Install Stripe controller

Set the Stripe Connector unique name to Default. You can create one <Pay> Connector per Twilio account with the name Default. When <Pay> is invoked, if the paymentConnector attribute is not specified then the default <Pay> Connector is used.

Set the Stripe Connector unique name to Default

Click on "Connect with Stripe" which will redirect over to Stripe and ask you to enter your credentials. After that, your Stripe account will be connected to the Twilio Stripe Connect Platform.

Set Up Twilio Pay to Capture Payment Details

With a small amount of TwiML, <Pay> will capture the four pieces of payment details needed to create a charge on a credit card. Those are:

  1. The user's 16-digit credit card number
  2. The expiration date for the credit card
  3. The zip code tied to the credit card account
  4. The CVC security code

If you're interested in customization for Pay check out <Pay> documentation.

Head over to TwiML Bins in your console. Click on the red plus icon to create a new bin. Give your new TwiML Bin a friendly name of "<Pay> with Stripe", then enter the following TwiML:

Head over to TwiML Bins in your console. Click on the red plus icon to create a new bin.

Save your TwiML bin and copy the URL it provisions for you.

Create a Twilio Function to Handle <Pay>ments

When <Pay> completes capturing our user's credit card, it will initiate a transaction with Stripe and then send some information via webhook to a URL you specify in your Stripe dashboard.

Now we'll need to create that Callback function. We'll be leveraging Twilio Functions, but you can use any publicly accessible URL you might build. Functions is Twilio's serverless solution allowing you to deploy JavaScript-based applications.

You can customize your callback code to personalize the experience for your customers. For this tutorial, we'll look at the status after <Pay> completes. The function could be extended to also look at the PaymentError attribute which contains the status Stripe sent back for the user's payment method.

To create this Function:

  1. Navigate to the Functions home in your console
  2. Click on the red plus icon to create a new function
  3. Select "blank" for your functions template and click "create"
  4. Rename your function to "pay" and update the path to /pay. This will be the URL that hosts this code for you
  5. Select "Incoming Voice Calls" as your event
  6. Now you can remove all the boilerplate code and paste the following into your function:
Now you can remove all the boilerplate code and paste the following into your function:
  1. Save your function. This will fully deploy it
  2. Copy the URL for your new function, then head back to the TwiML bin you created in the last step

Update your code to include your function URL in the action parameter. Now your TwiML code should look like this:

Update your code to include your function URL in the action parameter.

Once your TwiML bin is saved, it's time to connect a phone number to your new Pay application.

Purchase a Voice-Enabled Twilio Phone Number

In the Twilio console, search for and purchase an available phone number capable of voice calls.

Now that you have a phone number in hand, you need to tell it where to find your <Pay> application for managing calls. Click on "set up number" (or if using an owned Twilio phone number, click it in your list of phone numbers.)

Scroll to the "Voice & Fax" section. Double-check that "Accept Incoming" is set to Voice Calls, and Configure With is set to " Webhooks, TwiML Bins...".

Next to where it reads "A call comes in", select "TwiML" from the drop-down. You'll then be able to select the TwiML bin you made earlier.

Save your changes — it's time to test!

Test and Run the Code

At this point, you're ready to try everything out. Call the phone number you purchased above and enter the test values. To verify that your application correctly captured this data, navigate to your Call Logs and click on your most recent call. Scroll down to see the Request Inspector. Expand the parameters on the second POST for your call. You can navigate over to your Stripe Dashboard, copy the "PaymentConfirmationCode" "ch_xxxxx," and paste into the Stripe search. You should see the following:

Test and Run the Code

You're All Set!

After you've tested, you're good to go! Process credit cards over voice to your heart's content. Now you know 1) what an IVR is 2) just one of the many really interesting and helpful things IVR can do for you and your business. Check back here soon to see what other nifty things can be done with Twilio!