支付
学习如何在 MkSaaS 中设置和使用支付
MkSaaS 支持多种支付提供商,您可以根据需要选择合适的支付方案。
所有提供商使用同一套应用流程:服务端 Action 创建托管结账,支付平台将用户重定向回
/payment,签名验证后的 Webhook 再更新共享的支付表。用户权益以 Webhook 写入的
数据库状态为准,不能只依赖浏览器重定向结果。
支付提供商
Stripe
全球最流行的支付平台,支持一次性支付和订阅
Creem
面向独立开发者的支付平台,内置税务合规和订阅管理
Waffo Pancake
面向独立开发者的支付平台,提供托管结账、消费者门户和全球税务合规
自定义支付提供商
MkSaaS 支持扩展新的支付提供商:
- 在
src/payment/provider目录中创建新的文件 - 从
types.ts实现PaymentProvider接口 - 在
index.ts中更新支付服务提供商选择逻辑
示例实现:
import {
type CheckoutResult,
type CreateCheckoutParams,
type CreatePortalParams,
type PaymentProvider,
type PortalResult,
} from '@/payment/types';
export class MyProvider implements PaymentProvider {
readonly requiresCustomerId = true;
readonly hostsPostCheckoutPage = false;
public async createCheckout(params: CreateCheckoutParams): Promise<CheckoutResult> {
// 创建结账会话的实现
}
public async createCustomerPortal(params: CreatePortalParams): Promise<PortalResult> {
// 创建客户门户的实现
}
public async handleWebhookEvent(payload: string, signature: string): Promise<void> {
// 处理 webhook 事件的实现
}
public getProviderName(): string {
return 'MyProvider';
}
}两个可选标记用于描述提供商差异:
requiresCustomerId:客户门户是否需要已保存的支付平台客户 ID。hostsPostCheckoutPage:支付平台是否自行托管支付完成后的确认页。
先在 src/types/index.d.ts 的 PaymentConfig['provider'] 中加入提供商名称,
再在 src/payment/index.ts 注册延迟创建工厂:
import { MyProvider } from './provider/my-provider';
const providerRegistry: Partial<
Record<PaymentProviderName, PaymentProviderFactory>
> = {
stripe: () => new StripeProvider(),
creem: () => new CreemProvider(),
waffo: () => new WaffoProvider(),
'my-provider': () => new MyProvider(),
};Webhook 路由只有在事件已处理或被明确忽略后才返回 200。签名或载荷无效时返回
400,处理失败时返回 500,以便支付平台安全重试。
MkSaaS文档