feat(data): add paywall payment APIs
This commit is contained in:
@@ -10,6 +10,10 @@ export const ChatHistoryResponseSchema = z.object({
|
||||
total: z.number().default(0),
|
||||
limit: z.number(),
|
||||
offset: z.number(),
|
||||
isVip: z.boolean(),
|
||||
privateFreeLimit: z.number(),
|
||||
privateUsedToday: z.number(),
|
||||
privateCanViewFree: z.boolean(),
|
||||
});
|
||||
|
||||
export type ChatHistoryResponseInput = z.input<typeof ChatHistoryResponseSchema>;
|
||||
|
||||
@@ -4,12 +4,21 @@
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const ChatMessageSchema = z.object({
|
||||
role: z.string(),
|
||||
content: z.string(),
|
||||
id: z.string().default(""),
|
||||
createdAt: z.string().default(""),
|
||||
});
|
||||
export const ChatMessageSchema = z
|
||||
.object({
|
||||
role: z.string(),
|
||||
content: z.string(),
|
||||
id: z.string().default(""),
|
||||
createdAt: z.string().default(""),
|
||||
created_at: z.string().optional(),
|
||||
isPrivate: z.boolean().nullable().default(null),
|
||||
privateLocked: z.boolean().nullable().default(null),
|
||||
privateHint: z.string().nullable().default(null),
|
||||
})
|
||||
.transform(({ created_at, ...data }) => ({
|
||||
...data,
|
||||
createdAt: data.createdAt || created_at || "",
|
||||
}));
|
||||
|
||||
export type ChatMessageInput = z.input<typeof ChatMessageSchema>;
|
||||
export type ChatMessageData = z.output<typeof ChatMessageSchema>;
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const ChatBlockDetailSchema = z.object({
|
||||
type: z.string(),
|
||||
usedToday: z.number(),
|
||||
limit: z.number(),
|
||||
});
|
||||
|
||||
export const ChatSendResponseSchema = z.object({
|
||||
mode: z.string().default(""),
|
||||
reply: z.string(),
|
||||
@@ -17,7 +23,15 @@ export const ChatSendResponseSchema = z.object({
|
||||
isGuest: z.boolean().default(false),
|
||||
// 函数式 default —— 每次 parse 时重新调 Date.now()(后端不返回 timestamp 时用当下时间)
|
||||
timestamp: z.number().default(() => Date.now()),
|
||||
blocked: z.boolean().nullable().default(null),
|
||||
blockReason: z.string().nullable().default(null),
|
||||
blockDetail: ChatBlockDetailSchema.nullable().default(null),
|
||||
paywallTriggered: z.boolean(),
|
||||
showUpgrade: z.boolean(),
|
||||
imageType: z.string().nullable().default(null),
|
||||
imageUrl: z.string().nullable().default(null),
|
||||
});
|
||||
|
||||
export type ChatSendResponseInput = z.input<typeof ChatSendResponseSchema>;
|
||||
export type ChatSendResponseData = z.output<typeof ChatSendResponseSchema>;
|
||||
export type ChatBlockDetailData = z.output<typeof ChatBlockDetailSchema>;
|
||||
|
||||
@@ -12,3 +12,5 @@ export * from "./image_upload_response";
|
||||
export * from "./send_message_request";
|
||||
export * from "./stt_data";
|
||||
export * from "./sync_message";
|
||||
export * from "./unlock_private_request";
|
||||
export * from "./unlock_private_response";
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 私密消息解锁请求
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const UnlockPrivateRequestSchema = z.object({
|
||||
messageId: z.string(),
|
||||
});
|
||||
|
||||
export type UnlockPrivateRequestInput = z.input<
|
||||
typeof UnlockPrivateRequestSchema
|
||||
>;
|
||||
export type UnlockPrivateRequestData = z.output<
|
||||
typeof UnlockPrivateRequestSchema
|
||||
>;
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 私密消息解锁响应
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const UnlockPrivateReasonSchema = z.enum([
|
||||
"ok",
|
||||
"quota_exceeded",
|
||||
"not_private",
|
||||
"not_found",
|
||||
]);
|
||||
|
||||
export const UnlockPrivateResponseSchema = z.object({
|
||||
unlocked: z.boolean(),
|
||||
content: z.string().nullable(),
|
||||
showUpgrade: z.boolean(),
|
||||
paywallTriggered: z.boolean(),
|
||||
privateFreeLimit: z.number(),
|
||||
privateUsedToday: z.number(),
|
||||
reason: UnlockPrivateReasonSchema,
|
||||
});
|
||||
|
||||
export type UnlockPrivateReason = z.output<typeof UnlockPrivateReasonSchema>;
|
||||
export type UnlockPrivateResponseInput = z.input<
|
||||
typeof UnlockPrivateResponseSchema
|
||||
>;
|
||||
export type UnlockPrivateResponseData = z.output<
|
||||
typeof UnlockPrivateResponseSchema
|
||||
>;
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 创建支付订单请求
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const PayChannelSchema = z.enum(["stripe", "ezpay"]);
|
||||
|
||||
export const CreatePaymentOrderRequestSchema = z.object({
|
||||
planId: z.string(),
|
||||
payChannel: PayChannelSchema,
|
||||
autoRenew: z.boolean(),
|
||||
});
|
||||
|
||||
export type PayChannel = z.output<typeof PayChannelSchema>;
|
||||
export type CreatePaymentOrderRequestInput = z.input<
|
||||
typeof CreatePaymentOrderRequestSchema
|
||||
>;
|
||||
export type CreatePaymentOrderRequestData = z.output<
|
||||
typeof CreatePaymentOrderRequestSchema
|
||||
>;
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 创建支付订单响应
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const CreatePaymentOrderResponseSchema = z.object({
|
||||
orderId: z.string(),
|
||||
payParams: z.record(z.string(), z.unknown()),
|
||||
});
|
||||
|
||||
export type CreatePaymentOrderResponseInput = z.input<
|
||||
typeof CreatePaymentOrderResponseSchema
|
||||
>;
|
||||
export type CreatePaymentOrderResponseData = z.output<
|
||||
typeof CreatePaymentOrderResponseSchema
|
||||
>;
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @file Payment schema barrel.
|
||||
*/
|
||||
|
||||
export * from "./create_payment_order_request";
|
||||
export * from "./create_payment_order_response";
|
||||
export * from "./payment_order_status_response";
|
||||
export * from "./payment_plan";
|
||||
export * from "./payment_plans_response";
|
||||
export * from "./payment_vip_status_response";
|
||||
export * from "./payment_websocket_event";
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 支付订单状态响应
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const PaymentOrderStatusSchema = z.enum(["pending", "paid", "failed"]);
|
||||
|
||||
export const PaymentOrderStatusResponseSchema = z.object({
|
||||
orderId: z.string(),
|
||||
status: PaymentOrderStatusSchema,
|
||||
orderType: z.string(),
|
||||
planId: z.string(),
|
||||
});
|
||||
|
||||
export type PaymentOrderStatus = z.output<typeof PaymentOrderStatusSchema>;
|
||||
export type PaymentOrderStatusResponseInput = z.input<
|
||||
typeof PaymentOrderStatusResponseSchema
|
||||
>;
|
||||
export type PaymentOrderStatusResponseData = z.output<
|
||||
typeof PaymentOrderStatusResponseSchema
|
||||
>;
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 支付套餐
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
const PaymentPlanWireSchema = z.object({
|
||||
plan_id: z.string(),
|
||||
plan_name: z.string(),
|
||||
order_type: z.string(),
|
||||
amount_cents: z.number(),
|
||||
currency: z.string(),
|
||||
vip_days: z.number().nullable(),
|
||||
dol_amount: z.number().nullable(),
|
||||
});
|
||||
|
||||
export const PaymentPlanSchema = z
|
||||
.preprocess((value) => {
|
||||
if (!value || typeof value !== "object") return value;
|
||||
const data = value as Record<string, unknown>;
|
||||
if ("planId" in data) {
|
||||
return {
|
||||
plan_id: data.planId,
|
||||
plan_name: data.planName,
|
||||
order_type: data.orderType,
|
||||
amount_cents: data.amountCents,
|
||||
currency: data.currency,
|
||||
vip_days: data.vipDays,
|
||||
dol_amount: data.dolAmount,
|
||||
};
|
||||
}
|
||||
return value;
|
||||
}, PaymentPlanWireSchema)
|
||||
.transform((data) => ({
|
||||
planId: data.plan_id,
|
||||
planName: data.plan_name,
|
||||
orderType: data.order_type,
|
||||
amountCents: data.amount_cents,
|
||||
currency: data.currency,
|
||||
vipDays: data.vip_days,
|
||||
dolAmount: data.dol_amount,
|
||||
}));
|
||||
|
||||
export type PaymentPlanInput = z.input<typeof PaymentPlanSchema>;
|
||||
export type PaymentPlanData = z.output<typeof PaymentPlanSchema>;
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 支付套餐列表响应
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
import { PaymentPlanSchema } from "./payment_plan";
|
||||
|
||||
export const PaymentPlansResponseSchema = z.object({
|
||||
plans: z.array(PaymentPlanSchema),
|
||||
});
|
||||
|
||||
export type PaymentPlansResponseInput = z.input<
|
||||
typeof PaymentPlansResponseSchema
|
||||
>;
|
||||
export type PaymentPlansResponseData = z.output<
|
||||
typeof PaymentPlansResponseSchema
|
||||
>;
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* VIP 状态响应
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const PaymentVipStatusResponseSchema = z.object({
|
||||
isVip: z.boolean(),
|
||||
vipExpiresAt: z.string().nullable(),
|
||||
});
|
||||
|
||||
export type PaymentVipStatusResponseInput = z.input<
|
||||
typeof PaymentVipStatusResponseSchema
|
||||
>;
|
||||
export type PaymentVipStatusResponseData = z.output<
|
||||
typeof PaymentVipStatusResponseSchema
|
||||
>;
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 支付 WebSocket 事件
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
export const PaymentSuccessVipEventSchema = z.object({
|
||||
type: z.literal("payment_success"),
|
||||
orderId: z.string(),
|
||||
payType: z.literal("vip"),
|
||||
planName: z.string(),
|
||||
vipExpiresAt: z.string().nullable(),
|
||||
});
|
||||
|
||||
export const PaymentSuccessDolEventSchema = z.object({
|
||||
type: z.literal("payment_success"),
|
||||
orderId: z.string(),
|
||||
payType: z.literal("dol"),
|
||||
planName: z.string(),
|
||||
dolAmount: z.number(),
|
||||
dolBalance: z.number(),
|
||||
});
|
||||
|
||||
export const PaymentFailedEventSchema = z.object({
|
||||
type: z.literal("payment_failed"),
|
||||
orderId: z.string(),
|
||||
info: z.string(),
|
||||
});
|
||||
|
||||
export const PaymentSuccessEventSchema = z.discriminatedUnion("payType", [
|
||||
PaymentSuccessVipEventSchema,
|
||||
PaymentSuccessDolEventSchema,
|
||||
]);
|
||||
|
||||
export const PaymentWebSocketEventSchema = z.union([
|
||||
PaymentSuccessEventSchema,
|
||||
PaymentFailedEventSchema,
|
||||
]);
|
||||
|
||||
export type PaymentSuccessVipEventData = z.output<
|
||||
typeof PaymentSuccessVipEventSchema
|
||||
>;
|
||||
export type PaymentSuccessDolEventData = z.output<
|
||||
typeof PaymentSuccessDolEventSchema
|
||||
>;
|
||||
export type PaymentFailedEventData = z.output<typeof PaymentFailedEventSchema>;
|
||||
export type PaymentSuccessEventData = z.output<typeof PaymentSuccessEventSchema>;
|
||||
export type PaymentWebSocketEventInput = z.input<
|
||||
typeof PaymentWebSocketEventSchema
|
||||
>;
|
||||
export type PaymentWebSocketEventData = z.output<
|
||||
typeof PaymentWebSocketEventSchema
|
||||
>;
|
||||
Reference in New Issue
Block a user