Accept Serverless Payments with Stripe and PubNub Functions

By Chandler Mayo

This tutorial covers how to build a chat application that accepts serverless payments using Stripe and PubNub Functions. Whether you’re already using PubNub or not, this is an easy way to process payments without having to set up your own backend infrastructure.

This example shows how to create a chat application secured through a payment. You can reuse this code to do things like selling products or services, restricting access to a webpage, selling a digital download, accepting donations, or anything else you’d want to process payments for.

Why Serverless? What is Serverless?

If you’re looking to process payments in your application, you’ll need to set up a secure environment to create the charge with a payment gateway. It may seem like a good idea to set up your own infrastructure so you can have complete control over everything, but this can be a bad idea. Doing it yourself means you’ll have to manage uptime, scale to handle traffic loads, and ensure security. If you want to build a reliable product that never fails, you’ll want a better solution.

A better approach is to offload scaling responsibility to a cloud provider. With this model, you will often pay for the resources used by your product on a ‘pay as you go’ basis instead of buying units of computing capacity.

This is the case with Functions-as-a-Service (FaaS). The cloud provider handles most or all of the server administration, provisioning, security, and maintenance. That means your product infinitely scales without managing servers or infrastructure.

More advantages of a serverless design pattern include:

  • Reduced Cost: Pay for what you use and not for idle servers.
  • Decreased Time to Market: Focus on building your product and not managing the infrastructure to support it.
  • Reduced Latency: Your users are global. Your product should be global. Cloud services operate points of presence across regions delivering a faster and higher quality service to your users.

What are PubNub Functions?

PubNub Functions is a serverless environment to execute functions. PubNub Functions are JavaScript event handlers that can be executed on in-transit PubNub messages or in the request/response style of a RESTful API over HTTPS. If you are familiar with Node.js and Express, the On Request event handler development will be second nature.

Build a Service Secured with a Stripe Charge

This example shows a way to create a chat application secured with a payment. Chat apps are a common use case for PubNub’s core publish-subscribe offering, however, you can do a lot more with accepting payments. You can use the same code to build an online store, sell a subscription to an online magazine, or make a P2P payment app.

Want to skip right to the demo or see the completed code? Find ChatEngine Paid Stripe Chat on Github.

How Our App Will Work

  1. A user enters their payment details and a preferred username into our app’s frontend. The payment details are sent directly to Stripe using Stripe.js. Stripe.js then tokenizes the sensitive information so that it won’t be exposed when sent to a backend to initiate a charge.
    • It is against PubNub Terms and Conditions to send credit card information including credit card numbers, CSV numbers (three-digit codes for Visa and MasterCard, four-digit code for American Express) and magnetic stripe information through the PubNub network.
  2. The token is used by our Stripe Charge Function, hosted in PubNub functions, to initiate a charge with Stripe.
  3. The charge is processed by Stripe and our Stripe Charge Function receives the result. If the payment was successful then we add the user’s username into a KV store also provided by PubNub.
  4. The payment status is then forwarded to the app’s frontend and the user is granted access to our chat application.
  5. You can verify if the user has already paid with an Auth Check Function that looks up a user’s username in the KV store.

Important Considerations

The frontend of our app can be hosted on Github Pages or you can test it locally.

Our app is built on top of ChatEngine Basic Chat project powered by PubNub ChatEngine. ChatEngine uses PubNub Functions Serverless Environment as a globally distributed back-end. This is deployed by clicking the button in the ChatEngine Activation form below. The basic chat app tutorial can be found here.

Getting Started

  • You’ll need a Stripe account and API keys. You don’t need to activate your account unless you plan to go beyond testing. The test keys will work fine for this project.
  • You’ll need to deploy a ChatEngine application. It’s completely free up to a million messages per month. You can write an HTML, CSS, and JavaScript chat app with the ChatEngine Client SDK.

Hold on to these PubSub keys! They are integral to our Chat application, and we will paste them into the client code.

Setting Up Serverless Functions

Go to your PubNub Admin Dashboard and find the application named “ChatEngine Quickstart” that you created with the deploy tool above. Then click on the keyset that was created for that app.

Next click “Functions” in the sidebar and then the “chatengine-application” module.

Click “Create”, name the function “AuthCheck”, set the event type to “On Request”, and set the path to “auth.”

Delete any code in the editor and replace it with a function to lookup our user’s username in the KV store:

// Set the module event type to "On Request".
export default (request, response) => { const db = require("kvstore"); const username = request.params.username; return db.get(username).then((dataFromDb) => { if (!dataFromDb) { console.log("The username does not exist!"); // db.set(username, {}); // Uncomment to allow on later requests. response.status = 401; return response.send("Not Allowed"); } else { console.log("The username already exists!"); response.status = 200; return response.send("Allowed"); } });

Create another function and name the function “Stripe”, set the event type to “On Request”, and set the path to “stripe”.

Delete any code in the editor and replace it with a function to create a charge with Stripe and then add the user’s username to the KV store if the charge was successful:

// Set the module event type to "On Request".
export default (request, response) => { const db = require("kvstore"); const vault = require("vault"); const xhr = require("xhr"); const token = request.params.token; const username = request.params.username; return db.get(username).then((dataFromDb) => { if (!dataFromDb) { return vault.get("sk_test").then((apiKey) => { const http_options = { "method": "POST", "headers": { "Authorization": "Bearer "+apiKey, }, }; return xhr.fetch(""+token, http_options).then((resp) => { if (resp.status == 200) { db.set(username, {}); } response.status = resp.status; return response.send(resp); }); }); } else { console.log("The username already exists!"); response.status = 200; return response.send("Allowed"); } });

You’ll need to add your Stripe secret key to the PubNub vault. Click on “My Secrets” in the function editor and add a key named “sk_test” with your test Stripe secret key.

Setting Up The Frontend

Download, clone, or fork the frontend from the ChatEngine Paid Chat Example GitHub Repo.

The paid chat example is similar to ChatEngine Basic Chat with the addition of a credit card input form powered by Stripe Checkout. Open “app.js”.

Edit the line where the Stripe client is created and replace the Stripe publishable key with your key.

// Create a Stripe client.
var stripe = Stripe('pk_test_REPLACE_ME');

Edit the ChatEngine initialization and replace the publish and subscribe keys with your keys from when you deployed your ChatEngine app.

// Init ChatEngine
const ChatEngine = ChatEngineCore.create({ publishKey: 'pub-key-replace', subscribeKey: 'sub-key-replace'
}, { globalChannel: 'paid-chat-example'

Open “index.html” in your browser or deploy with GitHub pages. If you decide to deploy with GitHub Pages, ensure the “Enforce HTTPS” option is checked (it won’t show up right away after deploying the first time).

Use a Stripe test card to pay for access to the chat.

Try refreshing the page and inputting your paid username to rejoin chat.

What’s Next?

Here are a few ideas:

Have suggestions or questions about the content of this post? Reach out at