Incapture Technologies

Inside the Cloud

Incapture Technologies Blog

 

Integrating Third-Party Services with Rapture: Stripe (Payments)

Published:
June 8, 2016
Author:

Clients building applications using Rapture may want to collect payment from users based on some usage metric (recurring subscription, service-based fees, consumption-based fees, etc.). In this blog post, we will describe how we integrated Stripe with Rapture to set up a subscription service for our hosted trial environments through the Incapture developer portal.

Stripe offers a suite of APIs that support online commerce. Two aspects of their offering stood out to us –
i. Emphasis on security and PCI compliance — all sensitive credit card data is directly sent to Stripe’s vault, without it touching Incapture’s servers
ii. Developer-friendly APIs — good documentation wins, hands down.

I’ll give examples of how easy it was to build the integration using Rapture’s Reflex language — a procedural language that runs on the Java Virtual Machine — with Stripe’s API. This article is as much about Stripe subscriptions as it is about Rapture, Reflex and a front-end framework (in this case, Angular) providing the requisite stack to build a simple web app.

 

I. Creating a Subscription Plan in Stripe
The use case our application addresses is migrating clients from a free to paid subscription after some initial trial period. Our first step was to define parameters of a subscription plan through the Stripe dashboard; we opted for a test 30-day recurring subscription at $50 per month with no limits on usage. Now, every time a customer requests a new environment, we can associate the subscription plan ID with it.

Stripe has the option of specifying a trial period while creating a subscription plan — a handy feature that releases you from the responsibility of keeping a tab on the trial end date. However, this also necessitates collection of payment details at the time an environment is set up. We decided to not use the feature to ensure a zero-pressure customer onboarding experience.

So, when a customer accesses their dev portal dashboard, in addition to being notified when the trial period ends, there’s now an option to “Upgrade” their environment.

 

Subscription status on an environment card

Fig. 1. ‘Subscription Status’ on an environment card on the dev portal dashboard

 

II. Creating a Form to Collect Payment Details
We took advantage of Stripe’s Checkout form. It is customizable at a high level (company logo, title etc.) as well as at a functional level. We can use the same form for two different purposes — creating a subscription and updating payment details — by passing in appropriate arguments to the handler.

 

Stripe Checkout handler with different arguments

Fig.2. Stripe Checkout handler with different arguments

 

III. Creating a Subscription
If a customer signs up for a subscription for the very first time (i.e. they have never provided their payment details before), submitting the form creates two new objects:
i. Stripe customer
ii. Stripe subscription — that ties the customer object to the subscription plan we created via the Stripe dashboard.

A returning user who previously created a subscription for another environment will already be associated with a customer object (and, consequently, a payment source) and we do not need to collect payment details again. All we do is create a new subscription object and link it to the customer object.

Once created, Stripe will automatically renew the subscription every 30 days.

 

IV. Managing Subscriptions
Developers have a lot of flexibility in designing payment workflows in Rapture applications. For instance, basic tasks like updating payment information and canceling or refreshing subscriptions can be fully automated. Alternatively, certain actions can trigger alerts that allow for a support team member to connect with a client. Rapture also provides a number of extension points that may be linked with payments. The entitlements framework can be used to manage access to certain services and datasets based on subscription tier. Because all system activity is automatically logged, producing usage reports and using this data to inform customer segmentation and pricing analysis becomes a quick task.

 

V. The Mechanics
Incapture’s dev portal uses an Angular front-end and an API server built on the Rapture platform. For most apps, Reflex is the scripting language we employ to tap into Rapture’s powerful service framework mechanism: a service endpoint written in Reflex is the medium that the front-end and server use to talk to each other. Stripe has a RESTful API and Reflex leverages the entire platform API — including the ability to handle HTTP request and response objects. The result? A fully-functional Stripe app built really quickly!

Let’s take a look at the example of creating a Stripe customer object.

 

Flow diagram for creating a Stripe customer object

Fig.3. Flow diagram for creating a Stripe customer object

 

From the Subscription page, following the ‘Subscribe’ button click, we present the Stripe Checkout modal to collect a customer’s card details. After submitting the Checkout form, if everything checks out, Stripe returns a token ID that should be used to create a new customer object.

This line in our Angular controller invokes the createSubscription Reflex script (remember, creating a customer is actually a step encountered while creating a subscription for the very first time):
paymentService.createSubscription(createCustomer, token.id, token.email, planId, envName)
(The first argument is a flag that is set to true or false depending on the use case.)

Moving on to the Reflex part..
An important aspect of Reflex is that we can call one script from another. So, in our main script that contains the core logic (that follows the flow of creating a subscription), we call another script that makes the Stripe API call to create a customer object.
(This separation of core logic from vendor-specific API calls will also make it really easy to update scripts if we decide to switch to another payment platform in the future.)

stripeCreateCustomer = fromjson(#script.runScript("script://curtis/stripe_createCustomer",
                                 {'token': token, 'email': email, 'planId': planId}));

(email and planId are optional arguments.)

The stripe_createCustomer script itself is this:

response = {};
 
import HttpData as http;
 
headers = {};
headers["Authorization"] = "Bearer " + ENV['STRIPE_SK'];
 
url = "https://api.stripe.com/v1/customers";
 
params = {};
params["source"] = token;
params["description"] = "First plan: " + planId;
params["email"] = email;
 
urlwithparams = $http.uriBuilder(url,params);
 
stripeResponse = $http.get(urlwithparams, "POST", null, "JSON", headers);
 
if (stripeResponse.error == null) do
     response = stripeResponse;
else do
     response.error = stripeResponse.error;
end
 
return json(response);

(Reflex has a number of built-in functions and special operators — e.g. ENV[…] — that are semantic shortcuts when interacting with Rapture . More power to you!)

Importing the HttpData module into the script gives us the ability to make REST calls with support for HTTP POST, GET, DELETE etc.

On successful creation, Stripe returns a customer object in its response. The onus of processing what is required falls on the caller Reflex script. In this case, we are only interested in the customerId value; so, we retrieve it from the response and store it in our database. (customerId is what we use to get a customer’s Stripe-related info — including determining whether a customer has already subscribed to a plan and, therefore, not asking for their payment details again.)
Further processing can specify what should be sent to the front-end JavaScript code (e.g. feedback).


Creating web apps that integrate with third-party services is a breeze when built with the Rapture-Reflex-Angular stack! In a later post, we’ll explore how to make Stripe’s webhooks talk to our dev portal and Slack.


Subscribe for updates