Payment Configuration
TinyShip payment system configuration guide
TinyShip supports seven payment methods: WeChat Pay, Alipay, Stripe, PayPal, Creem, Dodo Payments, and Waffo Pancake, with three payment modes: one-time payment, subscription, and credits (WeChat Pay and Alipay only support one-time and credits).
Credits System: For AI credit consumption configuration, see Credits System Configuration.
AI Quick Setup: Users with Agent Skills installed can tell their AI "help me configure payment" to use the tinyship-payment skill for interactive setup.
Pricing Mode: Static vs Dynamic
Before configuring payment plans, decide which pricing mode to use:
- Static pricing (default): Plans live in
config/payment.tsand ship with your code. Best for projects with fixed plans that rarely change. The "Configure Payment Plans" section below covers static mode - Dynamic pricing: Plans are stored in the database and managed in real time from the admin panel at
/admin/pricing, with no redeployment. Adds strikethrough pricing, locale filtering, custom ordering, and more. See Dynamic Pricing
The two modes can be switched anytime via the PRICING_MODE environment variable, without affecting each other.
Related Pages
| Page | Path | Description |
|---|---|---|
| Pricing | /pricing | Display all payment plans |
| Payment Success | /payment-success | Payment success redirect |
| Payment Cancel | /payment-cancel | Payment cancel redirect |
| Dashboard | /dashboard | View subscription status and order history |
Supported Payment Methods
| Method | One-time | Subscription | Credits | Primary Market | Currency |
|---|---|---|---|---|---|
| WeChat Pay | Yes | No | Yes | China | CNY |
| Alipay | Yes | No | Yes | China | CNY |
| Stripe | Yes | Yes | Yes | Global | Multi-currency |
| PayPal | Yes | Yes | Yes | Global | Multi-currency |
| Creem | Yes | Yes | Yes | Global | USD, EUR, etc. |
| Dodo Payments | Yes | Yes | Yes | Global | Multi-currency |
| Waffo Pancake | Yes | Yes | Yes | Global | Multi-currency (no CNY for subscriptions) |
Configuration Overview
Configure through providers in config/payment.ts. Choose based on your project needs:
- Chinese users: Recommend WeChat Pay or Alipay
- International users: Recommend Stripe or PayPal
- Easier approval: Recommend Creem
- Tax and compliance offloading: Recommend Dodo Payments or Waffo Pancake in Merchant of Record mode
Important: During local development, prefer test/sandbox mode (Stripe and Creem support this, WeChat Pay does not). For WeChat Pay testing, use real 0.01 CNY payments.
Detailed Configuration Documents
Choose the payment methods you need:
Recommended for Chinese market, supports QR code payment
Recommended for the Chinese market
International market, supports subscriptions and one-time payments
Global market, supports subscriptions and one-time payments
Recommended for indie developers going global, easy approval
Merchant of Record payments for global SaaS and digital products
Global MoR mode with hosted checkout
Database-driven real-time pricing management, no redeployment needed
Local development testing and Webhook debugging
Configure Payment Plans
Configure pricing plans through plans in config/payment.ts. Plans configured here will automatically appear on the /pricing page.
Dynamic pricing: If you need to adjust pricing plans in real time without redeploying, use the dynamic pricing feature. Once enabled, plans are read from the database and can be modified anytime from the admin panel at /admin/pricing.
Plan Types
| Type | Description | Use Case |
|---|---|---|
| One-time | Pay once for permanent access | Lifetime membership, software license |
| Subscription | Recurring billing by period | SaaS services, monthly membership |
| Credits | Buy credits, consume by usage | AI chat, image generation |
Plan Configuration Structure
Each plan requires the following fields:
plans: {
lifetime: {
provider: 'wechat', // Payment provider: 'wechat' | 'alipay' | 'stripe' | 'paypal' | 'creem' | 'dodo'
id: 'lifetime', // Unique plan identifier
amount: 199.00, // Price amount
originalAmount: 299.00, // Original price (for showing discount)
currency: 'CNY', // Currency: 'CNY' | 'USD' | 'EUR' etc.
recommended: true, // Whether to highlight on pricing page
hidden: false, // Whether to hide from pricing page
duration: {
months: 999999, // Duration in months (999999 = lifetime)
type: 'one_time' // Type: 'one_time' | 'recurring' | 'credits'
},
// Creem-specific field
creemProductId: 'prod_xxx', // Creem product ID (required for Creem)
// Dodo Payments-specific field
dodoProductId: 'pdt_xxx', // Dodo product ID (required for Dodo Payments)
// Stripe-specific field
stripePriceId: 'price_xxx', // Stripe price ID (required for Stripe subscriptions)
i18n: { /* i18n config */ }
}
}Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | Payment provider to use |
id | string | Yes | Unique plan identifier for API calls |
amount | number | Yes | Price amount |
originalAmount | number | No | Original price for showing discounts |
currency | string | Yes | Currency code (ISO 4217) |
recommended | boolean | No | Highlight on pricing page |
hidden | boolean | No | Hide from pricing page |
duration.months | number | Yes | Duration in months |
duration.type | string | Yes | Payment type |
creemProductId | string | Creem required | Creem platform product ID |
dodoProductId | string | Dodo Payments required | Dodo Payments platform product ID |
stripePriceId | string | Stripe sub required | Stripe platform price ID |
Internationalization
Each plan needs multi-language support:
i18n: {
'en': {
name: 'Monthly Plan',
description: 'Perfect for short-term projects',
duration: 'month',
features: ['All premium features', 'Priority support']
},
'zh-CN': {
name: '月度订阅',
description: '每月订阅,灵活管理',
duration: '月',
features: ['所有高级功能', '优先支持']
}
}Complete Example
Here's a complete lifetime plan configuration example:
lifetime: {
provider: 'wechat',
id: 'lifetime',
amount: process.env.NODE_ENV === 'development' ? 0.01 : 199.00,
originalAmount: 299.00,
currency: 'CNY',
recommended: true,
duration: {
months: 999999,
type: 'one_time'
},
i18n: {
'en': {
name: 'TinyShip Complete',
description: 'Get lifetime access to the complete SaaS starter kit',
duration: 'lifetime',
features: [
'Complete SaaS template source code',
'Free lifetime updates',
'Priority customer support',
'Access to private GitHub repository'
]
},
'zh-CN': {
name: 'TinyShip 完整版',
description: '获得完整SaaS启动套件的终身访问权限',
duration: '终身',
features: [
'完整SaaS模板源码',
'终身免费更新',
'优先客户支持',
'访问GitHub私有仓库'
]
}
}
}Development Testing: The example uses process.env.NODE_ENV === 'development' ? 0.01 : 199.00 to differentiate between development and production prices for easy testing.
Payment Flow
- User selects plan → 2. Create order → 3. Redirect to payment → 4. Handle callback → 5. Update status
API Endpoints
// Initiate payment
POST /api/payment/initiate
{
"planId": "monthly",
"provider": "stripe"
}
// Query payment status
GET /api/payment/query/:orderId
// Webhook handler
POST /api/payment/webhook/:provider
// Cancel payment
POST /api/payment/cancel/:orderIdReference Documentation
- Payment Testing Guide - Local development and Webhook debugging
- Credits System Guide - Credit recharge and consumption