Introduction to Stripe payment gateway

Huynh Phan
5 min readJul 5, 2020
Card Payment

Hi guys, this is my first blog of writing something.

I’ve never been worked with Stripe before until my current project. I did some researchs and I’ve just finished integration in test environment and waiting to deploy and use live-mode keys. That’s why I want to write about this to summarize my knowledge about Stripe.

As you reading this blog, I assume you are seeking knowledge or troubleshooting issues with Stripe and have known what Stripe is.

To be very brief, Stripe is a third party to handle payment for our application.

Stripe has many payment services, you can refer here. In this blog I will focus on their most popular one, Connect to accept a payment.

According to Stripe document,

Connect is a powerful API and set of tools used to route payments between a business, customers, and recipients who need to get paid.

Sounds matching your business? Let’s go ahead.

“So if I want to integrate Stripe, where should I start?”

There are something you should know before getting started.

There are 3 types of accounts:

  1. Standard: take the least effort to integrate and administrate. There are also no platform fees. Best for applications like Shopify where buyers transact directly with sellers.
  2. Custom: you have total control over the user experience. Takes time to set up and requires extensive development resources. Best for large retail marketplaces that process transactions like Amazon. Fees apply.
  3. Express: a hybrid option that allows platform owners to customize some aspects while Stripe takes care of onboarding, verification and account management. Quicker to implement. Platform fees apply.

There are 3 type of charges: Direct charges, Destination charges and Separate charges and transfers

  1. Direct charges: recommended for standard account where buyers transact directly with the seller’s account. Sellers are therefore responsible for Stripe fees, refunds, and chargebacks.
  2. Destination charges: recommended for express and custom account where buyers transact with the platform, but products or services are delivered by the seller account. Net payments (after deduction of commission or transaction fees) are automatically allocated to seller accounts. In this scenario, your platform account is responsible for and manages the Stripe fees, refunds and chargebacks on behalf of the seller accounts.
  3. Separate charges and transfers: you have more control over the payment flow. You can delay the payment, change the transferred amount, …

The first thing you should do is to determine what kind of your business is. If your application sells products for one merchant only, Standard is your choice. If it is a platform where many merchants put their products on, Express or Custom is for you.

Payment APIs: Charges API and Payment Intents API

To be brief, there are currently 2 strategies to finish a payment:

  1. Charges API (the older one, not recommended, but you still can find some instructions using this one).
  2. Payment Intents API. Stripe recommends using this one.

For further comparison, you can refer this

Working Flow

Now let’s get into steps to finish integration.

Connect Account

If you want your sellers to receive funds, you must sign up Stripe for your platform with their card data being managed by Stripe.

In order to do that, you must build up 2 kind of redirect URIs:

1. Our Redirect Uri: After user successfully signup Stripe, they will be redirect to that uri with 2 parameters code (used to retrieve Stripe authorization for the account) and state (will be described below). So our server must write this GET handler with checking state, authorize user with code and storing necessary Stripe account data.

Add redirect URI

2. Stripe Redirect Uri: This is the Stripe form user uses to signup their account with the following format:

https://connect.stripe.com/express/oauth/authorize?client_id={your_client_id}&state={state}&suggested_capabilities[]=transfers&stripe_user[email]=user@example.com

where:

  • your_client_id: can be found in the dashboard under Settings -> Connect
  • state: Stripe recommends using this as csrf token but I use that for both csrf token and user id (metadata) separated by underscore.
  • suggested_capabilities: define what capability your connected account is allowed to do. In our case, we want our connected account receiving payments, which is transfers.
  • stripe_user: use this to prefill any information for your user in Stripe form.

More parameters can be found here.

This is our form looks like

After an account is connected on your platform, you can see them in Connected accounts tab in Dashboard. We can view their account and balances.

Connected Accounts

Accept Payment

After an account connected to your platform, they now can receive payment. I will use destination charges to demonstrate.

1. Server: Create payment indent

  • The payment indent object tells the detail of a transaction: amount, receiver (account destination), currency, application fees.
  • Stripe fee for a transaction is 2.9% + 30 cents (usd currency) in the time of writing this. So you must calculate. This is an example for this fee model.
Stripe fund flow example

2. Client: setup payment form using Stripe Elements

  • Strip Elements is set of prebuilt elements which can be embedded to our application as iframe to collect user card data in a secured PCI compliance way.
  • Client use client_secret in payment intent object created from step 1 to submit payment.

3. Server: setup Webhook for Stripe to call after success payment

  • Write a POST handler API that Stripe will call. Take a note about body parser with this endpoint
// Use JSON parser for all non-webhook routes
app.use((req, res, next) => {
if (req.originalUrl === "/webhook") {
next();
} else {
bodyParser.json()(req, res, next);
}
});
// const webhook_secret = 'whsec_...''app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
const sig = request.headers['stripe-signature'];

let event;

// Verify webhook signature and extract the event.
// See https://stripe.com/docs/webhooks/signatures for more information.
try {
event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret);
} catch (err) {
return response.status(400).send(`Webhook Error: ${err.message}`);
}

if (event.type === 'payment_intent.succeeded') {
const paymentIntent = event.data.object;
handleSuccessfulPaymentIntent(paymentIntent);
}

response.json({received: true});
});
  • When we receive this request with event.type is payment_intennt.succeeded, it means our customer has successfully done the payment. We should buy services or products for them then.
  • Configure this webhook endpoint in dashboard settings under Developers -> Webhooks.
  • In the snippet above, there is webhook_secret variable, you can get this secret after configuring webhook.
webhook_secret

And that’s all about Stripe that I have integrated so far. Thank you for your reading.

--

--

Huynh Phan

A Software Engineer. Enthusiasted by challenges, performances, high scale systems.