How to Integrate Stripe Connect with Your Marketplace for C&C Payments?

How to Integrate Stripe Connect with Your Marketplace for C&C Payments?

Stripe Connect is one of the most popular and dynamic payment systems that pays out sellers in over 30+countries worldwide. Stripe has 14 global offices, supports multi-vendor, ticketing, or on-demand marketplaces and eCommerce platforms all over the world.

Importance of proper payments system evaluation

Here at Apiko, we’ve already covered this payment engine in the Payment System Integration article, as an insanely powerful and easily integrated solution.

When developing a marketplace app, a lot of focus goes on the homepage and design — it’s the first thing that visitors see when they arrive. Besides, don’t miss out on a proper payment system evaluation, since that’s the milestone of marketplace app structure.

It has to be user-friendly, time and cost-effective, professional-looking and reliable enough to manage dozens of transactions on a daily basis.

What is Stripe Connect?

Stripe Connect is a payment gateway for authorizing transactions of eBusinesses, online retails and different types of marketplaces. It processes tons of confidential data, like credit card numbers, personal data, payment history, etc.

From the integration point of view, Stripe is a widely well-known solution, that involves exhaustive documentation, see-through workflow, and highly productive capacity utilization.

Our data-driven research allows concluding that Stripe Connect is a perfect fit to manage payments on your project, especially when it comes to marketplace apps.

Stripe Connect is successfully used by numerous eCommerce A-listers, like Lyft, Shopify, Woocommerce, Kickstarter, etc. Depending on their functional peculiarities, all these solutions have specific features of using Stripe (discover the list of Stripe’s customers for more info).

Stripe Connect pricing

And just a heads-up - this payment gateway isn’t free. Pricing options are two-fold: fixed price for the integrated solution (2.9% + 30¢ per successful card charge) or customized plan available for businesses with large payment volume or unique business models.

This fee is the same for all cards, such as Visa, MasterCard, Maestro, AmericanExpress, Discover, JCB, ApplePay, etc.

Generally, Stripe provides users with a flexible, pay-as-you-go pricing. Moreover, all Stripe’s customers get 100+ out of the box features with its integrated per-transaction pricing.

Bear in mind, that integrated pricing means no setup fees or monthly fees. There are a few additional charges, though, including the payments outlined below:

  1. Instant payouts. Instant Payouts lets you access funds in a blink of an eye using an eligible debit card, right from the Dashboard and requires 1% extra payment.
  2. International payments. An additional 1% fee will be applied if currency conversion takes place.
  3. Premium support service. The price starts at $1,800 per month. A customized support plan includes personalized optimization, emergency support for critical issues and a dedicated support manager aimed to address your concerns and provide technical assistance in a heartbeat.

What account types does Stripe have to offer?

You need to create this account (known as a connected account) for each user that receives or sends money on your marketplace. These accounts are generally created when a user signs up for your platform. The type of accounts you create influence and define who is responsible for chargebacks, user support, etc.

First, let’s choose the best account type, that will work with the marketplace app swiftly and securely. Stripe Connect offers 3 account types, including Standard, Express, Custom.

Let’s dive into these three account types and their use cases:

  1. Standard - it’s a so-called conventional Stripe account, directly held by its owner (your platform’s user). It’s mostly preferred by those who want to use direct charges and don’t need full control over users’ experience. Customers who run a Standard account can easily log in to the Dashboard, manage payments on their own, connect this account to other platforms or disconnect it from your marketplace.
  2. An Express Stripe Account provides holders with access to a minimal 2-paged Dashboard that allows managing users’ personal information and payouts to their bank. Besides, this option lets Stripe handle account onboarding, management, and identity verification and guarantees you significant control over clients’ experience.
  3. A Custom Stripe Account offers you - the marketplace owner - collect any information you need and be completely responsible for all interactions with a user. Custom account holders do not have access to a Stripe Dashboard, and Stripe will not contact them directly.

In our particular case, Express Stripe Account is the best example for this guide, as due to the peculiarities, this type is quite user-friendly and can be launched very quickly in a heartbeat.

Speaking about the marketplace app, the target audience is twofold: customers and retailers, contractors or wholesalers (although, both of them can switch between these groups).

Let’s jump to the step by step guide for a better understanding of how to manage payment, that was made by a client. Now we have to retransfer the money to another platform and freeze it before the customer gets the order. After that, we can remove the commission according to the tariffs and send the payment to an initial recipient - a retailer.

How to test Stripe payments?

This guide is focused on the marketplace app, built with React Native. Let’s find out how to use Stripe Connect for C&C payments smoothly and accurately via mobile application.

The first step that’s required to start managing payments is to create a registration page, where customers would be able to insert their credit card details.

We’ll use Tipsi-Stripe library as it works perfectly with React Native:

Stripe empowers you to create a Secret Token for a credit card through the API. A token is an identification number, you need for running Stripe operations.

First of all, you should set up the API key, given by Stripe for a customer. Log in to your Dashboard, move to Get your test API keys section and copy a Publis hable key.

stripe payments

After connecting Tipsi-Stripe to the project, you have to authorize it with a Publishable key. Import Tipsi-Stripe and add this code in an index.js file.

stripe.setOptions({
    publishableKey: "pk_test_IWY5RxT3RCx2lWhKL3564wby00TeUso122",
});

To create a credit card token a user have to insert Number, ExpMonth, ExpYear, CVC. Once the data is provided, use the following method from the library.

stripe payments

Then you get a credit card token and can link it to the user’s Stripe account on your marketplace app. This account will be identified as a Customer, so you will be able to find it by clicking on the Customers category (bootstrap sidebar on your Dashboard).

You can connect this Customer Account to a particular credit card using Stripe API on the backend. For instance, we use NodeJS and ExpressJS framework and can find all necessary information in the Stripe-Node library.

If you opt for any other programming language for backend development (Ruby, Python, PHP, GO, DotNet), Stripe has 136 repositories available devoted to various projects, so you’re more than welcome to follow their code on GitHub.

Create the endpoint on your server for merging the Customer Account with payment details.

import { Router } from 'express';
import { addCard } from './addCard';

export const paymentsRouter = Router();

paymentsRouter.post(
    '/add-card',
    (req, res, next) =>
        addCard(req)
            .then(data => res.json(data))          
            .catch(next),
);

We’ll get the following code:

import { createCustomer, addCustomerCard } from '../../libs/stripe'; 
import { User } from '../../models/users';

export const addCard = async ({ user, body: { cardToken } }) => {
    if (!user.stripeCustomerId) {
        const stripeCustomerId = await createCustomer(user.email);
        
        await User.findOneAndUpdate(
            { _id: user._id },
            { $set: { stripeCustomerId } },
        );
        
        return addCustomerCard(stripeCustomerId, cardToken);
    }
    
    return addCustomerCard(user.stripeCustomerId, cardToken);
};  

Let’s dive deeper into the createCustomer and addCustomerCard functions. In the Stripe-Node library, we create a dedicated /libs/stripe folder that contains index.js file. Here we’ll initialize the Stripe client for backend and insert the following functions from the library.

import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export const createCustomer = email =>
    stripe
        .customers
        .create({ email })
        .then(({ id }) => id);

export const addCustomerCard = (stripeCustomerId, stripeToken) =>
    stripe
           .customers
           .createSource(stripeCustomerId, {
                source: stripeToken,
	        });

As for addCard function, first make sure that a user, who adds a credit card, is already enrolled on your platform as a customer. If it isn’t, use the appropriate function from Stripe-Node library. Next, use the function for merging credit card details with an appropriate user via a secret token. Having done these actions, you get a unique Stripe identification number, that’s to be entered into the customer model using MongoDB model.

import { Schema } from 'mongoose';

export const UserSchema = new Schema({
    fullName: { type: String, trim: true },
    photo: String,
    email: { type: String, trim: true },
    stripeCustomerId: String,
    createdAt: {
        type: Date,
        default: Date.now,
    },
});

If dealing with an existing customer, just skip two previous steps and link a credit card.

Now you can connect all available credit cards to a user profile, by means of new endpoint:

paymentsRouter.get(
    '/get-cards', 
    (req, res, next) =>
        getCards(req)
            .then(data => res.json(data))
            .catch(next),
);

Here’s the getCards function:

import { listCustomerCards } from '../../libs/stripe';

export const getCards = async ({ user }) => {
    if (!user.stripeCustomerId) return [];
    
    return listCustomerCards(user.stripeCustomerId);
};

Next, use the listCustomerCards function from Stripe-Node:

export const listCustomerCards = stripeCustomerId =>
    stripe
        .customers
        .listCards(stripeCustomerId);

All the steps, outlined above, are used for empowering Buyers to process a payment, keep reading to find out how to use identification numbers for transactions.

Let’s move on to the Seller flow, as we’ve chosen Express Stripe account. Now you have to display data, provided by Stripe, as so-called onboarding webpages. For this reason, use a React Native WebView component and create My Balance page to show payment history, current payouts status, and the button, by clicking on which customers could open this window and provide all necessary credentials. Once it’s done, you can add a client to your Stripe platform as a Connected User.

stripe payments
stripe payments

To get these pages created, insert an appropriate URL from Stripe documentation into the following WebView component:

const STRIPE_URL = 'https://connect.stripe.com/express/oauth/authorize?redirect_uri=https://stripe.com/connect/default/oauth/test&client_id=ca_EML9A3iznTRa21sGGiEam3WkP3CcVtfrs';

<WebView
    source={{ uri: STRIPE_URL }}
    startInLoadingState
    scalesPageToFit
    javaScriptEnabled
    bounces={false}
    onNavigationStateChange={({ navState }) => onWebViewStateChange(navState)}
    javaScriptEnabledAndroid
/>

Now, if a user clicks on the Connect Stripe button, the WebView componet will be shown. Here are the screens of data your customers will see.

stripe payments
stripe payments
stripe payments

Having completed all needed fields with required data, clients finish the registration and leave a unique code in the URL’s parameters. To get this code, you should use an onNavigationStateChange requisite in a WebView and enter the onWebViewStateChange function there.

onWebViewStateChange(navState) {
    if (navState.url.includes('?code=')) {
        this.props.setCode(navState.url.split('?code=')[1]);
        this.props.onToggleVisibleRegisterModal(false);
        this.props.onSuccess();
    }
},

Once you receive this code and set the data strusture in React’s state, run the onSuccess function:

async onSuccess() {
    try {
        this.props.setIsLoading(true);
        
        const { data: { stripeAccountId } } = await api.createAccount(props.code());
        await this.props.editProfile({ stripeAccountId });

        this.props.setIsLoading(false);
        this.props.getData();
    } catch (err) {
        this.props.setIsLoading(false);
        alertError(err);
    }
},

This code make a createAccount request, so while it’s been running the loading bar is shown on the screen.

The endpoint createAccount code:

paymentsRouter.post(
    '/create-account',
    (req, res, next) =>
        connectAccount(req)
            .then(data => res.json(data))
            .catch(next),
);

connectAccount function:

import { createConnectedAccount } from '../../libs/stripe';
import { User } from '../../models/users';

export const connectAccount = async ({ user, body: { authorizationCode } }) => {
    const { data: { stripe_user_id } } = await createConnectedAccount(authorizationCode);
    
    await User.findOneAndUpdate(
       { _id: user._id },
       { $set: { stripeAccountId: stripe_user_id } },
    );
    
    return { stripeAccountId: stripe_user_id };
};

The connectAccount function sends that received code to createConnectedAccount function, where you can create the request through Axios. Thus, you can connect newly registered customers to your Stripe platform and add Stripe identification number to the particular user model.

export const createConnectedAccount = authorizationCode =>
    axios.post(STRIPE_TOKEN_URI, {
        client_secret: process.env.STRIPE_SECRET_KEY,
        code: authorizationCode,
        grant_type: 'authorization_code',
    });

Then, you’ll get and set necessary data structure via getData function, for example balance history.

async getData() {
    if (!this.props.user.stripeAccountId) return;
    
    this.props.setIsLoading(true);
    
    const result = await Promise.all([
        api.getBalance(),
        api.checkPayoutsStatus(this.props.user.stripeAccountId),
    ]);
    
    this.props.setPendingBalance(result[0].data.pending);
    this.props.setPayoutsEnable(result[1].data);
    this.props.setIsLoading(false);
},

Create two endpoints for getting payments and checking a transaction status and permissions for funds withdrawal.

paymentsRouter.get(
    '/get-balance',
    (req, res, next) =>
        getBalance(req.user.stripeAccountId)
            .then(data => res.json(data)
            .catch(next),
);

paymentsRouter.post(
    '/check-payouts-status',
    (req, res, next) =>
        customerDetails(req.body.stripeAccountId)
            .then(({ payouts_enabled }) => res.json(payouts_enabled))
            .catch(next),
);




export const getBalance = async (stripeAccountId) => {
    if (!stripeAccountId) return null;
    return stripe
        .balance
        .retrieve({ stripe_account: stripeAccountId })
        .then(({ pending }) => (
            {
                pending: pending[0].amount,
            }
        ));
};



export const customerDetails = stripeAccountId =>
    stripe
        .accounts
        .retrieve(stripeAccountId);

After that, Open Stripe button is shown on the My Balance screen. When users tap on this button new WebView, containing all account data, will be displayed.

stripe webview elements
stripe payments

Generate this Webview link on the backend, create a particular endpoint and use the following function from the Stripe-Node library:

paymentsRouter.get(
    '/create-login-link',
    withAuthUser,
    (req, res, next) =>
        createLoginLink(req.user.stripeAccountId)
            .then(data => res.json(data))
            .catch(next),
);

And next one:

export const createLoginLink = stripeAccountId =>
    stripe
        .accounts
        .createLoginLink(stripeAccountId)
        .then(({ url }) => url);

How does Stripe work from a vendor's perspective?

For implementing our target payments flow you have to use two functions from Stripe-Node library, outlined below.

The first one conducts financial transactions from buyers’ credit cards to the platform’s balance.

export const createCharges = ({ amount, stripeCustomerId, cardId }) =>
    stripe.charges.create({
        amount,
        currency: 'usd',
        customer: stripeCustomerId,
        source: cardId,
    });
const charge = await createCharges({
        amount: goodsPrice,
        stripeCustomerId: buyer.stripeCustomerId,
        cardId: buyerCardId,
     });

For more info concerning this function, explore the link.

Use it on the backend for the event of buying products. Fulfill it with all needed information, such as product pricing, identification number of the seller’s account and connected credit card.

If payment is successful, you can find it in your Stripe Dashboard.

stripe payments

Once a customer receives the order, the money will be transferred to the seller’s account. For this reason, use the following function from the Strip-Node library.

export const createTransfer = (amount, stripeChargeId, stripeAccountId) => {
stripe
    .transfers
    .create({
        amount,
        currency: 'usd',
        source_transaction: stripeChargeId,
        destination: stripeAccountId,
    });
};

This function contains these parameters:

  1. amount - how much money you have to pay

  2. stripeAccountId- seller’s identification number in Stripe

  3. stripeChargeId - the id code of transaction.

Stripe dashboard: How long does it take to integrate Stripe Connect?

Making conclusion, let’s explore the Stripe dashboard and highlight the most crucial categories you may find there.

The dashboard contains all needed information, associated with your marketplace app. Via clicking on the Balance section you can see the current balance of your platform. This category involves the Transactions subsection, that stores all payments conducted through your platform. From a programmers’ point of view, we can strongly recommend using a Developer menu, where you can find the backlogs of all previous transactions, associated with our platform, and perform various operations with API keys.