Vexor

Marketplaces

Marketplaces enable you to process payments from multiple vendors as the marketplace owner. Sellers can easily connect their payment gateway accounts to your application and begin selling their products or services. This is an advanced payments processing topic since it involves managing payment authorizations, refunds, captures, and other sensitive payment-related operations across multiple vendors, where you are responsible for facilitating money movement. In this guide, you'll learn how to create a basic marketplace that handles common use cases without dealing directly with payment gateway complexities or worrying about security and authentication tasks. Once comfortable with the basics, you can extend your implementation to handle more complex scenarios.

What you'll learn

  • How to create a basic marketplace application
  • How to allow sellers to connect their payment gateway accounts to your marketplace
  • How to handle payments to multiple vendors and take a percentage of the sales
  • How to handle webhooks
  • How to handle refunds from multiple vendors

What you'll build

As marketplaces are complex applications, we will provide a basic marketplace application already built that allows sellers to connect their payment gateway accounts to your marketplace and begin selling their products or services.

This will be a better approach than just showing you the code, we will also explain the logic behind it.

By the end of this guide, you will have a marketplace application that looks like this:

home og image

Let's get started! 🚀

We will create this application using Next.js following these 10 steps:

Create the UI for the marketplace

Repository

Clone the repo:

git clone https://github.com/Vectrals-Software/vexor-marketplace-nextjs.git

As said in the introduction, to focus only on the marketplace logic, we will clone a repo with a basic UI and authentication logic (without third party platforms 😎) already built.

Dependencies

Install the dependencies and run the app. Open your project with your favorite code editor and run the following commands in the terminal:

npm install && npm run dev

In your browser, you should see the following screen:

home og image

Notice that you will see some warnings and errors in the terminal about the missing environment variables, we will fix that in the next steps.

Environment variables

This project comes with authentication already setup, for that we need to store the users in a database and make use of OAuth providers. Also we need to setup Resend to send emails to the users (2FA email verification, password reset, etc).

First, create a .env file in the root of the project and copy the content of the .env.example file to it.

Database

In this example we will use MongoDB but you can use any other database you want. We need a database to store the vendors and their payment gateway accounts.

Login to MongoDB Atlas and create a new database for this project. Once you have your database, you should have a connection string like this:

mongodb+srv://<database-username>:<database-password>@cluster.abc123.mongodb.net/<project-name>

Paste this connection string in the .env file in the DATABASE_URL variable.

DATABASE_URL="your-database-connection-string"

Authentication

This project comes with authentication already setup, for that we've used NextAuth.js. This way we don't use any third party platforms and we can handle the authentication logic ourselves.

Don't get us wrong - platforms like Clerk, Firebase, and Kinde are fantastic solutions! Feel free to use any of these excellent platforms in your own projects and adapt our code accordingly.

There are some variables in the .env file that you need to setup:

AUTH_SECRET="" // A secret key used to verify the integrity of the authentication token. 
// You can generate a random key with `openssl rand -base64 32` or come up with your own. 
// It's just a random string.
AUTH_GOOGLE_ID="" // The Google ID for the Google authentication provider.
AUTH_GOOGLE_SECRET="" // The Google secret for the Google authentication provider.
AUTH_GITHUB_ID="" // The GitHub ID for the GitHub authentication provider.
AUTH_GITHUB_SECRET="" // The GitHub secret for the GitHub authentication provider.

See NextAuth.js providers documentation for more information about the authentication providers and how to get the credentials.

Mailing

We need to setup Resend -recommended- to send emails to the users (2FA email verification, password reset, etc).

Login to Resend and create a new account. Once you have your account, you should have an API key, paste this in the .env file in the RESEND_API_KEY variable. If you have configured a domain in Resend, you can use it in the MAILING_DOMAIN environment variable.

RESEND_API_KEY="your-resend-api-key"
MAILING_DOMAIN="your-mailing-domain.com"

App URL

In the .env file, set the NEXT_PUBLIC_APP_URL variable to the URL of your application. For now we'll just use http://localhost:3000. We'll change this later when we deploy the application.

(Take into account that you'll need to add this URL to the Allowed URLs -or similar- in the authentication providers).

NEXT_PUBLIC_APP_URL="http://localhost:3000"

Vexor

In the .env file, set the NEXT_PUBLIC_VEXOR_PROJECT, NEXT_PUBLIC_VEXOR_PUBLISHABLE_KEY and VEXOR_SECRET_KEY variables to the project ID, publishable key and secret key you got from your Vexor dashboard.

NEXT_PUBLIC_VEXOR_PROJECT="your-project-id"
NEXT_PUBLIC_VEXOR_PUBLISHABLE_KEY="your-publishable-key"
VEXOR_SECRET_KEY="your-secret-key"

Marketplaces integration is an advanced topic, so we assume that you already know how to create a project in Vexor and get the credentials. If not you can follow the Checkout guide to learn how to create a project and get the credentials and get familiar with the Vexor SDK.

Credentials

Credentials are the way to connect your marketplace with the payment gateways. Currently we support Stripe and MercadoPago for marketplaces.

Get the credentials

We assume you already have an account created within Stripe and that you understand how to setup and differentiate between sandbox and production configurations. If not, you can read more here.

  1. Go to your Stripe dashboard and select the account you want to use.
  2. Go to Developers > API Keys and click on API Keys.
  3. Copy the Publishable Key and Secret Key and paste them in the corresponding fields in the Vexor dashboard in the Project details. We'll do this in the next step.

As you can see in the video, we have selected Sandbox as the environment (a sandbox account). So our Vexor project will use the sandbox credentials for Stripe. If you select Production you should use the production credentials for Stripe.

Add the credentials

Go to your Vexor dashboard and select the project you created for this marketplace.

  • In the Project details, add the credentials for the payment gateway you want to use.

For this example we'll add both Stripe and MercadoPago credentials. So we can use both payment gateways in our marketplace application.

Application URL

We need to setup a public URL for the marketplace application. This is the URL that the payment gateways will use to send webhooks to the marketplace application.

Also MercadoPago needs the redirect URLs to be added in the application details as authorized redirects.

In this step we'll create the application URLs, add the additional configuration in the MercadoPago application and configure the webhooks in both Stripe and MercadoPago.

Create the public URL

In production environments, you can set the webhook directly as your domain. For example, if you have a domain https://my-app.com, you can set the webhook URL to https://my-app.com/api/webhooks or any other route you want.

In development environments, webhooks cannot be set to make a request to localhost, so you need to set the webhook URL to a public URL. In this case, you can use ngrok, cloudflared or any other tunneling service to create a public URL for your local development environment.

In this example, we will create a public URL for our local development environment using cloudflared. Again, if you are working on a production environment, you can skip this step since you will use your production domain instead.

You need to install ngrok or cloudflared to use tunnels. You can find more information about how to install cloudflared for this example here.

You can also deploy the application to a platform like Vercel and use the domain provided by the platform as the public URL.

Assuming you're working on a local development environment in http://localhost:3000, run the following command in your terminal to create a public URL:

cloudflared tunnel --url http://localhost:3000

This will create a public URL and print it in the terminal. Copy that URL, it will be used in the next step.

Add URL to MercadoPago

This step is only needed if you want to use MercadoPago in your marketplace.

Mercadopago requires the URLs to be added in the application details as authorized redirects. If you pay attention to the code, in the src/actions/seller/connect-account.ts file you'll see that we redirect the user to the following URL: ${APP_DOMAIN}/sell/connect-mercadopago.

// src/actions/seller/connect-account.ts
 
 const redirectUrl = gatewayId === 'mercadopago' ? 
    `${APP_DOMAIN}/sell/connect-mercadopago` : 
    `${APP_DOMAIN}/sell`

This is the URL we need to add in the MercadoPago application. Where ${APP_DOMAIN} is the public URL we created in the previous step.

Configure webhooks

In our project structure we have a src/api/webhooks folder that contains the webhooks handler for the marketplace. So the endpoint we need to set in the payment gateway is ${APP_DOMAIN}/api/webhooks.

We'll configure this in both Stripe and MercadoPago in the following steps.

If you need more information about webhooks, you can read the Webhooks guide. Here we'll just show how to set the webhook URL in the payment gateways for this example.

We'll need two types of webhooks:

  • One webhook to know when a seller has connected their account.
  • Another webhook to know when a payment is successful.

We're almost done with the setup! Just one more step to go.

Add the webhooks to the project in the Vexor dashboard.

That's it for the setup! 😮‍💨

Now let's go to the fun part! 😁

Test the application

If for any reason the URL you created in the previous step is not available anymore and you need to create a new one, remember that you'll need to update the URL configuration for webhooks in the payment gateways (and for MercadoPago, the authorized redirects in the application details).

Set the app domain

In the .env file, set the NEXT_PUBLIC_APP_URL variable to the URL we created in the previous steps.

For example:

NEXT_PUBLIC_APP_URL="broader-scene-lewis-phpbb.trycloudflare.com"

Create a seller account

Visit the application with the URL you created in the previous steps (Don't use localhost!!!) and register a new user in the application. This user will be the seller.

Connect a payment gateway account

Login with the seller account you created in the previous step and connect a payment gateway account.

These are the files that handle the connection to the payment gateways:

The frontend code that handles the connection to the payment gateways is in the src/components/seller/connect-account.ts file:

This component is imported in the src/app/sell/page.tsx file:

The connect-account.ts component is making use of the connectAccount action that is defined in the src/actions/seller/connect-account.ts file:

Create a customer account

Open the application in a new incognito tab/window (or another browser) and register a new user in the application. This user will be the customer.

Make a purchase

Login with the customer account you created in the previous step and make a purchase of the seller's product.

These are the files that handle the purchase:

In the src/app/buy/page.tsx file you can see the code that imports the AllProducts component. This component is in charge of showing all the products available for purchase.

The AllProducts component is in charge of fetching the products from the database and displaying them to the user.

As you can see, each product has a BuyProductBtn component that is in charge of handling the purchase of the product.

The code responsible for handling the purchase is in the buyProduct action that is defined in the src/actions/products/buy-product.ts file.

Handle refunds

Let's go back to the seller's account and handle a refund. This applies to both payment gateways.

These are the files that handle the refund:

As seller, you can see your sales in the /my-sales page. This page is defined in the src/app/my-sales/page.tsx file:

This page imports the MySales component that is in charge of fetching the sales from the database and displaying them to the user.

Each sale item has a RefundOrderButton component that is in charge of handling the refund of the sale. This component is defined in the src/components/orders/refund-order-btn.tsx file:

This component is in charge of handling the refund of the sale. The logic to handle the refund is in the refundOrder action that is defined in the src/actions/orders/refund-order.ts file.

Congratulations! 🎉

You have now a fully functional marketplace with Vexor. You can now adjust the marketplace to your needs and build an amazing multi-vendor platform.

You can charge fees based on the sale amount, or even a fixed fee per sale. See the vexor.connect.pay() SDK reference for more information.

With stripe, you can also support the express integration, which lets you sellers to access their stripe dashboard to track their sales and payouts. You can read more about it in the vexor.connect.stripe() section. And if you need more information about how Stripe Express works, you can read more about it in the Stripe Express documentation.

Support

Need help implementing your marketplace?

Our team and community are eager to support you with your integration. We recognize that every marketplace is unique, and we're committed to assisting you at every stage of the process.

On this page