# Stripe shortlink card-collection tool spec

## Goal
Create a small internal tool that:
- creates a Stripe Checkout Session in `mode=setup`
- stores the full hosted Stripe URL
- generates a short customer-safe link on a No More Chores domain
- redirects the customer to the real Stripe hosted page reliably

## Why this is needed
Stripe's hosted setup URL can be extremely long and may include a fragment (`#...`). In testing, trimming that fragment broke the link. A normal URL shortener is risky because fragments are handled client-side.

## Recommended UX
Internal staff enters:
- customer name
- email or phone
- existing Stripe customer ID, or create new customer
- optional Launch27 customer ID

Tool returns:
- short URL, example: `https://pay.nomorechores.com/card/abc123`
- Stripe customer ID
- Stripe checkout session ID
- expiration time

## Recommended architecture

### Option A, simplest and recommended
Use a tiny app with:
- backend endpoint to create session
- database table for short links
- frontend redirect page on your own domain

Suggested stack:
- Node/Next.js or simple Express
- SQLite/Postgres/Supabase for storage
- Stripe SDK
- deployed on your existing web infra or a lightweight host

### Flow
1. Staff creates a card-collection request.
2. Backend creates Stripe Checkout Session with:
   - `mode=setup`
   - `customer=cus_...`
   - `currency=cad`
   - success/cancel URLs on your domain
3. Backend stores:
   - short code
   - full Stripe URL
   - customer ID
   - session ID
   - created by
   - created at
   - expires at
   - optional Launch27 customer ID
4. Tool returns short URL.
5. Customer opens short URL.
6. Your redirect page looks up the stored full Stripe URL.
7. Page immediately redirects in browser using JavaScript:
   - `window.location.replace(fullStripeUrl)`
8. Customer lands on Stripe.

## Why client-side redirect
Because the Stripe URL may depend on the fragment. A 301/302 server redirect may drop or mishandle fragment behavior. A browser-side redirect to the exact stored URL is safer.

## Data model

### card_collection_links
- `id`
- `code` unique short token
- `stripe_customer_id`
- `stripe_checkout_session_id`
- `stripe_checkout_url`
- `launch27_customer_id` nullable
- `customer_name` nullable
- `customer_email` nullable
- `customer_phone` nullable
- `status` (`open`, `completed`, `expired`, `cancelled`)
- `created_by`
- `created_at`
- `expires_at`
- `completed_at` nullable
- `stripe_setup_intent_id` nullable
- `stripe_payment_method_id` nullable
- `notes` nullable

## Endpoints

### POST `/api/card-links`
Input:
- customer info
- existing stripe customer id or create-new flag
- optional Launch27 customer id

Output:
- short URL
- stripe customer id
- checkout session id
- expires at

### GET `/card/:code`
- render minimal HTML page
- fetch target URL from server or embed at render time
- JS redirect to full Stripe URL
- fallback button: "Continue to secure payment page"

### POST `/api/stripe/webhook`
Handle:
- `checkout.session.completed`
- optionally `setup_intent.succeeded`

Webhook effects:
- mark short link completed
- store setup intent id
- extract and store payment method id if available
- optionally queue Launch27 sync

## Security rules
- short codes should be unguessable, not sequential
- expire links automatically
- do not expose secret key to frontend
- admin/staff tool behind auth
- log creator and timestamps
- webhook signature verification required
- avoid including sensitive internal IDs in customer-visible URLs

## Operational workflow
1. Staff opens internal tool.
2. Search existing customer.
3. Reuse existing Stripe customer or create one.
4. Click "Create card collection link".
5. Copy short URL and send to customer.
6. Customer submits card.
7. Webhook marks request completed.
8. Internal view shows payment method captured.
9. Copy or sync Stripe customer/payment method back into Launch27.

## MVP recommendation
Build the smallest useful version first:
- single staff page
- create Stripe setup session
- generate short code
- redirect page
- webhook completion tracking
- basic list of recent links

Skip for v1:
- fancy branding
- SMS/email sending inside tool
- Launch27 auto-sync
- role systems beyond simple auth

## Future integration
Later this can become part of the custom booking flow:
- create lead/customer
- collect card on file
- attach payment method to Stripe customer
- save customer + payment data in your booking system
- trigger quote/booking confirmation workflow

## Known implementation note from live testing
For this Stripe account, creating the setup Checkout Session required:
- `mode=setup`
- `customer=cus_...`
- `currency=cad`

## Recommendation
Build this as a tiny internal app first, not inside Launch27. Then fold it into the custom booking form once the flow is proven.
