📦 Billing (ECPay 綠界)
Module ID:
@saas/billing-ecpay| Version: 1.0.0
ECPay 全方位金流 AIO 定期定額 billing integration — CheckMacValue (SHA256), 定期定額 recurring orders (PeriodType/Frequency/ExecTimes), dual notify route handlers (ReturnURL + PeriodReturnURL), renewal scheduler, and idempotent event processing. Taiwan-local PaymentProvider for the @saas stack.
Installation
npx shadcn@latest add @saas/billing-ecpayDependencies
@saas/billing
Routes
app/api/billing/ecpay/return/route.tsapp/api/billing/ecpay/period/route.ts
Server Actions
No server actions
Database Tables
planssubscriptionspayment_events
Environment Variables
[object Object][object Object][object Object][object Object][object Object][object Object]
Post-Install Steps
Step 1 (env-wire): Add ECPAY_MERCHANT_ID, ECPAY_HASH_KEY, ECPAY_HASH_IV to .env.local. Use sandbox values for development (MerchantID: 3002607). Never commit to git.
Step 2 (command): Set BILLING_PROVIDER=ecpay in .env.local to activate the ECPay provider.
echo 'BILLING_PROVIDER=ecpay' >> .env.localStep 3 (db-generate): Generate Drizzle migrations for the billing tables (plans, subscriptions, payment_events). These tables are shared with @saas/billing — skip if already migrated.
pnpm db:generateStep 4 (db-migrate): Apply billing migrations to your database.
pnpm db:migrateStep 5 (manual): planId format for createCheckout: '{interval}:{amountTWD}:{description}' e.g. 'month:299:Pro Plan'. The amount must be a positive integer (TWD). Wire your pricing tiers to use this format as planId.
Step 6 (manual): Register notify URLs in ECPay 廠商管理後台 → 系統開發設定: ReturnURL = https://yourdomain.com/api/billing/ecpay/return, PeriodReturnURL = https://yourdomain.com/api/billing/ecpay/period. For local dev use ngrok or similar tunneling.
Step 7 (manual): Renewal scheduler: set up a cron job (e.g. /api/cron/billing-reconcile) that calls provider.queryAndCheckRenewal(merchantTradeNo) for each active ECPay subscription. When needsRenewal=true, call provider.createCheckout() again to build a new 定期定額 order and send the consumer a re-subscribe link.
Step 8 (manual): ExecTimes caps: D/M periods max 999, Y periods max 99. The renewal scheduler rebuilds before exhaustion (default threshold: remaining < 3). Adjust ECPAY_RENEWAL_THRESHOLD as needed.
Step 9 (manual): Sandbox testing: use ECPay's test credit card (4311-9522-2222-2222, CVV 222, exp 2099/01) to simulate 定期定額 payments. Sandbox PeriodReturnURL is triggered automatically for the first 3 test cycles.
Step 10 (command): Run typecheck and lint to verify no import errors.
pnpm typecheck && pnpm lintLive Demo
Configure your deployed Next.js app URL via the VITEPRESS_DEMO_BASE environment variable, then rebuild to enable live iframe embeds.
API Demonstration
Server Actions note: Server Actions (
"use server") are not callable cross-origin. Use the "Try in Live App" link above to interact with them.