Sfoglia il codice sorgente

♻️ refactor(wechat-pay): separate schema definitions from entity files

- move WechatCouponStockSchema, CreateWechatCouponStockDto and UpdateWechatCouponStockDto from wechat-coupon-stock.entity.ts to new file wechat-coupon-stock.schema.ts
- move WechatCouponSchema, CreateWechatCouponDto and UpdateWechatCouponDto from wechat-coupon.entity.ts to new file wechat-coupon.schema.ts
- move WechatPayConfigSchema, CreateWechatPayConfigDto and UpdateWechatPayConfigDto from wechat-pay-config.entity.ts to new file wechat-pay-config.schema.ts
- update import paths in api routes to use new schema files

🐛 fix(wechat-pay): ensure proper error response status code

- fix query-stocks.ts to always return 500 status code on error instead of dynamic code
yourname 6 mesi fa
parent
commit
d8b3b2dd9b

+ 1 - 1
src/server/api/wechat-coupon-stocks/index.ts

@@ -1,6 +1,6 @@
 import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
 import { WechatCouponStock } from '@/server/modules/wechat-pay/wechat-coupon-stock.entity';
-import { WechatCouponStockSchema, CreateWechatCouponStockDto, UpdateWechatCouponStockDto } from '@/server/modules/wechat-pay/wechat-coupon-stock.entity';
+import { WechatCouponStockSchema, CreateWechatCouponStockDto, UpdateWechatCouponStockDto } from '@/server/modules/wechat-pay/wechat-coupon-stock.schema';
 import { authMiddleware } from '@/server/middleware/auth.middleware';
 
 const wechatCouponStockRoutes = createCrudRoutes({

+ 1 - 1
src/server/api/wechat-coupons/index.ts

@@ -1,6 +1,6 @@
 import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
 import { WechatCoupon } from '@/server/modules/wechat-pay/wechat-coupon.entity';
-import { WechatCouponSchema, CreateWechatCouponDto, UpdateWechatCouponDto } from '@/server/modules/wechat-pay/wechat-coupon.entity';
+import { WechatCouponSchema, CreateWechatCouponDto, UpdateWechatCouponDto } from '@/server/modules/wechat-pay/wechat-coupon.schema';
 import { authMiddleware } from '@/server/middleware/auth.middleware';
 
 const wechatCouponRoutes = createCrudRoutes({

+ 1 - 1
src/server/api/wechat-pay-config/index.ts

@@ -1,6 +1,6 @@
 import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
 import { WechatPayConfig } from '@/server/modules/wechat-pay/wechat-pay-config.entity';
-import { WechatPayConfigSchema, CreateWechatPayConfigDto, UpdateWechatPayConfigDto } from '@/server/modules/wechat-pay/wechat-pay-config.entity';
+import { WechatPayConfigSchema, CreateWechatPayConfigDto, UpdateWechatPayConfigDto } from '@/server/modules/wechat-pay/wechat-pay-config.schema';
 import { authMiddleware } from '@/server/middleware/auth.middleware';
 
 const wechatPayConfigRoutes = createCrudRoutes({

+ 1 - 1
src/server/api/wechat-pay/actions/query-stocks.ts

@@ -87,7 +87,7 @@ const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
     }, 200);
   } catch (error) {
     const { code = 500, message = '查询批次列表失败' } = error as Error & { code?: number };
-    return c.json({ code, message }, code);
+    return c.json({ code, message }, 500);
   }
 });
 

+ 0 - 50
src/server/modules/wechat-pay/wechat-coupon-stock.entity.ts

@@ -1,5 +1,4 @@
 import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
-import { z } from '@hono/zod-openapi';
 import { WechatPayConfig } from './wechat-pay-config.entity';
 
 @Entity('wechat_coupon_stocks')
@@ -66,52 +65,3 @@ export class WechatCouponStock {
   updatedAt!: Date;
 }
 
-// Zod Schema定义
-export const WechatCouponStockSchema = z.object({
-  id: z.number().int().positive().openapi({ description: '批次ID' }),
-  stockId: z.string().max(32).openapi({ description: '微信支付批次号', example: '1234567890' }),
-  stockName: z.string().max(64).openapi({ description: '批次名称', example: '春节代金券' }),
-  stockCreatorMchid: z.string().max(32).openapi({ description: '创建批次的商户号', example: '1234567890' }),
-  couponType: z.string().max(20).openapi({ description: '代金券类型', example: 'NORMAL' }),
-  couponUseRule: z.any().openapi({ description: '代金券使用规则' }),
-  stockSendRule: z.any().openapi({ description: '批次发放规则' }),
-  couponAmount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
-  couponQuantity: z.number().int().positive().openapi({ description: '代金券数量', example: 1000 }),
-  availableQuantity: z.number().int().min(0).openapi({ description: '可用数量', example: 1000 }),
-  distributedQuantity: z.number().int().min(0).default(0).openapi({ description: '已发放数量', example: 0 }),
-  status: z.string().max(20).default('CREATED').openapi({ description: '批次状态', example: 'CREATED' }),
-  startTime: z.date().openapi({ description: '开始时间', example: '2024-01-01T00:00:00Z' }),
-  endTime: z.date().openapi({ description: '结束时间', example: '2024-12-31T23:59:59Z' }),
-  configId: z.number().int().positive().openapi({ description: '微信支付配置ID', example: 1 }),
-  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
-  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
-  createdAt: z.date().openapi({ description: '创建时间', example: '2024-01-01T00:00:00Z' }),
-  updatedAt: z.date().openapi({ description: '更新时间', example: '2024-01-01T00:00:00Z' })
-});
-
-export const CreateWechatCouponStockDto = z.object({
-  stockName: z.string().max(64).openapi({ description: '批次名称', example: '春节代金券' }),
-  stockCreatorMchid: z.string().max(32).openapi({ description: '创建批次的商户号', example: '1234567890' }),
-  couponType: z.string().max(20).openapi({ description: '代金券类型', example: 'NORMAL' }),
-  couponUseRule: z.any().openapi({ description: '代金券使用规则' }),
-  stockSendRule: z.any().openapi({ description: '批次发放规则' }),
-  couponAmount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
-  couponQuantity: z.number().int().positive().openapi({ description: '代金券数量', example: 1000 }),
-  startTime: z.coerce.date().openapi({ description: '开始时间', example: '2024-01-01T00:00:00Z' }),
-  endTime: z.coerce.date().openapi({ description: '结束时间', example: '2024-12-31T23:59:59Z' }),
-  configId: z.number().int().positive().openapi({ description: '微信支付配置ID', example: 1 })
-});
-
-export const UpdateWechatCouponStockDto = z.object({
-  stockName: z.string().max(64).optional().openapi({ description: '批次名称', example: '春节代金券' }),
-  couponUseRule: z.any().optional().openapi({ description: '代金券使用规则' }),
-  stockSendRule: z.any().optional().openapi({ description: '批次发放规则' }),
-  couponAmount: z.number().int().positive().optional().openapi({ description: '代金券面额(分)', example: 100 }),
-  couponQuantity: z.number().int().positive().optional().openapi({ description: '代金券数量', example: 1000 }),
-  availableQuantity: z.number().int().min(0).optional().openapi({ description: '可用数量', example: 1000 }),
-  distributedQuantity: z.number().int().min(0).optional().openapi({ description: '已发放数量', example: 0 }),
-  status: z.string().max(20).optional().openapi({ description: '批次状态', example: 'RUNNING' }),
-  startTime: z.coerce.date().optional().openapi({ description: '开始时间', example: '2024-01-01T00:00:00Z' }),
-  endTime: z.coerce.date().optional().openapi({ description: '结束时间', example: '2024-12-31T23:59:59Z' }),
-  configId: z.number().int().positive().optional().openapi({ description: '微信支付配置ID', example: 1 })
-});

+ 50 - 0
src/server/modules/wechat-pay/wechat-coupon-stock.schema.ts

@@ -0,0 +1,50 @@
+import { z } from '@hono/zod-openapi';
+
+export const WechatCouponStockSchema = z.object({
+  id: z.number().int().positive().openapi({ description: '批次ID' }),
+  stockId: z.string().max(32).openapi({ description: '微信支付批次号', example: '1234567890' }),
+  stockName: z.string().max(64).openapi({ description: '批次名称', example: '春节代金券' }),
+  stockCreatorMchid: z.string().max(32).openapi({ description: '创建批次的商户号', example: '1234567890' }),
+  couponType: z.string().max(20).openapi({ description: '代金券类型', example: 'NORMAL' }),
+  couponUseRule: z.any().openapi({ description: '代金券使用规则' }),
+  stockSendRule: z.any().openapi({ description: '批次发放规则' }),
+  couponAmount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
+  couponQuantity: z.number().int().positive().openapi({ description: '代金券数量', example: 1000 }),
+  availableQuantity: z.number().int().min(0).openapi({ description: '可用数量', example: 1000 }),
+  distributedQuantity: z.number().int().min(0).default(0).openapi({ description: '已发放数量', example: 0 }),
+  status: z.string().max(20).default('CREATED').openapi({ description: '批次状态', example: 'CREATED' }),
+  startTime: z.date().openapi({ description: '开始时间', example: '2024-01-01T00:00:00Z' }),
+  endTime: z.date().openapi({ description: '结束时间', example: '2024-12-31T23:59:59Z' }),
+  configId: z.number().int().positive().openapi({ description: '微信支付配置ID', example: 1 }),
+  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
+  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
+  createdAt: z.date().openapi({ description: '创建时间', example: '2024-01-01T00:00:00Z' }),
+  updatedAt: z.date().openapi({ description: '更新时间', example: '2024-01-01T00:00:00Z' })
+});
+
+export const CreateWechatCouponStockDto = z.object({
+  stockName: z.string().max(64).openapi({ description: '批次名称', example: '春节代金券' }),
+  stockCreatorMchid: z.string().max(32).openapi({ description: '创建批次的商户号', example: '1234567890' }),
+  couponType: z.string().max(20).openapi({ description: '代金券类型', example: 'NORMAL' }),
+  couponUseRule: z.any().openapi({ description: '代金券使用规则' }),
+  stockSendRule: z.any().openapi({ description: '批次发放规则' }),
+  couponAmount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
+  couponQuantity: z.number().int().positive().openapi({ description: '代金券数量', example: 1000 }),
+  startTime: z.coerce.date().openapi({ description: '开始时间', example: '2024-01-01T00:00:00Z' }),
+  endTime: z.coerce.date().openapi({ description: '结束时间', example: '2024-12-31T23:59:59Z' }),
+  configId: z.number().int().positive().openapi({ description: '微信支付配置ID', example: 1 })
+});
+
+export const UpdateWechatCouponStockDto = z.object({
+  stockName: z.string().max(64).optional().openapi({ description: '批次名称', example: '春节代金券' }),
+  couponUseRule: z.any().optional().openapi({ description: '代金券使用规则' }),
+  stockSendRule: z.any().optional().openapi({ description: '批次发放规则' }),
+  couponAmount: z.number().int().positive().optional().openapi({ description: '代金券面额(分)', example: 100 }),
+  couponQuantity: z.number().int().positive().optional().openapi({ description: '代金券数量', example: 1000 }),
+  availableQuantity: z.number().int().min(0).optional().openapi({ description: '可用数量', example: 1000 }),
+  distributedQuantity: z.number().int().min(0).optional().openapi({ description: '已发放数量', example: 0 }),
+  status: z.string().max(20).optional().openapi({ description: '批次状态', example: 'RUNNING' }),
+  startTime: z.coerce.date().optional().openapi({ description: '开始时间', example: '2024-01-01T00:00:00Z' }),
+  endTime: z.coerce.date().optional().openapi({ description: '结束时间', example: '2024-12-31T23:59:59Z' }),
+  configId: z.number().int().positive().optional().openapi({ description: '微信支付配置ID', example: 1 })
+});

+ 0 - 39
src/server/modules/wechat-pay/wechat-coupon.entity.ts

@@ -1,5 +1,4 @@
 import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
-import { z } from '@hono/zod-openapi';
 import { WechatCouponStock } from './wechat-coupon-stock.entity';
 
 @Entity('wechat_coupons')
@@ -57,41 +56,3 @@ export class WechatCoupon {
   updatedAt!: Date;
 }
 
-// Zod Schema定义
-export const WechatCouponSchema = z.object({
-  id: z.number().int().positive().openapi({ description: '代金券ID' }),
-  couponId: z.string().max(32).openapi({ description: '微信支付代金券ID', example: '1234567890' }),
-  stockId: z.string().max(32).openapi({ description: '批次号', example: '1234567890' }),
-  openid: z.string().max(64).openapi({ description: '用户openid', example: 'oP-y45xbf7hrhC6yeabpjXzIhUWg' }),
-  outRequestNo: z.string().max(64).openapi({ description: '商户请求单号', example: 'ORDER123456789' }),
-  couponStatus: z.string().max(20).default('SENDED').openapi({ description: '代金券状态', example: 'SENDED' }),
-  amount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
-  availableStartTime: z.date().openapi({ description: '可用开始时间', example: '2024-01-01T00:00:00Z' }),
-  availableEndTime: z.date().openapi({ description: '可用结束时间', example: '2024-12-31T23:59:59Z' }),
-  usedTime: z.date().nullable().openapi({ description: '使用时间', example: null }),
-  transactionId: z.string().max(64).nullable().openapi({ description: '微信支付订单号', example: null }),
-  stockIdRef: z.number().int().positive().openapi({ description: '批次ID', example: 1 }),
-  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
-  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
-  createdAt: z.date().openapi({ description: '创建时间', example: '2024-01-01T00:00:00Z' }),
-  updatedAt: z.date().openapi({ description: '更新时间', example: '2024-01-01T00:00:00Z' })
-});
-
-export const CreateWechatCouponDto = z.object({
-  couponId: z.string().max(32).openapi({ description: '微信支付代金券ID', example: '1234567890' }),
-  stockId: z.string().max(32).openapi({ description: '批次号', example: '1234567890' }),
-  openid: z.string().max(64).openapi({ description: '用户openid', example: 'oP-y45xbf7hrhC6yeabpjXzIhUWg' }),
-  outRequestNo: z.string().max(64).openapi({ description: '商户请求单号', example: 'ORDER123456789' }),
-  couponStatus: z.string().max(20).default('SENDED').openapi({ description: '代金券状态', example: 'SENDED' }),
-  amount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
-  availableStartTime: z.coerce.date().openapi({ description: '可用开始时间', example: '2024-01-01T00:00:00Z' }),
-  availableEndTime: z.coerce.date().openapi({ description: '可用结束时间', example: '2024-12-31T23:59:59Z' }),
-  stockIdRef: z.number().int().positive().openapi({ description: '批次ID', example: 1 })
-});
-
-export const UpdateWechatCouponDto = z.object({
-  couponStatus: z.string().max(20).optional().openapi({ description: '代金券状态', example: 'USED' }),
-  usedTime: z.coerce.date().optional().openapi({ description: '使用时间', example: '2024-01-01T12:00:00Z' }),
-  transactionId: z.string().max(64).optional().openapi({ description: '微信支付订单号', example: '4200000123456789' }),
-  stockIdRef: z.number().int().positive().optional().openapi({ description: '批次ID', example: 1 })
-});

+ 39 - 0
src/server/modules/wechat-pay/wechat-coupon.schema.ts

@@ -0,0 +1,39 @@
+import { z } from '@hono/zod-openapi';
+
+export const WechatCouponSchema = z.object({
+  id: z.number().int().positive().openapi({ description: '代金券ID' }),
+  couponId: z.string().max(32).openapi({ description: '微信支付代金券ID', example: '1234567890' }),
+  stockId: z.string().max(32).openapi({ description: '批次号', example: '1234567890' }),
+  openid: z.string().max(64).openapi({ description: '用户openid', example: 'oP-y45xbf7hrhC6yeabpjXzIhUWg' }),
+  outRequestNo: z.string().max(64).openapi({ description: '商户请求单号', example: 'ORDER123456789' }),
+  couponStatus: z.string().max(20).default('SENDED').openapi({ description: '代金券状态', example: 'SENDED' }),
+  amount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
+  availableStartTime: z.date().openapi({ description: '可用开始时间', example: '2024-01-01T00:00:00Z' }),
+  availableEndTime: z.date().openapi({ description: '可用结束时间', example: '2024-12-31T23:59:59Z' }),
+  usedTime: z.date().nullable().openapi({ description: '使用时间', example: null }),
+  transactionId: z.string().max(64).nullable().openapi({ description: '微信支付订单号', example: null }),
+  stockIdRef: z.number().int().positive().openapi({ description: '批次ID', example: 1 }),
+  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
+  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
+  createdAt: z.date().openapi({ description: '创建时间', example: '2024-01-01T00:00:00Z' }),
+  updatedAt: z.date().openapi({ description: '更新时间', example: '2024-01-01T00:00:00Z' })
+});
+
+export const CreateWechatCouponDto = z.object({
+  couponId: z.string().max(32).openapi({ description: '微信支付代金券ID', example: '1234567890' }),
+  stockId: z.string().max(32).openapi({ description: '批次号', example: '1234567890' }),
+  openid: z.string().max(64).openapi({ description: '用户openid', example: 'oP-y45xbf7hrhC6yeabpjXzIhUWg' }),
+  outRequestNo: z.string().max(64).openapi({ description: '商户请求单号', example: 'ORDER123456789' }),
+  couponStatus: z.string().max(20).default('SENDED').openapi({ description: '代金券状态', example: 'SENDED' }),
+  amount: z.number().int().positive().openapi({ description: '代金券面额(分)', example: 100 }),
+  availableStartTime: z.coerce.date().openapi({ description: '可用开始时间', example: '2024-01-01T00:00:00Z' }),
+  availableEndTime: z.coerce.date().openapi({ description: '可用结束时间', example: '2024-12-31T23:59:59Z' }),
+  stockIdRef: z.number().int().positive().openapi({ description: '批次ID', example: 1 })
+});
+
+export const UpdateWechatCouponDto = z.object({
+  couponStatus: z.string().max(20).optional().openapi({ description: '代金券状态', example: 'USED' }),
+  usedTime: z.coerce.date().optional().openapi({ description: '使用时间', example: '2024-01-01T12:00:00Z' }),
+  transactionId: z.string().max(64).optional().openapi({ description: '微信支付订单号', example: '4200000123456789' }),
+  stockIdRef: z.number().int().positive().optional().openapi({ description: '批次ID', example: 1 })
+});

+ 0 - 33
src/server/modules/wechat-pay/wechat-pay-config.entity.ts

@@ -1,5 +1,4 @@
 import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
-import { z } from '@hono/zod-openapi';
 
 @Entity('wechat_pay_config')
 export class WechatPayConfig {
@@ -37,35 +36,3 @@ export class WechatPayConfig {
   updatedAt!: Date;
 }
 
-// Zod Schema定义
-export const WechatPayConfigSchema = z.object({
-  id: z.number().int().positive().openapi({ description: '配置ID' }),
-  merchantId: z.string().max(32).openapi({ description: '商户号', example: '1234567890' }),
-  appId: z.string().max(32).openapi({ description: '应用ID', example: 'wx1234567890abcdef' }),
-  privateKey: z.string().openapi({ description: '商户私钥', example: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...' }),
-  certificateSerialNo: z.string().max(40).openapi({ description: '证书序列号', example: '1234567890ABCDEF1234567890ABCDEF12345678' }),
-  apiV3Key: z.string().max(32).openapi({ description: 'APIv3密钥', example: 'abcdefghijklmnopqrstuvwxyz012345' }),
-  isActive: z.number().int().min(0).max(1).openapi({ description: '是否启用:0-禁用,1-启用', example: 1 }),
-  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
-  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
-  createdAt: z.date().openapi({ description: '创建时间', example: '2024-01-01T00:00:00Z' }),
-  updatedAt: z.date().openapi({ description: '更新时间', example: '2024-01-01T00:00:00Z' })
-});
-
-export const CreateWechatPayConfigDto = z.object({
-  merchantId: z.string().max(32).openapi({ description: '商户号', example: '1234567890' }),
-  appId: z.string().max(32).openapi({ description: '应用ID', example: 'wx1234567890abcdef' }),
-  privateKey: z.string().openapi({ description: '商户私钥', example: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...' }),
-  certificateSerialNo: z.string().max(40).openapi({ description: '证书序列号', example: '1234567890ABCDEF1234567890ABCDEF12345678' }),
-  apiV3Key: z.string().max(32).openapi({ description: 'APIv3密钥', example: 'abcdefghijklmnopqrstuvwxyz012345' }),
-  isActive: z.number().int().min(0).max(1).default(1).openapi({ description: '是否启用:0-禁用,1-启用', example: 1 })
-});
-
-export const UpdateWechatPayConfigDto = z.object({
-  merchantId: z.string().max(32).optional().openapi({ description: '商户号', example: '1234567890' }),
-  appId: z.string().max(32).optional().openapi({ description: '应用ID', example: 'wx1234567890abcdef' }),
-  privateKey: z.string().optional().openapi({ description: '商户私钥', example: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...' }),
-  certificateSerialNo: z.string().max(40).optional().openapi({ description: '证书序列号', example: '1234567890ABCDEF1234567890ABCDEF12345678' }),
-  apiV3Key: z.string().max(32).optional().openapi({ description: 'APIv3密钥', example: 'abcdefghijklmnopqrstuvwxyz012345' }),
-  isActive: z.number().int().min(0).max(1).optional().openapi({ description: '是否启用:0-禁用,1-启用', example: 1 })
-});

+ 33 - 0
src/server/modules/wechat-pay/wechat-pay-config.schema.ts

@@ -0,0 +1,33 @@
+import { z } from '@hono/zod-openapi';
+
+export const WechatPayConfigSchema = z.object({
+  id: z.number().int().positive().openapi({ description: '配置ID' }),
+  merchantId: z.string().max(32).openapi({ description: '商户号', example: '1234567890' }),
+  appId: z.string().max(32).openapi({ description: '应用ID', example: 'wx1234567890abcdef' }),
+  privateKey: z.string().openapi({ description: '商户私钥', example: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...' }),
+  certificateSerialNo: z.string().max(40).openapi({ description: '证书序列号', example: '1234567890ABCDEF1234567890ABCDEF12345678' }),
+  apiV3Key: z.string().max(32).openapi({ description: 'APIv3密钥', example: 'abcdefghijklmnopqrstuvwxyz012345' }),
+  isActive: z.number().int().min(0).max(1).openapi({ description: '是否启用:0-禁用,1-启用', example: 1 }),
+  createdBy: z.number().int().positive().nullable().openapi({ description: '创建用户ID', example: 1 }),
+  updatedBy: z.number().int().positive().nullable().openapi({ description: '更新用户ID', example: 1 }),
+  createdAt: z.date().openapi({ description: '创建时间', example: '2024-01-01T00:00:00Z' }),
+  updatedAt: z.date().openapi({ description: '更新时间', example: '2024-01-01T00:00:00Z' })
+});
+
+export const CreateWechatPayConfigDto = z.object({
+  merchantId: z.string().max(32).openapi({ description: '商户号', example: '1234567890' }),
+  appId: z.string().max(32).openapi({ description: '应用ID', example: 'wx1234567890abcdef' }),
+  privateKey: z.string().openapi({ description: '商户私钥', example: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...' }),
+  certificateSerialNo: z.string().max(40).openapi({ description: '证书序列号', example: '1234567890ABCDEF1234567890ABCDEF12345678' }),
+  apiV3Key: z.string().max(32).openapi({ description: 'APIv3密钥', example: 'abcdefghijklmnopqrstuvwxyz012345' }),
+  isActive: z.number().int().min(0).max(1).default(1).openapi({ description: '是否启用:0-禁用,1-启用', example: 1 })
+});
+
+export const UpdateWechatPayConfigDto = z.object({
+  merchantId: z.string().max(32).optional().openapi({ description: '商户号', example: '1234567890' }),
+  appId: z.string().max(32).optional().openapi({ description: '应用ID', example: 'wx1234567890abcdef' }),
+  privateKey: z.string().optional().openapi({ description: '商户私钥', example: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...' }),
+  certificateSerialNo: z.string().max(40).optional().openapi({ description: '证书序列号', example: '1234567890ABCDEF1234567890ABCDEF12345678' }),
+  apiV3Key: z.string().max(32).optional().openapi({ description: 'APIv3密钥', example: 'abcdefghijklmnopqrstuvwxyz012345' }),
+  isActive: z.number().int().min(0).max(1).optional().openapi({ description: '是否启用:0-禁用,1-启用', example: 1 })
+});