Stripe Payments Integration
Relevant source files
The following files were used as context for generating this wiki page:
- supabase/functions/create-checkout/index.ts
- supabase/functions/create-payment/index.ts
- supabase/functions/create-vendor-payment/index.ts
- src/pages/UniversalPayments.tsx
- src/pages/VendorPayments.tsx
- src/integrations/supabase/types.ts
- supabase/migrations/20251211141030_4825af33-5f37-4e88-a7bb-86643946b0fc.sql
The Stripe Payments Integration within the Monarch Property Management system provides a secure and unified framework for handling financial transactions across multiple user roles, including tenants and vendors. The system leverages Stripe Checkout to facilitate property bookings, vendor service payments, and recurring subscriptions while ensuring data integrity through Supabase Edge Functions and database triggers.
This integration manages the lifecycle of a payment from initialization via a Checkout Session to status updates within the project's internal database. It supports specific business logic such as 7-day free trials for subscriptions and metadata tracking to link Stripe events back to internal entities like bookings, rfqs, or vendor_payments.
Integration Architecture
The architecture utilizes a serverless approach where the frontend interacts with Supabase Edge Functions, which in turn communicate with the Stripe API. This ensures that sensitive keys like the STRIPE_SECRET_KEY are never exposed to the client side.
Payment Flow Overview
The following sequence diagram illustrates the process of creating a secure payment session:
Payment Types and Configuration
The system categorizes payments into three primary types, each with distinct Stripe configurations and internal tracking requirements.
Supported Transaction Types
| Type | Description | Internal Entity Mapping |
|---|---|---|
| Booking | Payments for property reservations by guests/tenants. | bookings table |
| Vendor Payment | One-off payments for vendor services or background checks. | vendor_payments table |
| Subscription | Recurring monthly fees for platform access (Basic, Professional, Enterprise). | stripe_subscriptions table |
Sources: supabase/functions/create-checkout/index.ts:16-33, src/integrations/supabase/types.ts:1140-1165
Subscription Logic
Subscriptions are configured as recurring monthly payments with a 7-day free trial period. The system is designed to collect payment methods upfront but delay charges until the trial ends.
sessionConfig.mode = 'subscription';
sessionConfig.subscription_data = {
trial_period_days: 7,
trial_settings: {
end_behavior: { missing_payment_method: 'cancel' },
},
metadata: { userId: user.id, subscriptionTier },
};
Sources: supabase/functions/create-checkout/index.ts:182-192
Database Schema and Persistence
The integration relies on several tables within the public schema to maintain a record of transactions and link them to Stripe entities.
Key Database Tables
| Table | Purpose | Key Fields |
|---|---|---|
transactions | Central log of all Stripe-initiated payment attempts. | stripe_session_id, amount, status, booking_id |
vendor_payments | Tracks specialized payment requests for vendors. | stripe_payment_intent_id, status (pending, processing, paid) |
stripe_customers | Maps Supabase user_id to Stripe customer_id. | user_id, stripe_customer_id |
stripe_subscriptions | Stores current status of user subscriptions. | stripe_subscription_id, status, current_period_end |
Sources: src/integrations/supabase/types.ts:1140-1200, supabase/migrations/20251211141030_4825af33-5f37-4e88-a7bb-86643946b0fc.sql:80-110
Security and Row Level Security (RLS)
Security is enforced through unified RLS policies that restrict data access based on the authenticated user's ID or administrative status. For example, users can only select their own Stripe records:
CREATE POLICY "stripe_payments_unified_select" ON public.stripe_payments
FOR SELECT USING (
(user_id = (SELECT auth.uid()))
OR (SELECT is_admin_user((SELECT auth.uid())))
);
Sources: supabase/migrations/20251211141030_4825af33-5f37-4e88-a7bb-86643946b0fc.sql:95-101
API Endpoints (Edge Functions)
The project implements several specialized Edge Functions to handle payment initialization.
create-checkout
A multi-purpose function that generates Stripe Checkout URLs for bookings, vendor payments, and subscriptions.
- URL:
POST /functions/v1/create-checkout - Validation: Uses Zod to ensure
amount,currency, and type-specific IDs (e.g.,bookingId) are present. - Workflow: Fetches user profile, configures Stripe
line_items, creates the session, and inserts a record into thetransactionstable.
Sources: supabase/functions/create-checkout/index.ts:16-50, supabase/functions/create-checkout/index.ts:221-233
create-payment / create-vendor-payment
Functions tailored specifically for vendor-initiated payments (e.g., paying for an RFQ or administrative fee).
- Validation: Verifies the payment belongs to the authenticated vendor and is in a
pendingstatus. - Status Update: Upon successful session creation, the local payment record is updated to
processingand tagged with thestripe_session_id.
Sources: supabase/functions/create-vendor-payment/index.ts:46-65, supabase/functions/create-payment/index.ts:70-85
Vendor Payment Lifecycle
The following diagram details the state transitions for a vendor payment within the system:
Implementation Details
Metadata Handling
To maintain the link between Stripe's external ecosystem and the internal database, the integration heavily utilizes Stripe's metadata field. This field is populated during session creation and is crucial for webhooks (implemented separately) to process the correct entities.
Example Metadata structure:
userId: Internal Supabase UUID.type: The transaction category (booking, subscription, etc.).bookingId/paymentId: The primary key of the related internal record.
Sources: supabase/functions/create-checkout/index.ts:121-125, supabase/functions/create-checkout/index.ts:154-154
Client-Side Interaction
The frontend provides a handlePayNow function that invokes the Supabase Edge Function and handles the redirect:
const processPayment = async () => {
const { data, error } = await supabase.functions.invoke('create-payment', {
body: { paymentId: selectedPayment.id }
});
if (data?.url) window.open(data.url, '_blank');
};
Sources: src/pages/UniversalPayments.tsx:63-82
Summary
The Stripe Payments Integration is a robust, serverless system centered around Supabase Edge Functions. It provides a secure bridge between the property management database and Stripe's payment infrastructure. By utilizing metadata, strict RLS policies, and validated Edge Functions, the system ensures that property bookings, vendor fees, and subscriptions are handled with high accuracy and security.