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¶
- Ask client for their email — personal email they want to own the account long-term
- Walk them through account creation (15 minutes, can be a quick call)
- Identity + bank verification — 2–5 business days (doesn't block development)
- Client provides you with: API token + Location ID (Square) or Publishable + Secret Key (Stripe)
- 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_TOKENas 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 Secretover a secure channel (NOT plain email) - [ ] Implement
lib/quickbooks.ts— token refresh,findOrCreateCustomer,sendInvoice. No SDK; purefetch. - [ ] 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_URIas plain env var in dashboard - [ ] Client verifies in production dashboard
- [ ] Estimate: 1–2 developer days + ~15 min client setup (Intuit app creation)