Payments for Marketplace Apps using Stripe Connect | Stories from Offthreadr

Ankur Datta
4 min readMar 25, 2024

--

The classic tutorial for payments using stripe pictures a subscription app, which has 2 simple components.

  • The customer proceeds to click the buy now button. You(dev) create a checkout session. Also, handle routing from the checkout page.
  • Add a webhook event handler to handle payment events such as, on successful completion of payment: add user to the premium tier.

Easy right?

While building offthreadr, this clear picture soon turned cloudy, as the payments needed to be transferred to course-owners instead of our stripe account. Furthermore, each course is a different product!

In this post, I write about stripe-connect, a less explored; beautiful product from stripe. I’ve also provided snippets in typescript, used in my nextjs app.

Offthreadr.com is an AI-powered course platform which enables learning on the go with snippets delivered directly to your email!

What’s more?

  • get your questions answered in seconds with course-AI
  • participate on in-platform community to network with peers!
Do checkout offthreadr-AI

Here’s the breakdown of the scenario:

  1. A course owner can sell as many courses. For each course sold, the course fee should get directly credited to the course owner. As offthreadr offers a 0-commission lifetime deal(atleast now).
  2. When the course owner makes the course public, a stripe-product should get created with metadata specific to the course like course-name, related assets.
  3. When a student needs to complete payment to enroll to the course, the checkout session for that particular course needs to be created.
  4. Enroll student to the course, on successful payment.

The scenario seems pretty fine. Except linking the course owner’s account. That’s where stripe connect comes into light.

Linking Stripe Account of Seller

Stripe connect, enables creation of express accounts for sellers on the marketplace: the seller can link their bank account to the express account created; such that payouts for their sales can be made directly to their bank account.


const account = await stripe.accounts.create({
type: "express",
email,
metadata: {
adminId,
},
});

The id from account object needs to be persisted to identify the seller’s stripe account.

✅ Step 1: Linking Stripe account

Creation of Product

Its good to know the terms associated with stripe product

  • A product is a tangible item which is sold by a seller. It is a course in this scenario which has properties like, name, description, url, etc.
  • A price object represents price of the product, in a specific currency.
  • Thus, a product can be associated with a bunch of prices. It also has a default price-object associated with it.

Stripe provides APIs to create products and price, such that it can be integrated with ecomm apps.

So, whenever the seller(course owner) makes the course public, a product and a price is created. I’ve used a single USD price.

Here’s a code snippet where a new price is created for an existing product.

 const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2023-10-16",
});

const price = await stripe.prices.create({
currency: "usd",
unit_amount: usd * 100,
product: productId,
active: isActive,
});

const product = await stripe.products.update(productId, {
name: courseName,
description: description,
url: `https://offthreadr.com/c/${creatorSlug}/${courseSlug}`,
default_price: price.id,
active: isActive,
});

The productId obtained form product object needs to be persisted which could be used for checkout.

✅ Step 1: Linking Stripe account.

✅ Step 2: Using Stripe API to create products.

Handling checkout

You might be asking:

  • We are not specifying that the product belongs to a specific stripe account
  • Where are we specifying that the course belongs to the particular seller?

Well, that’s handled by the checkout data. During checkout, we specify a field, payment_intent_data which describes the destination stripe account.

  const priceId = course.priceId;
const destinationAccountId = course.creator.stripeAccountId;

const session = await stripe.checkout.sessions.create({
mode: "payment",
line_items: [
{
price: priceId,
quantity: 1,
},
],
payment_intent_data: {
transfer_data: {
destination: destinationAccountId,
},
},
metadata: {
userId,
courseId,
},
success_url
cancel_url
});

✅ Step 1: Linking Stripe account.

✅ Step 2: Using Stripe API to create products.

✅ Step 3: Handling Checkout.

The next step, is creating webhook-listeners to add enroll user to the course on successfull completion of payment. There are tons of medium articles about that, so I’m not gonna detail about that :)

There you have it! Enabling marketplaces with stripe-connect is that easy!

Have a great day :)

I’m Ankur Datta, I write about my side-projects and hurdles I faced while building them. Follow me on X, linkedin & visit offthreadr.com!

--

--

Ankur Datta
Ankur Datta

Written by Ankur Datta

I'm a biz+tech nerd! I write about hurdles I came across while building personal and freelance projects!

Responses (1)