Files
blackcanyontickets/reactrebuild0825/STRIPE_CHECKOUT_GUIDE.md
dzinesco aa81eb5adb feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality
- Implement territory management with manager performance tracking
- Add seatmap components for venue layout management
- Create customer management features with modal interface
- Add advanced hooks for dashboard flags and territory data
- Implement seat selection and venue management utilities
- Add type definitions for ticketing and seatmap systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-26 09:25:10 -06:00

1126 lines
34 KiB
Markdown

# Stripe Connect Checkout + Ticket Minting Guide
This guide covers the complete implementation of Stripe Connect checkout sessions with automatic ticket generation.
## Overview
The system now supports:
-**Checkout Creation**: Using connected Stripe accounts with platform fees
-**Payment Processing**: Secure Stripe Checkout with proper fee splitting
-**Webhook Handling**: Automatic ticket minting on payment completion
-**Inventory Management**: Automatic inventory updates and sold count tracking
-**Order Records**: Complete purchase history with customer details
## Backend Implementation
### New Cloud Functions
#### 1. `createCheckout`
**Endpoint**: `POST /api/checkout/create`
Creates a Stripe Checkout session using the organization's connected account with full idempotency and inventory safety.
**Request Body**:
```typescript
{
orgId: string;
eventId: string;
ticketTypeId: string;
qty: number;
purchaserEmail?: string;
successUrl: string;
cancelUrl: string;
}
```
**Response**:
```typescript
{
url: string; // Stripe Checkout URL
sessionId: string; // Session ID for tracking
}
```
**Key Features**:
- Validates organization has connected Stripe account and charges enabled
- Calculates platform fees using `PLATFORM_FEE_BPS` environment variable (default 3%)
- Creates checkout with connected account using `stripeAccount` parameter
- Includes comprehensive metadata for webhook processing
- Creates placeholder order for UI polling
- Full inventory validation before checkout creation
#### 2. `stripeWebhookConnect`
**Endpoint**: `POST /api/stripe/webhook/connect`
Handles webhooks from connected accounts with full idempotency protection.
**Supported Events**:
- `checkout.session.completed` - Triggers ticket minting
- `payment_intent.succeeded` - Additional payment tracking
**Ticket Minting Process**:
1. **Idempotency Check**: Creates `processedSessions/{sessionId}` document to prevent duplicates
2. **Inventory Transaction**: Atomically validates and decrements inventory
3. **Ticket Generation**: Creates individual tickets with UUID QR codes
4. **Order Update**: Marks order as 'paid' with payment details
5. **Email Delivery**: Sends confirmation email with QR code links
6. **Error Handling**: Graceful failure handling with comprehensive logging
All operations use Firestore transactions for atomic consistency.
#### 3. `verifyTicket`
**Endpoint**: `POST /api/tickets/verify` or `GET /api/tickets/verify/:qr`
Verifies ticket QR codes and marks them as scanned.
**Request Body** (POST):
```typescript
{
qr: string;
}
```
**Response**:
```typescript
{
valid: boolean;
ticket?: {
id: string;
eventId: string;
ticketTypeId: string;
eventName?: string;
ticketTypeName?: string;
status: string;
purchaserEmail?: string;
};
reason?: string; // 'already_scanned', 'ticket_voided', 'Ticket not found'
scannedAt?: string;
}
```
**Key Features**:
- Atomic scan status updates to prevent double-scanning
- Comprehensive ticket information in response
- Support for both POST with body and GET with path parameter
- Detailed error reasons for failed verifications
#### 4. `getOrder`
**Endpoint**: `POST /api/orders/get`
Retrieves order details by session ID for frontend polling.
**Request Body**:
```typescript
{
sessionId: string;
}
```
**Response**:
```typescript
{
id: string;
status: 'pending' | 'paid' | 'failed_sold_out';
qty: number;
totalCents: number;
purchaserEmail?: string;
eventName?: string;
ticketTypeName?: string;
// ... additional order details
}
```
### Environment Configuration
Required environment variables for Firebase Functions:
```bash
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET_CONNECT=whsec_... # For connected account events
# Email Configuration (optional - logs in dev if not set)
EMAIL_API_KEY=re_... # Resend API key
# Application Configuration
APP_URL=https://staging.blackcanyontickets.com # For QR code links
PLATFORM_FEE_BPS=300 # 3% platform fee (default if not set)
```
Firebase Functions config (legacy method):
```bash
firebase functions:config:set stripe.secret_key="sk_test_..."
firebase functions:config:set stripe.connect_webhook_secret="whsec_..."
firebase functions:config:set email.api_key="re_..."
firebase functions:config:set app.url="https://staging.blackcanyontickets.com"
firebase functions:config:set platform.fee_bps="300"
```
## Webhook Setup
### Platform Webhook (Existing)
- **URL**: `https://us-central1-PROJECT_ID.cloudfunctions.net/stripeWebhook`
- **Events**: `account.updated`
- **Purpose**: Sync account connection status
### Connect Webhook (New)
- **URL**: `https://us-central1-PROJECT_ID.cloudfunctions.net/stripeWebhookConnect`
- **Events**: `checkout.session.completed`
- **Purpose**: Handle successful payments and mint tickets with idempotency protection
**Note**: Connect webhooks receive a `Stripe-Account` header identifying which connected account triggered the event.
## Frontend Implementation
### useCheckout Hook
```typescript
import { useCheckout } from '../hooks/useCheckout';
const { createCheckout, isLoading, error } = useCheckout();
// Create checkout session
await createCheckout({
orgId: user.organization.id,
eventId: 'event_123',
ticketTypeId: 'ticket_type_456',
quantity: 2,
customerEmail: 'customer@example.com',
successUrl: '/checkout/success',
cancelUrl: '/checkout/cancel',
});
```
### TicketPurchase Component
Complete checkout component with:
- Quantity selector with inventory validation
- Price breakdown including platform fees
- Customer email input
- Secure checkout button
- Error handling and loading states
```tsx
import { TicketPurchase } from '../components/checkout/TicketPurchase';
<TicketPurchase
eventId="event_123"
ticketTypeId="ticket_type_456"
ticketTypeName="General Admission"
priceInCents={5000} // $50.00
maxQuantity={10}
inventory={50}
/>
```
### Success/Cancel Pages
- **`/checkout/success`** - Displays purchase confirmation with ticket details
- **`/checkout/cancel`** - Handles cancelled purchases with retry options
## Data Schema
### Tickets Collection
```typescript
// /tickets/{ticketId}
{
orgId: string;
eventId: string;
ticketTypeId: string;
orderId: string; // Links to order (sessionId)
purchaserEmail: string;
qr: string; // UUID for scanning
status: 'issued' | 'scanned' | 'void';
createdAt: Timestamp;
scannedAt?: Timestamp;
updatedAt?: Timestamp;
}
```
### Orders Collection
```typescript
// /orders/{sessionId}
{
orgId: string;
eventId: string;
ticketTypeId: string;
qty: number;
sessionId: string;
status: 'pending' | 'paid' | 'failed_sold_out';
totalCents: number;
createdAt: Timestamp;
purchaserEmail?: string;
paymentIntentId?: string;
stripeAccountId: string;
updatedAt?: Timestamp;
failureReason?: string; // For failed orders
}
```
### Updated Ticket Types
```typescript
// /ticket_types/{ticketTypeId}
{
orgId: string;
eventId: string;
name: string;
priceCents: number;
currency: 'USD';
inventory: number; // Total available
sold: number; // Number sold (incremented atomically)
createdAt: Timestamp;
updatedAt?: Timestamp;
}
```
### Processed Sessions Collection (Idempotency)
```typescript
// /processedSessions/{sessionId}
{
sessionId: string;
processedAt: Timestamp;
orgId: string;
eventId: string;
ticketTypeId: string;
qty: number;
paymentIntentId: string;
stripeAccountId: string;
}
```
## Testing Flow
### End-to-End Test Scenario
1. **Setup**: Ensure organization has connected Stripe account
2. **Create Event**: With published status and active ticket types
3. **Purchase Flow**:
```bash
# User clicks "Purchase Tickets"
# → createStripeCheckout called
# → Redirects to Stripe Checkout
# → User completes payment
# → Stripe sends webhook to stripeConnectWebhook
# → Tickets automatically minted
# → User redirected to success page
```
### Validation Points
✅ **Payment Processing**:
- Platform fee calculated correctly (2.9% + $0.30)
- Connected account receives net amount
- Platform receives application fee
✅ **Ticket Generation**:
- Unique ticket IDs generated
- QR codes created for scanning
- Customer information captured
✅ **Inventory Management**:
- Available inventory decremented
- Sold count incremented
- Overselling prevented
✅ **Data Consistency**:
- All database operations atomic
- Order and ticket records linked
- Audit trail maintained
## Error Handling
### Common Scenarios
1. **Payment Fails**: User sees error, can retry
2. **Webhook Delay**: Tickets may take 1-2 minutes to appear
3. **Inventory Conflict**: Prevented by atomic operations
4. **Email Issues**: Tickets stored in database regardless
### Monitoring
Add logging to track:
- Checkout session creation success/failure rates
- Webhook processing times
- Ticket minting success rates
- Payment vs. ticket generation correlation
## Security Considerations
### Payment Security
- ✅ Card data never touches your servers
- ✅ PCI compliance handled by Stripe
- ✅ Webhook signatures verified
- ✅ Connected account isolation
### Data Protection
- ✅ Customer data encrypted in transit and at rest
- ✅ Minimal customer data stored (email, name)
- ✅ Ticket IDs non-enumerable (timestamp + random)
- ✅ Organization data isolation maintained
## Performance Optimizations
### Database Efficiency
- Batch operations for ticket creation
- Indexed queries for ticket lookup
- Efficient inventory updates
- Proper error rollback
### Frontend Optimization
- Immediate redirect to Stripe (no waiting)
- Optimistic UI updates where appropriate
- Error state handling
- Loading state management
## Next Steps
### Advanced Features
1. **Email Notifications**: Send ticket confirmations via Resend/SendGrid
2. **PDF Generation**: Create downloadable ticket PDFs with QR codes
3. **Calendar Integration**: Add event to customer calendars
4. ✅ **Refund Handling**: Secure refund processing with organization validation
5. **Bulk Purchases**: Handle group bookings and corporate sales
6. **Waitlist Management**: Handle sold-out scenarios with waitlist functionality
7. **Dynamic Pricing**: Time-based and demand-based pricing strategies
8. **Multi-Currency Support**: International payment processing
### Performance Optimizations
1. **Webhook Batching**: Process multiple events in single transaction
2. **Inventory Caching**: Redis caching for high-traffic events
3. **Database Sharding**: Partition tickets by event for scale
4. **Queue Processing**: Async ticket generation for very large orders
5. **CDN Integration**: Cache static checkout pages
### Analytics Integration
1. **Sales Tracking**: Revenue and conversion analytics with refund adjustments
2. **Customer Insights**: Purchase behavior analysis and fraud detection
3. **Event Performance**: Attendance and sales metrics with real-time updates
4. **Platform Metrics**: Fee collection and growth tracking with configurable rates
5. **Operational Analytics**: Webhook processing times, error rates, and idempotency metrics
6. **Security Analytics**: Failed authentication attempts and suspicious refund patterns
## Refunds, Voids & Disputes System
### Overview
The platform now supports comprehensive refund management, dispute handling, and financial reconciliation with enterprise-grade safety features:
- ✅ **Full/Partial/Per-Ticket Refunds**: Flexible refund options with proper ledger tracking
- ✅ **Automatic Dispute Handling**: Tickets locked on dispute creation, outcomes processed automatically
- ✅ **Financial Reconciliation**: Complete ledger system with CSV export capabilities
- ✅ **Permission-Based Access**: Only admins/super-admins can process refunds
- ✅ **Idempotent Operations**: Prevents duplicate refunds and maintains data consistency
### Refund Management
#### Creating Refunds
**Endpoint**: `POST /api/refunds/create`
**Request Body**:
```typescript
{
orderId: string; // Required: Order to refund
ticketId?: string; // Optional: Specific ticket to refund
amountCents?: number; // Optional: Custom amount (defaults to full/ticket price)
reason?: string; // Optional: Reason for refund
}
```
**Refund Types**:
1. **Full Order Refund**: Refunds entire order amount
```typescript
{ orderId: "order_123" }
```
2. **Single Ticket Refund**: Refunds specific ticket at ticket price
```typescript
{ orderId: "order_123", ticketId: "ticket_456" }
```
3. **Partial Amount Refund**: Custom refund amount
```typescript
{ orderId: "order_123", amountCents: 2500 } // $25.00
```
4. **Multiple Tickets**: Multiple tickets via custom amount
```typescript
{ orderId: "order_123", amountCents: 5000 } // 2 x $25 tickets
```
**Response**:
```typescript
{
refundId: string;
stripeRefundId: string;
amountCents: number;
status: "succeeded" | "failed";
}
```
**Key Features**:
- **Permission Validation**: Only org admins/super-admins can create refunds
- **Idempotency Protection**: Duplicate refund requests return existing refund
- **Automatic Fee Handling**: Platform fees and Stripe fees refunded proportionally
- **Ticket Status Updates**: Refunded tickets marked as 'refunded' status
- **Comprehensive Logging**: Full audit trail for all refund operations
#### Refund Validation Rules
- Order must be in 'paid' status
- Refund amount cannot exceed order total
- Tickets must be 'issued' or 'scanned' (not already refunded/void/disputed)
- Only organization members with admin privileges can create refunds
- Disputed orders cannot be refunded (must resolve dispute first)
### Dispute Handling
#### Automatic Dispute Processing
The system automatically handles Stripe dispute webhooks:
**`charge.dispute.created`**:
1. Finds order by payment intent/charge ID
2. Locks all related tickets (status: 'locked_dispute')
3. Creates dispute fee ledger entries if applicable
4. Updates order with dispute information
**`charge.dispute.closed`**:
1. **If Won**: Restores tickets to previous status ('issued'/'scanned')
2. **If Lost**: Voids tickets and creates negative ledger entries (loss accounting)
**Dispute Status Tracking**:
```typescript
// Order dispute field
{
dispute?: {
disputeId: string;
status: string;
reason: string;
outcome?: "won" | "lost";
createdAt: Timestamp;
closedAt?: Timestamp;
}
}
```
**Ticket Status Flow**:
```
Normal Flow: issued → scanned
Dispute Flow: issued → locked_dispute → (won: issued) | (lost: void)
```
#### Getting Dispute Information
**Endpoint**: `POST /api/disputes/get`
**Request Body**:
```typescript
{ orderId: string; }
```
**Response**:
```typescript
{
orderId: string;
dispute: {
disputeId: string;
status: string;
reason: string;
outcome?: string;
} | null;
}
```
### Financial Ledger System
#### Ledger Entry Types
All financial transactions are recorded in the `ledger` collection:
```typescript
interface LedgerEntry {
orgId: string;
eventId: string;
orderId: string;
type: "sale" | "refund" | "fee" | "platform_fee" | "dispute_fee";
amountCents: number; // Positive for revenue, negative for costs
currency: "USD";
stripe: {
balanceTxnId?: string;
chargeId?: string;
refundId?: string;
disputeId?: string;
accountId: string;
};
createdAt: Timestamp;
meta?: Record<string, any>;
}
```
#### Ledger Entry Creation
**For Sales** (in `checkout.session.completed`):
```typescript
// Sale entry (+$150.00)
{ type: "sale", amountCents: 15000 }
// Platform fee (+$4.50 for platform)
{ type: "platform_fee", amountCents: 450 }
// Stripe processing fee (-$4.65 for organizer)
{ type: "fee", amountCents: -465 }
```
**For Refunds** (in `createRefund` and `refund.created` webhook):
```typescript
// Refund entry (-$75.00)
{ type: "refund", amountCents: -7500 }
// Platform fee refund (-$2.25 for platform)
{ type: "platform_fee", amountCents: -225 }
// Stripe refund fee (varies by policy)
{ type: "fee", amountCents: -0 }
```
**For Disputes** (in `charge.dispute.created`):
```typescript
// Dispute fee (-$15.00 typically)
{ type: "dispute_fee", amountCents: -1500 }
```
### Reconciliation & Reporting
#### Reconciliation API
**Endpoint**: `POST /api/reconciliation/data`
**Request Body**:
```typescript
{
orgId: string;
eventId?: string; // Optional: specific event or "all"
startDate: string; // ISO date string
endDate: string; // ISO date string
format?: "json" | "csv"; // Default: json
}
```
**Response (JSON)**:
```typescript
{
summary: {
grossSales: number; // Total sales amount
refunds: number; // Total refunds (positive)
stripeFees: number; // Total Stripe fees (positive)
platformFees: number; // Total platform fees (positive)
disputeFees: number; // Total dispute fees (positive)
netToOrganizer: number; // Final amount to organizer
totalTransactions: number; // Unique order count
period: { start: string; end: string; }
};
entries: LedgerEntry[]; // Detailed transactions
total: number; // Entry count
}
```
**Calculation Formula**:
```
Net to Organizer = Gross Sales - Refunds - Stripe Fees - Platform Fees - Dispute Fees
```
#### CSV Export
**Request with `format: "csv"`** returns downloadable CSV with:
- **Summary Section**: Period, totals, and key metrics
- **Transaction Details**: Complete ledger entries
- **Headers**: Date, Type, Amount, Order ID, Stripe Transaction ID, Account ID, Notes
**CSV Structure**:
```csv
SUMMARY
2024-01-01,Period Start,,,,,
2024-12-31,Period End,,,,,
,Gross Sales,150.00,,,,
,Net to Organizer,140.85,,,,
TRANSACTIONS
Date,Type,Amount,Order ID,Stripe Transaction ID,Account ID,Notes
2024-08-01T10:30:00Z,sale,150.00,order-123,txn_abc123,acct_def456,
2024-08-01T10:30:00Z,platform_fee,4.50,order-123,txn_abc123,acct_def456,
```
### Frontend Components
#### RefundModal Component
**Location**: `src/features/orders/RefundModal.tsx`
**Props**:
```typescript
interface RefundModalProps {
isOpen: boolean;
onClose: () => void;
order: {
id: string;
totalCents: number;
tickets: Array<{
id: string;
status: string;
priceCents: number;
ticketTypeName: string;
}>;
};
onRefundCreated?: (refundId: string) => void;
}
```
**Features**:
- **Refund Type Selection**: Full, partial, or specific tickets
- **Dynamic Amount Calculation**: Updates based on selection
- **Validation**: Prevents invalid amounts and states
- **Real-time Feedback**: Success/error states with detailed messages
- **Permission Awareness**: Disabled for users without refund permissions
#### OrdersTable Component
**Location**: `src/features/orders/OrdersTable.tsx`
**Features**:
- **Order Display**: Status, amounts, customer info, ticket details
- **Dispute Alerts**: Visual indicators for disputed orders
- **Refund History**: Shows existing refunds with amounts and dates
- **Action Buttons**: Context-aware refund and view options
- **Real-time Updates**: Refreshes data after refund operations
#### Reconciliation Component
**Location**: `src/features/reports/Reconciliation.tsx`
**Features**:
- **Date Range Filtering**: Custom period selection
- **Event Filtering**: All events or specific event
- **Summary Cards**: Key financial metrics with visual indicators
- **Detailed Breakdown**: Sortable transaction table
- **CSV Export**: Client-side download generation
- **Real-time Calculations**: Updates as filters change
### Security & Permissions
#### Refund Permissions
Only users with these roles can create refunds:
- **Super Admin**: Global platform admin
- **Organization Admin**: Admin of the specific organization
- **Territory Manager**: Manager of organization's territory _(future feature)_
#### Permission Validation
```typescript
// Server-side validation in all refund endpoints
async function checkRefundPermissions(uid: string, orgId: string): Promise<boolean> {
const userDoc = await db.collection("users").doc(uid).get();
const userData = userDoc.data();
// Super admin access
if (userData?.role === "super_admin") return true;
// Org admin access
if (userData?.organization?.id === orgId && userData?.role === "admin") return true;
return false;
}
```
#### API Security
- **Authentication**: All refund APIs require valid JWT token
- **Authorization**: Organization-based access control
- **Input Validation**: Comprehensive validation of all parameters
- **Rate Limiting**: Protection against abuse (configured at infrastructure level)
### Error Handling & Monitoring
#### Comprehensive Error Handling
```typescript
// Refund creation errors
{
"orderId is required" |
"Order not found" |
"Can only refund paid orders" |
"Invalid refund amount: {amount}. Must be between 1 and {max}" |
"Cannot refund ticket with status: {status}" |
"Insufficient permissions" |
"Refund failed" // With Stripe error details
}
```
#### Logging & Monitoring
**Structured Logging**:
```typescript
console.log(`[create_refund] Starting refund creation`, {
orderId, ticketId, amountCents, uid, orgId,
timestamp: new Date().toISOString()
});
console.log(`[create_refund] Refund completed successfully`, {
refundId, stripeRefundId, amountCents,
processingTime: Date.now() - startTime
});
```
**Key Metrics to Monitor**:
- Refund success/failure rates
- Average refund processing time
- Dispute resolution outcomes
- Ledger entry consistency
- Permission denial attempts
### Testing & Validation
#### Comprehensive Test Coverage
**File**: `tests/refunds-disputes.spec.ts`
**Test Scenarios**:
- ✅ Full order refunds with success validation
- ✅ Partial amount refunds with input validation
- ✅ Single and multiple ticket refunds
- ✅ Refund amount validation and error handling
- ✅ Permission-based access control
- ✅ Idempotency for duplicate refund requests
- ✅ Dispute status display and ticket locking
- ✅ Reconciliation calculations and CSV export
- ✅ Ledger entry creation and integrity
#### Manual Testing Checklist
- [ ] Admin can create all types of refunds
- [ ] Non-admin users get permission denied
- [ ] Refunded tickets show correct status
- [ ] Ledger entries balance with Stripe dashboard
- [ ] Disputed orders block refund attempts
- [ ] CSV export contains accurate data
- [ ] Duplicate refund requests handled gracefully
### Production Deployment
#### Environment Variables
```bash
# Required for refunds and disputes
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET_CONNECT=whsec_...
EMAIL_API_KEY=re_...
APP_URL=https://portal.blackcanyontickets.com
PLATFORM_FEE_BPS=300 # 3% platform fee
```
#### Webhook Configuration
**Connect Webhook Events** (required for dispute handling):
```
charge.dispute.created
charge.dispute.closed
refund.created
checkout.session.completed
```
#### Database Indexes
**Recommended Firestore indexes**:
```typescript
// ledger collection
{ orgId: "asc", createdAt: "desc" }
{ orgId: "asc", eventId: "asc", createdAt: "desc" }
{ orderId: "asc", type: "asc" }
// refunds collection
{ orgId: "asc", createdAt: "desc" }
{ orderId: "asc", createdAt: "desc" }
// orders collection
{ paymentIntentId: "asc" }
```
### Troubleshooting
#### Common Issues
**Refund Fails with Stripe Error**:
- Check if payment intent supports refunds
- Verify connected account has sufficient balance
- Ensure webhook secrets are correctly configured
**Ledger Entries Don't Match Stripe**:
- Verify all webhook events are being processed
- Check for missing balance transaction data
- Validate fee calculations against Stripe dashboard
**Disputes Not Processing**:
- Confirm webhook endpoint is receiving events
- Verify `charge.dispute.*` events are configured
- Check account identification in webhook headers
**CSV Export Issues**:
- Verify `csv-writer` dependency is installed
- Check file system permissions for temporary files
- Validate date range parameters
#### Support Escalation
For production issues:
1. Check Firebase Functions logs for detailed error traces
2. Verify Stripe webhook delivery logs
3. Validate ledger entry consistency with database queries
4. Contact platform support with specific error messages and timestamps
## Summary of Complete Implementation
### ✅ Security Enhancements
- **Idempotency Protection**: Prevents duplicate operations across all functions
- **Transactional Safety**: Atomic operations for inventory, refunds, and ledger entries
- **Permission-Based Access**: Role-based refund authorization with org isolation
- **Input Validation**: Comprehensive validation of all API inputs and business rules
- **Account Isolation**: Proper Stripe Connect account handling and data separation
### ✅ Financial Integrity
- **Complete Ledger System**: Every transaction recorded with full audit trail
- **Automated Fee Tracking**: Stripe processing fees and platform fees captured automatically
- **Dispute Accounting**: Proper handling of dispute outcomes with financial adjustments
- **Reconciliation Tools**: Real-time financial reporting with CSV export capabilities
- **Multi-Currency Support**: Foundation for international payment processing _(USD only currently)_
### ✅ Operational Excellence
- **Comprehensive Error Handling**: Graceful handling of all failure scenarios
- **Structured Logging**: Consistent audit trail optimized for monitoring and alerting
- **Performance Monitoring**: Processing times and success rates tracked across all operations
- **Automated Testing**: Complete test coverage for critical financial operations
- **Production Readiness**: Enterprise-grade configuration and deployment guidelines
### ✅ User Experience
- **Intuitive Refund Interface**: Easy-to-use modal with multiple refund options
- **Real-time Status Updates**: Live feedback on refund processing and dispute status
- **Comprehensive Reporting**: Detailed financial reconciliation with export capabilities
- **Permission-Aware UI**: Interface adapts based on user roles and permissions
- **Mobile-Responsive Design**: Full functionality across all device types
The refunds, disputes, and reconciliation system is now production-ready with enterprise-grade financial controls, comprehensive audit trails, and robust error handling! 💰🔒📊
## Connecting Stripe for Organizers
### Accessing Payment Settings
Organizers need to connect their Stripe account before they can publish events and accept payments.
**Navigation Path**:
- From any event detail page → "Connect Stripe Account" button in payment banner
- From publish modal → "Connect Payments" action button (with `data-testid="paymentCheck"`)
- Direct URL: `/org/{orgId}/payments`
### React Integration Components
The frontend integration includes several key components with proper TypeScript support and testing:
#### PaymentSettings Component
**Location**: `src/features/org/PaymentSettings.tsx`
**Features**:
- **Design Token Based**: Uses semantic color and spacing tokens (no hardcoded values)
- **Data Test IDs**: All interactive elements have `data-testid` attributes for testing
- **Zustand Integration**: Connects to `useCurrentOrgStore` for real-time payment status
- **Mock API Integration**: Uses `api.stripeConnect` service for consistent data fetching
**Key Elements**:
- `data-testid="connectBtn"` - Connect/Continue Setup button
- `data-testid="refreshBtn"` - Refresh Status button
- `data-testid="disconnectBtn"` - Disconnect button
- UX Callout: Shows warning when payment not connected for publishing
#### PublishEventModal Component
**Location**: `src/features/events/PublishEventModal.tsx`
**Enhanced Features**:
- **Payment Checklist**: Payment requirement with `data-testid="paymentCheck"`
- **Publish Button**: `data-testid="publishBtn"` for E2E testing
- **Smart Actions**: Direct link to payment settings when payment not connected
- **Requirement Validation**: Blocks publishing until all requirements met including payment
#### Stripe Connect Hooks
**Location**: `src/hooks/useStripeConnect.ts`
**Provides**:
- `useStripeConnect(orgId)` - Main hook for all Stripe Connect operations
- `useStripeConnectStatus(orgId)` - Auto-fetching payment status
- `useStripeConnectStart(orgId)` - Onboarding flow initiation
- `useStripeConnectRefresh(orgId)` - Manual status refresh
**State Management**:
- Integrates with Zustand org store
- Mock API integration for demo/testing
- Proper loading and error states
- TypeScript interfaces for all data structures
### API Integration
**Mock API Endpoints** (for frontend demo):
- `POST ${VITE_API_BASE}/stripe/connect/start` - Start onboarding
- `GET ${VITE_API_BASE}/stripe/connect/status` - Get connection status
**Service Layer**:
```typescript
import { api } from '../services/api';
// Start onboarding
const result = await api.stripeConnect.startOnboarding(orgId);
// Check status
const status = await api.stripeConnect.getConnectStatus(orgId);
```
### Payment Settings Interface
The Payment Settings page shows:
#### Connection Status
- **Provider**: Always shows "Stripe" (only supported provider)
- **Connected**: ✅ (Green check) or ❌ (Warning badge)
- **Business Name**: Displayed when account is fully set up
- **Account Details**: Shows detailsSubmitted and chargesEnabled status
#### Action Buttons
- **Connect Stripe**: Starts initial onboarding flow
- **Continue Setup**: Resumes incomplete onboarding
- **Refresh Status**: Manually checks current Stripe account status
- **Disconnect**: Removes Stripe connection (stub implementation)
### What "Connected" Means
An account is considered **fully connected** when:
1. `detailsSubmitted: true` - Business details provided to Stripe
2. `chargesEnabled: true` - Stripe has approved the account for processing
3. Both conditions must be true for `connected: true`
### Onboarding Process
1. **Click Connect/Continue**: Redirects to Stripe Connect onboarding
2. **Complete Forms**: Provide business details, banking info, identity verification
3. **Submit for Review**: Stripe reviews account (1-2 business days typical)
4. **Account Approved**: `chargesEnabled` becomes true, account fully connected
5. **Return to Platform**: Automatic redirect back to Payment Settings
### Status Messages
- **Setup Required**: Account created but details not submitted
- **Under Review**: Details submitted, waiting for Stripe approval
- **Connected**: Fully operational, can accept payments
### Publish Flow Integration
Events cannot be published until:
- ✅ At least 1 active ticket type exists
- ✅ Valid event dates (start < end)
- ✅ Stripe account connected (`connected: true`)
The publish modal enforces these requirements and provides direct links to resolve each issue.
### Troubleshooting
**Common Issues**:
- **Interrupted Onboarding**: Use "Continue Setup" button to resume
- **Long Review Times**: Stripe may request additional documentation
- **Account Restricted**: Check Stripe dashboard for specific requirements
- **Status Not Updating**: Use "Refresh Status" button to sync latest data
**Support**:
- Platform issues → Contact BCT support
- Stripe account issues → Contact Stripe support directly
### Testing & Quality Assurance
#### Comprehensive Test Suite
**PaymentSettings Component Tests** (`src/features/org/__tests__/PaymentSettings.test.tsx`):
- ✅ Renders payment settings page with correct elements
- ✅ Shows disconnected state when no payment info
- ✅ Displays connected status with account details
- ✅ Handles partially connected state with setup required
- ✅ Calls correct API endpoints with proper parameters
- ✅ Updates Zustand store on successful operations
- ✅ Displays loading states during API calls
- ✅ Shows error messages when API calls fail
- ✅ Handles URL parameters for post-onboarding flows
- ✅ Shows development info in DEV mode
**PublishEventModal Component Tests** (`src/features/events/__tests__/PublishEventModal.test.tsx`):
- ✅ Renders modal with requirements checklist
- ✅ Shows loading state while checking requirements
- ✅ Displays all requirements with proper pass/fail states
- ✅ Blocks publishing when payment not connected
- ✅ Shows payment checklist with correct data-testid
- ✅ Enables publish button when all requirements met
- ✅ Handles successful publishing flow with auto-close
- ✅ Provides action buttons for fixing failed requirements
- ✅ Maintains proper accessibility attributes
- ✅ Handles error states gracefully
#### Testing Patterns
**Data Test IDs**:
- `data-testid="connectBtn"` - Connect/Continue Setup button
- `data-testid="refreshBtn"` - Refresh Status button
- `data-testid="disconnectBtn"` - Disconnect button
- `data-testid="paymentCheck"` - Payment requirements checklist item
- `data-testid="publishBtn"` - Publish Event button
**Mock API Integration**:
```typescript
// Tests use consistent mocking patterns
global.fetch = vi.fn();
mockFetch.mockResolvedValue({
ok: true,
json: async () => ({ payment: mockPaymentData }),
});
```
**Zustand Store Testing**:
```typescript
// Store integration is mocked and validated
(useCurrentOrgStore as any).mockReturnValue({
org: mockOrg,
updatePaymentStatus: mockUpdatePaymentStatus,
});
expect(mockUpdatePaymentStatus).toHaveBeenCalledWith(expectedPaymentData);
```
#### End-to-End Testing
**Critical User Flows**:
1. **Payment Connection Flow**:
- Navigate to payment settings
- Click connect button
- Redirect to Stripe (mocked)
- Return with success status
- Verify payment status updated
2. **Publishing with Payment Check**:
- Open publish modal
- Verify payment requirement shows connected status
- Publish button enabled when all requirements met
- Successful publishing updates event status
3. **Error Handling Paths**:
- API failures show appropriate error messages
- Loading states provide user feedback
- Permission errors prevent unauthorized actions
#### Performance & Accessibility
**Key Metrics**:
-**WCAG AA Compliance**: Proper ARIA labels and keyboard navigation
-**Mobile Responsive**: Works on all device sizes
-**Loading States**: Immediate user feedback during API calls
-**Error Recovery**: Clear error messages with retry options
-**Design Token Usage**: No hardcoded colors or spacing values
**Browser Support**:
- Modern browsers with ES2020+ support
- Mobile Safari and Chrome
- Desktop Firefox, Chrome, Edge, Safari
#### Production Readiness Checklist
- [x] All components use design tokens (no hardcoded styles)
- [x] Comprehensive data-testid coverage for E2E testing
- [x] TypeScript interfaces for all props and state
- [x] Error boundaries and graceful failure handling
- [x] Loading states for all async operations
- [x] Accessibility compliance with proper ARIA attributes
- [x] Mock API integration for frontend-only testing
- [x] Comprehensive test coverage with React Testing Library
- [x] Integration with existing Zustand state management
- [x] Mobile-first responsive design implementation