BREAKING CHANGE: Complete refactor of payment handling New Architecture: 1. pakasir-webhook (120 lines -> was 535 lines) - Only verifies signature and updates order status - Removed: SMTP, email templates, notification logic 2. Database Trigger (NEW) - Automatically fires when payment_status = 'paid' - Calls handle-order-paid edge function - Works for webhook AND manual admin updates 3. handle-order-paid (NEW edge function) - Grants user access for products - Creates Google Meet events for consulting - Sends notifications via send-email-v2 - Triggers webhooks Benefits: - Single Responsibility: Each function has one clear purpose - Trigger works for both webhook and manual admin actions - Easier to debug and maintain - Reusable notification system Migration required: Run 20241223_payment_trigger.sql 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
94 lines
3.7 KiB
PL/PgSQL
94 lines
3.7 KiB
PL/PgSQL
-- ============================================================================
|
|
-- Payment Trigger Architecture
|
|
-- ============================================================================
|
|
-- This refactors the payment flow to use database triggers instead of
|
|
-- handling everything in the webhook function.
|
|
--
|
|
-- Flow:
|
|
-- 1. pakasir-webhook or admin updates order.payment_status = 'paid'
|
|
-- 2. Trigger fires -> calls handle_paid_order() function
|
|
-- 3. handle_paid_order() calls handle-order-paid edge function
|
|
-- 4. Edge function handles: access grants, notifications, meet links
|
|
-- ============================================================================
|
|
|
|
-- Enable pg_net extension for HTTP calls from PostgreSQL
|
|
CREATE EXTENSION IF NOT EXISTS pg_net;
|
|
|
|
-- ============================================================================
|
|
-- Function: handle_paid_order
|
|
-- Purpose: Called by trigger when order payment_status becomes 'paid'
|
|
-- Calls the edge function to handle all post-payment actions
|
|
-- ============================================================================
|
|
CREATE OR REPLACE FUNCTION handle_paid_order()
|
|
RETURNS TRIGGER AS $$
|
|
DECLARE
|
|
edge_function_url TEXT;
|
|
edge_function_response TEXT;
|
|
order_data JSON;
|
|
BEGIN
|
|
-- Only proceed if payment_status changed to 'paid'
|
|
IF (NEW.payment_status != 'paid' OR OLD.payment_status = 'paid') THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- Log the payment event
|
|
RAISE NOTICE 'Order % payment status changed to paid', NEW.id;
|
|
|
|
-- Get the edge function URL from environment
|
|
edge_function_url := current_setting('app.base_url', true) || '/functions/v1/handle-order-paid';
|
|
|
|
-- Prepare order data
|
|
order_data := json_build_object(
|
|
'order_id', NEW.id,
|
|
'user_id', NEW.user_id,
|
|
'total_amount', NEW.total_amount,
|
|
'payment_method', NEW.payment_method,
|
|
'payment_provider', NEW.payment_provider
|
|
);
|
|
|
|
-- Call the edge function asynchronously via pg_net
|
|
-- We use pg_net to avoid blocking the transaction
|
|
PERFORM net.http_post(
|
|
url := edge_function_url,
|
|
headers := json_build_object(
|
|
'Content-Type', 'application/json',
|
|
'Authorization', 'Bearer ' || current_setting('app.service_role_key', true)
|
|
),
|
|
body := order_data
|
|
);
|
|
|
|
RAISE NOTICE 'Called handle-order-paid for order %', NEW.id;
|
|
|
|
RETURN NEW;
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
-- Log error but don't fail the transaction
|
|
RAISE WARNING 'Failed to call handle-order-paid for order %: %', NEW.id, SQLERRM;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- ============================================================================
|
|
-- Trigger: on_order_paid
|
|
-- Purpose: Fires handle_paid_order() when order payment status changes
|
|
-- ============================================================================
|
|
DROP TRIGGER IF EXISTS on_order_paid ON orders;
|
|
|
|
CREATE TRIGGER on_order_paid
|
|
AFTER UPDATE ON orders
|
|
FOR EACH ROW
|
|
WHEN (NEW.payment_status = 'paid' AND OLD.payment_status IS DISTINCT FROM NEW.payment_status)
|
|
EXECUTE FUNCTION handle_paid_order();
|
|
|
|
-- ============================================================================
|
|
-- Comments for documentation
|
|
-- ============================================================================
|
|
COMMENT ON FUNCTION handle_paid_order() IS 'Triggered when order payment_status becomes "paid". Calls handle-order-paid edge function to handle access grants, notifications, and Meet link creation.';
|
|
COMMENT ON TRIGGER on_order_paid ON orders IS 'Fires handle_paid_order() function when payment status changes to paid';
|
|
|
|
-- ============================================================================
|
|
-- Grant necessary permissions
|
|
-- ============================================================================
|
|
GRANT EXECUTE ON FUNCTION handle_paid_order() TO postgres;
|
|
GRANT USAGE ON SCHEMA net TO postgres;
|