← Square
Guide

How to build a ticketing marketplace on Stripe Connect and Square

By Alastair Murdoch Last reviewed Tested on Stripe .NET library 51 · Square .NET SDK 43 · .NET 10
In short

Make the promoter the merchant of record: connect their own Stripe or Square account, take payments on it, and take your cut as a platform fee. Cap that fee to fit both providers' limits, set up Apple Pay and Google Pay on every promoter's account, record the real processing fee, and fix every bug on both providers together.

2
Payment providers kept in step
60%
Cap on the platform fee
3
Payment-model rewrites to get here
2,251
Commits on the platform

Before you start

  • ✓A decision on who is merchant of record (usually the promoter)
  • ✓Stripe Connect and Square developer accounts, with their test environments
  • ✓Your fee model per ticket, and who absorbs the processing fee
  • ✓A payment test plan covering each scenario on both providers

Deciding who is the merchant of record

The promoter sells the ticket, so the promoter should usually be merchant of record: their name on the statement, their refunds, their chargebacks. On a ticketing platform we built, payments go directly on the promoter's account, with the platform's cut as an application fee, avoiding settings that would quietly make the platform merchant of record. We got there in three iterations: transfers between three parties, then a fee plus a single transfer, then direct charges that mirror how Square works.

Connecting promoters

  • Stripe: promoters connect their own full (Standard) Stripe account and keep their own dashboard.
  • Square: ask for every permission you'll need up front (payments, payouts, customers if you'll store cards). Adding one later means every promoter reconnecting.
  • Identify the promoter from a one-time token, not whoever is logged in, and let it survive a slow sign-up (we use 30 minutes).
  • Encrypt stored tokens and renew Square's early: ours renew daily for any expiring within 7 days.

Working out fees per ticket

The booking fee is a percentage plus a fixed amount per ticket, rounded to the penny, with settings cascading from platform to promoter to event. It's fixed when the ticket enters the basket, so a settings change can't alter it mid-checkout. The platform fee is then capped at 60% of the charge to fit both providers' limits. The capped fee is recorded on the order and the uncapped figure kept for reporting.

Apple Pay, Google Pay and Klarna on every account

These need your checkout's web address registered on each promoter's account. We register it on connect or reconnect, checking what's already there, and gave existing promoters a backfill button.

Recording the real processing fee

On Stripe, the fee reported on the promoter's account includes your platform fee, so count only Stripe's own. On Square the fee isn't known at payment time, so it's filled in when Square reports the update. Never store an estimate: the promoter's payout report depends on it.

Planning for missed notifications

  • Tell Stripe when a notification fails briefly, so it retries.
  • Reconcile every minute on each provider, to catch payments whose notifications were missed, or acknowledged even though processing them failed.
  • Record each payout once, and never move one back from a final state.

Keeping the providers in step

A bug fixed on Stripe is checked and fixed on Square in the same change, and the payment test plan runs every scenario on both, embedded in promoters' websites and standalone.

What usually goes wrong

From our own projects, not the manual.

Apple Pay, Google Pay and Klarna vanished in live mode

The card form worked, but wallets and Klarna never appeared. When payments are taken on the promoter's account, Stripe needs your checkout domain registered on that account, and only enforces it in live mode. Register it on connect and backfill existing accounts.

Square rejected discounted orders with INVALID_FEES

A discount shrank the charge but not the platform fee, which then broke Square's fee limit. Cap the platform fee as a share of the actual charge on both providers.

Verified cards were still declined on Square

UK and EU cards passed the 3-D Secure check, but Square returned a generic decline because the proof of that check was never sent with the payment. Pass it through.

Customers couldn't retry after a decline

The retry reused the previous attempt's unique reference with a new card, so the provider rejected it. Issue a new reference only after a definite decline, and keep it after timeouts or server errors, or you risk charging twice.

Promoters' net takings were overstated

On the promoter's account, Stripe's fee figure includes the platform fee. Count only Stripe's own processing fee, and backfill it from charge updates.

OAuth connected the wrong promoter

The fixed return address carries no promoter details, so the connection step guessed from the logged-in user. Identify the promoter from the one-time token instead.

Square payments failed for some event names

Square's statement description forbids characters such as quotes, asterisks and angle brackets. Clean them out before sending.

Do it yourself, or get help?

If you're adding one provider to a simple shop, the provider's own documentation will get you most of the way. If you're a marketplace taking fees on other businesses' sales, supporting two providers, or putting checkout inside promoters' own websites, get help: the problems above only show up in live mode, with real cards, at real events.

Get a developer on it
FAQ

Common questions

Should a ticketing platform use direct or destination charges?

If promoters should be merchant of record (their name on statements, their refunds and chargebacks), take payments directly on their account and take your cut as an application fee. Destination charges make your platform the merchant of record instead.

Why do Apple Pay and Google Pay not show on my Stripe Connect checkout?

When payments are taken on the promoter's account, your checkout domain has to be registered on each promoter's Stripe account. Test mode doesn't enforce it, so it often only fails in live.

Can I support Stripe and Square on the same platform?

Yes. We choose the provider per event from the promoter's connected account, and keep both implementations in step so every fix lands on both.

Who pays the card processing fee?

That's a commercial choice. On our platform the promoter absorbs it and the customer pays a booking fee. Either way, record the real fee from the provider, not an estimate.

Building a ticketing or events platform?

Tell us how promoters get paid and how you make money. We'll design the payments before they're live with real events.