Skip to content

[Phase 0] Implement 8 missing outbound Edge Functions for payment integration #100

@TortoiseWolfe

Description

@TortoiseWolfe

Background

A payment-readiness audit (2026-05-20) discovered that 8 outbound Edge Functions called by browser code do not exist in supabase/functions/. Without them, clicking "Pay" on /payment-demo fails immediately with a 404 against a nonexistent function URL. No customer can complete a payment until this is done.

Discovered via:

grep -rohE "functions/v1/[a-z-]+" src/lib/payments src/components/payment

vs.

ls supabase/functions/

The TODO comment in src/lib/payments/stripe.ts:48 confirms: // (Edge Function will be created in Phase 5) — Phase 5 was never completed.

What's already shipped

The webhook (inbound) side is fully built and verified:

  • stripe-webhook — 425 LOC, signature verification, idempotency, payment_results writes
  • paypal-webhook — 317 LOC, same
  • send-payment-email — notification skeleton

These serve as the canonical patterns for the new functions (Deno serve, Stripe SDK via esm.sh, Supabase service client). New functions should mirror their structure.

The browser-side fetch sites are also shipped (3 in src/lib/payments/stripe.ts, 3 in src/lib/payments/paypal.ts, 2 in SubscriptionManager.tsx) — they expect specific request/response shapes documented at the call sites.

The 8 missing functions

# Function Browser caller Purpose
1 create-stripe-checkout src/lib/payments/stripe.ts:50 Create a Stripe Checkout Session for one-off charge
2 verify-stripe-session src/lib/payments/stripe.ts:92 Verify Stripe session ID post-redirect
3 create-stripe-subscription src/lib/payments/stripe.ts:135 Create Stripe subscription checkout
4 create-paypal-order src/lib/payments/paypal.ts:74 Create PayPal order (one-off)
5 capture-paypal-order src/lib/payments/paypal.ts:101 Capture approved PayPal order
6 create-paypal-subscription src/lib/payments/paypal.ts:145 Create PayPal billing subscription
7 cancel-subscription src/components/payment/SubscriptionManager/SubscriptionManager.tsx:87 Cancel subscription (Stripe or PayPal)
8 resume-subscription src/components/payment/SubscriptionManager/SubscriptionManager.tsx:126 Resume paused subscription

Sub-issues

Each sub-issue is a self-contained PR-sized chunk:

Total: ~20h focused implementation. Realistic 2–3 working days with reviews.

Implementation pattern (reference)

Each function follows the structure already established in supabase/functions/stripe-webhook/index.ts:

import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import Stripe from 'https://esm.sh/stripe@14.21.0?target=deno';

const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY') || '', {
  apiVersion: '2024-06-20',
  httpClient: Stripe.createFetchHttpClient(),
});
const supabase = createClient(
  Deno.env.get('NEXT_PUBLIC_SUPABASE_URL')!,
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);

serve(async (req) => {
  // 1. CORS preflight (use _shared/cors.ts from #106)
  // 2. Auth: verify caller's JWT, extract user_id (use _shared/auth.ts from #106)
  // 3. Parse body
  // 4. Load related DB row (e.g., payment_intents) with RLS check
  // 5. Call Stripe/PayPal SDK with idempotency_key (from _shared/idempotency.ts in #106)
  // 6. Write provider response to DB
  // 7. Return response in expected shape
});

Each PR should:

  • Add the function under supabase/functions/<name>/index.ts
  • Add Deno unit tests under supabase/functions/<name>/index.test.ts
  • Un-skip the matching E2E tests in tests/e2e/payment/ (only those that exercise the newly-shipped function)
  • Update docs/PAYMENT-DEPLOYMENT.md if the deployment story for the function differs from the pattern

Recommended order: ship #106 (shared infra) FIRST, then #101 (Stripe one-off — the MVP critical path), then the others in any order.

Acceptance

Phase 0 (this epic) is complete when:

  • All 8 functions exist under supabase/functions/<name>/index.ts
  • Each has Deno unit tests + at least one E2E test un-skipped that exercises it
  • tests/e2e/payment/01-stripe-onetime.spec.ts:3 ('should complete one-time payment successfully') passes against Stripe sandbox
  • docs/PAYMENT-DEPLOYMENT.md Step 4.2 is no longer marked "NOT YET SHIPPED"
  • The "Status of the integration" table at the top of that doc shows Outbound Edge Functions as ✅ shipped

Related

🤖 Created from audit on 2026-05-20

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgap-auditIdentified during 2026-04-25 planned-vs-shipped auditpriority:p1High — fix soon (stability hotspot, low-hanging fruit, single-decision unlocks)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions