Payments — Code Map
API — apps/api/src/payments/
Module + DI
payments.module.ts— wires all services, adapters, controllers.onModuleInitregisters each provider intoPaymentProviderRegistry.
Providers (providers/)
payment-provider.registry.ts—Map<PaymentProviderType, PaymentProviderAdapter>withregister/get/getOrThrow/list.cardcom.provider.ts— LowProfile/Create + GetLpResult + ChargeWithToken. No webhook signature.getRefundCapability() → 'manual'.icredit.provider.ts— Rivhit hosted page.GroupPrivateTokenbody signature.meshulam.provider.ts— Light-API iframe + JSON IPN.webhookKey === credentials.apiKeysignature.morning.provider.ts— Single-URL Morning webhook (?org=…). Signature TBD (:941). Issues חשבונית/קבלה automatically.tranzila.provider.ts— Stub-grade adapter; signature returnstrue.
Services (services/)
payment.service.ts— orchestrator.createHostedPayment,createCourseHostedPayment,charge,createRecurring,refund(capability switch),completeManualRefundTask,verifyAndActivateReturn,sendPaymentReceipt.payment-transaction.service.ts— CRUD onpayment_transactions.upsertPending,completePendingBySubscriptionId,findByProviderTransactionId.payment-provider-config.service.ts— encrypted credential CRUD onpayment_provider_configs; redacted reads.payment-provider-clients.service.ts—payment_provider_clientsupserts (Morning client linkage).credential-encryption.service.ts— AES-256-GCM round trip. Key fromPAYMENT_CREDENTIALS_ENCRYPTION_KEY(32-byte hex).webhook-processing.service.ts— dispatchespayment.completed | payment.failed | subscription.renewed | subscription.cancelled | refund.completed | client.created. Cross-org guard on course entitlements (:215,:362).recurring-charge.service.ts— daily 02:00 UTC cron.FOR UPDATE SKIP LOCKEDsweep, charge-then-update, debt promotion at 3 fails.payment-method.service.ts—replacePaymentMethod(deactivate old, insert new),getActivePaymentMethod.debt.service.ts—clearDebt(subscriptionId)charges the accumulateddebtAmountInCentsand zeroes it.payment-analytics.service.ts— KPIs (collected this month, MRR snapshot).payment-monitoring.service.ts— drains the observability event bus into Sentry breadcrumbs.payment-observability.service.ts— typedemit(eventName, payload)interface; the central spine for all payment telemetry.
Controllers (controllers/)
payment.controller.ts—GET/POST /organizations/:orgId/payments[…]. Member-facing list, refund, refund-task complete, verify-return, transaction detail.payment-webhook.controller.ts—@Publicpath-style and query-style webhook entry points.payment-provider-config.controller.ts—GET/POST/PATCH/DELETE /organizations/:orgId/payment-config.card-registration.controller.ts— admin-initiates-card-on-file for a member, plus member-side equivalents.payment-analytics.controller.ts—GET /organizations/:orgId/payment-analytics/*.invoicing.controller.ts—/organizations/:orgId/invoicing/*proxy onto the provider’slistDocuments / getDocumentadapter methods.
DTOs (dto/)
refund.dto.ts—{ amountInCents?, reason? }.configure-provider.dto.ts—{ provider, credentials, config? }+ update variant.
Shared — libs/shared/src/lib/
schemas/payment.schema.ts— Zod schemas forPaymentTransactionResponse, refund DTOs, transaction filters.interfaces/payment-provider.ts(canonicalPaymentProviderAdaptercontract,ChargeRequest,RefundRequest,WebhookEvent,RefundCapability,ClientInfo, etc.).constants/platform-tiers.ts—tierHasFeatureconsumed byRequiresFeature.
DB — libs/db/src/lib/schema/
payments.ts—plans,subscriptions,member_payment_methods,payment_provider_configs,payment_transactions,invoicing_configs,payment_provider_clients,cancellation_requests.enums.ts—paymentProvider,planType,planInterval,subscriptionStatus,transactionStatus,transactionType,cancellationRequestStatus,taskType(includesmanual_refund,cancellation_review).
Web — apps/web/src/
components/payments/— owner dashboard widgets:transactions-table.tsx,kpi-cards.tsx,payment-tabs.tsx,refund-task-complete-dialog.tsx,cancellation-requests-list.tsx,cancellations-widget.tsx,recurring-charges-table.tsx,documents-table.tsx,payments-data-table.tsx,summary-detail-toggle.tsx,date-range-filter.tsx.components/subscriptions/cancel-subscription-dialog.tsx— member self-cancel flow.components/member/plan-card.tsx— member-facing plan/subscription summary.app/[lang]/(protected)/dashboard/payments/— owner payment console.app/[lang]/(protected)/dashboard/settings/checkout-return/page.tsx— Cardcom return page; callsverify-checkoutfor platform-billing.app/[lang]/buy/courses/[id]/page.tsx— public course buy page (handles Clerk email-code flow). Seecourses/code-map.md.
Tests
apps/api/src/payments/services/refund-flow.int.spec.ts— end-to-end refund integration test.apps/api/src/payments/services/payment-transaction.service.unit.spec.tsapps/api/src/payments/services/credential-encryption.service.unit.spec.tsapps/api/src/payments/providers/*.unit.spec.ts— per-provider adapter contract tests.apps/api/src/subscriptions/cancellation-flow.int.spec.ts— cancellation-request + refund handshake.
Env
PAYMENT_CREDENTIALS_ENCRYPTION_KEY— 64-char hex (32 bytes) AES-256-GCM key.API_BASE_URL— used to construct webhook URLs (payment.service.ts:128).FRONTEND_URL— used for cancellation-request review links.- Cardcom platform terminal:
PLATFORM_BILLING_TERMINAL_NUMBER,PLATFORM_BILLING_API_NAME,PLATFORM_BILLING_API_PASSWORD(seeplatform-billing/).