Payment
Supported Providers
| Provider | Modes | Webhook endpoint |
|---|---|---|
| Stripe | One-time + subscriptions | POST /api/payment/notify/stripe |
| PayPal | One-time + subscriptions | POST /api/payment/notify/paypal |
| Alipay | One-time | POST /api/payment/notify/alipay |
| WeChat Pay | One-time + subscriptions | POST /api/payment/notify/wechat |
| Creem | One-time + subscriptions | POST /api/payment/notify/creem |
Credentials are configured in admin panel → Settings → Payment (e.g. stripe_secret_key, stripe_publishable_key, stripe_signing_secret; alipay_app_id / alipay_private_key / alipay_public_key; wechat_app_id / wechat_mch_id / wechat_api_v3_key …). Same-named env vars (STRIPE_SECRET_KEY etc.) work as fallbacks.
Pricing Catalog
Products live in src/config/pricing.ts — the server-side source of truth; prices sent from the client are ignored.
{
productId: 'starter_monthly',
productName: 'Starter',
description: 'Starter Monthly',
type: PaymentType.SUBSCRIPTION, // or PaymentType.ONE_TIME
priceInCents: 900,
currency: 'usd',
credits: 5000,
creditsValidDays: 30,
plan: { name: 'starter', interval: 'month', intervalCount: 1 },
}Default product keys: starter|pro|enterprise × monthly|yearly|lifetime.
Checkout Flow
- Client calls
POST /api/payment/checkoutwith{ product_id, payment_provider, redirect } - Server validates the product against the catalog, creates an order, and returns
{ checkout_url } - User pays on the provider's page, then returns via
/api/payment/callback?order_no=...&redirect=... - The provider's webhook (
/api/payment/notify/[provider]) is the reliable completion path: it marks the orderPAID, creates the subscription record if recurring, and grants credits
Always configure the webhook in the provider dashboard — the synchronous callback is only a fallback.