Skip to content

Payment Gateway Selection Guide

A quick reference for choosing between Square and Stripe for Bonbon Dino client projects.


TL;DR Decision Tree

Does the client need simple invoicing (one-off, custom amounts)?
  YES → Use Square ✅
  NO  → Does the client need subscriptions, usage-based billing, or complex pricing?
        YES → Use Stripe ✅
        NO  → Use Square ✅

Comparison Table

Aspect Square Stripe
Ease of Setup ⭐⭐⭐⭐⭐ ⭐⭐⭐
API Complexity Simple (5-10 endpoints) Complex (50+)
Learning Curve Shallow Steep
Invoice Hosting Built-in (Square hosts) DIY (you build it)
Built-in Features Reminders, receipts, portal Minimal (customize yourself)
Webhook Setup Optional Required
Community/Docs Good Excellent
Scalability Good (up to mid-market) Excellent (scales indefinitely)
Cost to Client 3.3% + 30¢ (typical) 2.9% + 30¢ (typical)
Developer Overhead Low High

When to Use Square ✅

Best for: - Therapy practices, consultants, coaches, mediators (service-based) - Custom per-session or per-project invoicing - Non-technical client (they manage through Dashboard) - Quick implementation needed - Small to mid-size businesses

Examples: - Keilen Family Services (therapist invoices) - Freelance consultants (project invoicing) - Personal trainers (session billing) - Mediators (hourly rates, per-case invoices)

Implementation time: 1–2 days API endpoints needed: ~5 (customers, orders, invoices, publish) Webhook complexity: None required Developer familiarity: Low to moderate


When to Use Stripe ✅

Best for: - SaaS (subscriptions, tiered pricing) - Marketplaces (splits, complex routing) - Scaling businesses (thousands of customers) - Custom payment flows (brand/design control) - Usage-based billing - International customers (multi-currency)

Examples: - Subscription management platform - Digital product marketplace - Software-as-a-service (pricing tiers) - Freelance marketplace (escrow, splits)

Implementation time: 3–5 days API endpoints needed: 20+ Webhook complexity: Moderate (payment events, invoice status) Developer familiarity: Moderate to high


Client Account Ownership

Always have the client create their own account. Do NOT create an account under Bonbon Dino's email.

Why?

  • Client owns their data/invoices/payouts
  • No dependency on you for account recovery, changes, or support
  • Cleaner handoff
  • Client gets email notifications (security, payouts, etc.)

How to Handle It

  1. Ask client for their email — personal email they want to own the account long-term
  2. Walk them through account creation (15 minutes, can be a quick call)
  3. Identity + bank verification — 2–5 business days (doesn't block development)
  4. Client provides you with: API token + Location ID (Square) or Publishable + Secret Key (Stripe)
  5. Deploy: You set secrets in Cloudflare/deployment platform, or client does with your verification

Implementation Checklists

Square Invoice Implementation

  • [ ] Client creates Square account (personal email)
  • [ ] Client completes identity + bank verification
  • [ ] Client generates API token (scopes: INVOICES_WRITE, ORDERS_WRITE, CUSTOMERS_READ/WRITE)
  • [ ] Client provides token + Location ID
  • [ ] Implement lib/square.ts (fetch wrapper)
  • [ ] Implement validation (form parsing)
  • [ ] Implement admin route (POST /api/admin/invoices)
  • [ ] Implement admin page + form component
  • [ ] Test against Square Sandbox (test card: 4111 1111 1111 1111)
  • [ ] At deploy: set SQUARE_ACCESS_TOKEN as Cloudflare secret, location ID + env as vars
  • [ ] Client verifies in production dashboard
  • [ ] Estimate: 1–2 developer days + 2–5 business days client verification

Stripe Implementation

  • [ ] Client creates Stripe account
  • [ ] Client generates API keys (Publishable + Secret)
  • [ ] Decide: Hosted Checkout vs. custom payment form?
  • [ ] If Hosted: implement redirect flow (simpler)
  • [ ] If Custom: implement Stripe Elements (more control, more code)
  • [ ] Set up webhooks (invoice events)
  • [ ] Implement invoice creation + payment trigger
  • [ ] Test against Stripe test mode
  • [ ] At deploy: set keys as Cloudflare secrets
  • [ ] Estimate: 3–5 developer days + client setup time

Cost Comparison (Annual)

Example: Small therapy practice sending $5,000/month in invoices

Platform Fee per Payment Annual Invoices Annual Cost Notes
Square 3.3% + 30¢ 60 invoices ~$198 Depends on payment rate
Stripe 2.9% + 30¢ 60 invoices ~$174 Slightly cheaper, more setup

Actual fees vary; confirm with current pricing.


Red Flags: When to Push Back

"I need Stripe because it's better" → Only if they have a specific use case (subscriptions, marketplace, etc.). Otherwise, Square is simpler.

"Just set it up under the agency's email" → No. Explain ownership and control; offer a guided call.

"I'll give you access to my account later" → Don't start dev until you have at least test credentials (Sandbox/Test mode).

"We'll handle payments ourselves, just integrate the button" → Clarify: do they want invoicing (Square/Stripe) or a one-off donation button? Different flows.


Resources

  • Square Documentation: https://developer.squareup.com/docs/invoices-api
  • Stripe Documentation: https://stripe.com/docs/invoicing
  • Square Sandbox Testing: https://developer.squareup.com/apps/sandbox
  • Stripe Test Mode: https://stripe.com/docs/testing (test cards provided)

Lessons Learned (Keilen Project)

What worked: Square for a simple invoicing flow. Minimal API surface, quick implementation, client owns account.

What to remember: Identity verification takes 2–5 days. Start early with the client.

What to avoid: Don't overcomplicate with webhooks if you don't need them (Square invoices don't require webhook listeners for basic flow).

Future projects: This guide saved 2 hours of "which platform should we use?" discussion for the next project.


When to Use QuickBooks Online ✅

Best for: - Client already has a QuickBooks Online subscription and wants invoices to flow directly into their books - Service businesses whose accountant is in QBO - Non-technical clients who already manage their business through QuickBooks - Scenarios where a single source of truth for revenue is required

Examples: - Therapy practices (Keilen Family Services) - Lawyers / accountants / consultants - Bookkeepers who bill hourly

Implementation time: 1–2 days (same ballpark as Square) API endpoints needed: ~4 (customer query, customer create, invoice create/send, companyinfo) Webhook complexity: None required (QBO does not push payment notifications on the basic plan) Developer familiarity: Low to moderate

Gotchas vs. Square: - Amounts are in dollars, not cents. QBO's Line[0].Amount is a decimal dollar amount (150.00 for $150), unlike Square which uses integer cents. Dividing cents by 100 at the boundary is a one-line change but easy to miss. - Customer lookup uses SQL-like query language: SELECT * FROM Customer WHERE PrimaryEmailAddr = '...'. Not a REST resource lookup. - Invoice send is a single POST. No separate "publish" step like Square's CreateInvoice + PublishInvoice. Use EmailStatus: "NeedToSend" on create and QBO emails the customer in the same call. - Refresh tokens rotate on every refresh. Both the access token AND the refresh token must be overwritten. Posting the same refresh token twice in parallel gets it revoked.

QuickBooks Online Implementation

  • [ ] Client creates an Intuit Developer account (developer.intuit.com) — can sign in with their existing QuickBooks credentials
  • [ ] Client creates an app under "QuickBooks Online and Payments" card
  • [ ] Client registers redirect URI(s) in the app's settings (HTTPS required for production, HTTP localhost OK for dev)
  • [ ] Client provides Client ID + Client Secret over a secure channel (NOT plain email)
  • [ ] Implement lib/quickbooks.ts — token refresh, findOrCreateCustomer, sendInvoice. No SDK; pure fetch.
  • [ ] Single OAuth scope: com.intuit.quickbooks.accounting (covers customer + invoice read/write + companyinfo)
  • [ ] Store tokens in D1/SQLite — single row keyed 'singleton', both access and refresh tokens, expiry timestamps
  • [ ] In-app "Connect to QuickBooks" flow (admin clicks → Intuit consent → callback → tokens stored)
  • [ ] Implement admin route (POST /api/admin/invoices)
  • [ ] Implement admin page + form component (unchanged from Square; validation is API-agnostic)
  • [ ] Test against Intuit sandbox (developer.intuit.com ships with a pre-seeded sandbox company)
  • [ ] At deploy: wrangler secret put QB_CLIENT_ID / QB_CLIENT_SECRET; QB_REDIRECT_URI as plain env var in dashboard
  • [ ] Client verifies in production dashboard
  • [ ] Estimate: 1–2 developer days + ~15 min client setup (Intuit app creation)