Payment Integrations
Payment Integrations
Component File: src/features/admin/components/PaymentIntegrations.tsx Route / navigation: Path /administration, Zustand administrationTool = payment-integrations. See 00-ADMINISTRATION-HUB.md. Access Level: Parent Org Only Last Updated: March 27, 2026 Status: ✅ Implemented
Overview
Payment Integrations helps parent organization admins connect Stripe so online gifts can settle to the nonprofit’s bank account. The setup row exposes three actions: Create new Stripe account (Express accounts.create when no Connect is resolved on the ancestor chain, otherwise resume onboarding—including Standard accounts, which skip Stripe Account Links and return without a new tab), Connect Stripe account (dialog; existing_stripe_account_id for Express / Standard / Custom connected accounts on the platform; Standard saves immediately, then Check connection), and Check connection. Routing and application fees are handled by existing checkout/payment Edge Functions after the org row has stripe_account_id.
Strings: User-visible text lives under admin.paymentIntegrationsPage in src/i18n/locales/*/auth.json (including `stripeInvalidRequest`, `connectCreateFailedGeneric` for clearer Connect setup toasts).
Access Control
> ⚠️ PARENT ORG ONLY: This tool is restricted to users with the parent_org role. Fund users do NOT have access.
| User Type | Access |
|-----------|--------|
| **Parent Org (`parent_org`)** | ✅ Full access |
| **Fund User (`fund_user`)** | ❌ No access |
| **Staff** | ❌ No access |
Supported processor
| Processor | Status | Notes |
|-----------|--------|--------|
| **Stripe (Connect Express)** | ✅ Active | Only supported path for donation processing in this screen |
When `legacy_direct` applies (no Connect on the ancestor chain but the org is under `DIRECT_STRIPE_PAYOUT_ORG_ID`), the status card still reflects platform account details from Stripe—same as checkout routing. See STRIPE-SETUP-GUIDE.md § *Shared payment routing*.
UI (high level)
- Centered primary card: One centered setup/status card with a compact action row.
- Setup tile/card behavior: Three buttons only—Create new Stripe account, Connect Stripe account (modal with
acct_…), Check connection—plus parent-only gating and legacy/migration alerts as today. - Status tile: Separates
ready,in progress,finishing setup(webhook propagation lag), andneeds attention. - Actions: Check connection, Continue setup, Payout dashboard, Update bank details, Sync now, and History (state-dependent).
- No manual test button: Replaced by Check connection + automatic refetch on focus/return/pending intervals.
Stripe integration (technical)
Uses checkStripeConnection(), createStripeConnectOrganization, createStripeConnectAccountLink, syncStripeSubscriptions, fetchSyncLogs, and related Edge Functions. See STRIPE-SETUP-GUIDE.md and STRIPE-CONNECT-UPGRADE.md.
Connection status vs checkout: The `check-stripe-connection` Edge Function uses the same `resolvePaymentTargetForOrg` logic as `create-payment-intent`, `create-checkout-session`, and `create-event-checkout`. Child funds under a parent with Connect (or under `DIRECT_STRIPE_PAYOUT_ORG_ID` for `legacy_direct`) see `active` / `connect_mode` consistent with whether online card payments can be created—not only whether the current org row has stripe_account_id.
const status = await checkStripeConnection(organizationId);
// Returns: { connected, status, account, error, lastChecked, ... }await syncStripeSubscriptions(paymentCheckOrgUuid); // org UUID scope
const logs = await fetchSyncLogs('stripe', 20); // reads sync_logsNotes
checkStripeConnection(organizationId?)accepts an optional org UUID; this page passespaymentCheckOrgUuidfor tenant-scoped checks.- Sync is organization-scoped (
organization_id) and should never send Stripe account IDs (acct_...) as the sync input. - Sync history in the dialog comes from
sync_logsviafetchSyncLogs('stripe', 20). - Express actions (“Express Dashboard”, “Update bank details”) are shown when
connect_mode === 'express'. `legacy_direct` is not shown as green “Connected”: when `REQUIRE_STRIPE_CONNECT_FOR_DONATIONS` is on (default), `check-stripe-connection` returns `needs_connect` with `legacy_direct_blocked` (same rule as donation/event checkout). If ops sets `REQUIRE_STRIPE_CONNECT_FOR_DONATIONS=false`, the UI shows Platform account with a warning until Connect is completed. - Stripe onboarding returns to
/admin/stripe-onboardingand the app routes users back to Administration → Payment Integrations automatically. - Connect setup failures map structured error codes from
create-stripe-connect-account(connect_not_enabled,already_connected,stripe_resume_account_missing,invalid_account_id,stripe_account_not_found,unsupported_account_type,stripe_account_already_linked,database_error,permission_denied,missing_authorization,invalid_authorization,method_not_allowed,connect_create_failed, `stripe_invalid_request`, etc.) so the UI can show actionable customer-safe messages (API `message` preferred when present). - Stripe platform-not-enabled onboarding failures are explicitly mapped to
connect_not_enabled(based on Stripe message pattern), avoiding misleading generic setup errors. - The client error adapter now assigns stable fallback codes for non-JSON/network invoke failures (instead of showing a generic unknown error).
- Unknown setup failures include a customer-safe support reference timestamp in the toast for easier ops triage.
- Readiness is intentionally conservative: UI treats the connection as fully ready when Stripe account status is active and org DB flags (
stripe_charges_enabled) are updated byplatform-webhook.
Related documentation
- STRIPE-SETUP-GUIDE.md — Platform secrets, webhooks, Connect
- 00-ADMINISTRATION-HUB.md — Hub navigation
Synced from IFMmvp-Frontend documentation: pages/administration/03-PAYMENT-INTEGRATIONS.md
Ready to Get Started?
See how Alignmint can simplify your nonprofit's operations. Schedule a free demo with our team and we'll walk you through everything.
Questions? Email us at steven@getalignmint.org