Răsfoiți Sursa

✨ feat(vod): add VOD service API endpoints

- create new VOD API module with signature generation functionality
- implement VOD signature generation using HMAC-SHA1 algorithm
- add environment variable configuration for VOD credentials
- register VOD routes in API router and export type definitions
- create client-side VOD API service for frontend integration
- add OpenAPI documentation and error handling for VOD endpoints
yourname 6 luni în urmă
părinte
comite
ff3b1b2011
3 a modificat fișierele cu 108 adăugiri și 1 ștergeri
  1. 5 1
      src/client/api.ts
  2. 3 0
      src/server/api.ts
  3. 100 0
      src/server/api/vod/index.ts

+ 5 - 1
src/client/api.ts

@@ -3,7 +3,7 @@ import type {
   AuthRoutes, UserRoutes, RoleRoutes, FileRoutes,
   ClassroomDataRoutes, SubmissionRecordsRoutes,
   StockDataRoutes, StockXunlianCodesRoutes, DateNotesRoutes, AliyunRoutes,
-  WechatAuthRoutes, ChatMessageRoutes
+  WechatAuthRoutes, ChatMessageRoutes, VodRoutes
 } from '@/server/api';
 import { axiosFetch } from './utils/axios-fetch';
 
@@ -54,3 +54,7 @@ export const wechatAuthClient = hc<WechatAuthRoutes>('/', {
 export const chatMessageClient = hc<ChatMessageRoutes>('/', {
   fetch: axiosFetch,
 }).api.v1['chat-messages'];
+
+export const vodClient = hc<VodRoutes>('/', {
+  fetch: axiosFetch,
+}).api.v1.vod;

+ 3 - 0
src/server/api.ts

@@ -13,6 +13,7 @@ import dateNotesRoutes from './api/date-notes/index'
 import aliyunRoute from './api/aliyun/index'
 import wechatRoutes from './api/auth/wechat/index'
 import chatMessageRoutes from './api/chat-messages/index'
+import vodRoutes from './api/vod/index'
 import { AuthContext } from './types/context'
 import { AppDataSource } from './data-source'
 import { Hono } from 'hono'
@@ -95,6 +96,7 @@ const dateNotesApi = api.route('/api/v1/date-notes', dateNotesRoutes)
 const aliyunApi = api.route('/api/v1/aliyun', aliyunRoute)
 const wechatAuthApi = api.route('/api/v1/auth/wechat', wechatRoutes)
 const chatMessageApi = api.route('/api/v1/chat-messages', chatMessageRoutes)
+const vodApi = api.route('/api/v1/vod', vodRoutes)
 
 export type AuthRoutes = typeof authRoutes
 export type UserRoutes = typeof userRoutes
@@ -108,6 +110,7 @@ export type DateNotesRoutes = typeof dateNotesApi
 export type AliyunRoutes = typeof aliyunApi
 export type WechatAuthRoutes = typeof wechatAuthApi
 export type ChatMessageRoutes = typeof chatMessageApi
+export type VodRoutes = typeof vodApi
 
 app.route('/', api)
 export default app

+ 100 - 0
src/server/api/vod/index.ts

@@ -0,0 +1,100 @@
+import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi';
+import { ErrorSchema } from '@/server/utils/errorHandler';
+import { AuthContext } from '@/server/types/context';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+import * as process from 'node:process';
+import * as crypto from 'node:crypto';
+import * as querystring from 'node:querystring';
+
+// 环境变量配置
+const VOD_SECRET_ID = process.env.VOD_SECRET_ID || '';
+const VOD_SECRET_KEY = process.env.VOD_SECRET_KEY || '';
+
+// 响应Schema定义
+const VodSignatureResponse = z.object({
+  signature: z.string().openapi({
+    description: 'VOD签名',
+    example: 'eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=='
+  })
+});
+
+/**
+ * 生成VOD签名
+ * @param secretId VOD密钥ID
+ * @param secretKey VOD密钥
+ * @returns VOD签名字符串
+ */
+function generateVodSignature(secretId: string, secretKey: string): string {
+  // 确定签名的当前时间和失效时间
+  const current = Math.floor(Date.now() / 1000);
+  const expired = current + 86400; // 签名有效期:1天
+
+  // 向参数列表填入参数
+  const arg_list = {
+    secretId,
+    currentTimeStamp: current,
+    expireTime: expired,
+    random: Math.round(Math.random() * Math.pow(2, 32)),
+  };
+
+  // 计算签名
+  const orignal = querystring.stringify(arg_list);
+  const orignal_buffer = Buffer.from(orignal, 'utf8');
+
+  const hmac = crypto.createHmac('sha1', secretKey);
+  const hmac_buffer = hmac.update(orignal_buffer).digest();
+
+  const signature = Buffer.concat([hmac_buffer, orignal_buffer]).toString('base64');
+
+  return signature;
+}
+
+// VOD签名生成路由定义
+const vodSignatureRoute = createRoute({
+  method: 'get',
+  path: '/signature',
+  middleware: [authMiddleware],
+  responses: {
+    200: {
+      description: '成功生成VOD签名',
+      content: { 'application/json': { schema: VodSignatureResponse } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: ErrorSchema } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: ErrorSchema } }
+    }
+  }
+});
+
+// 创建API应用实例
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(vodSignatureRoute, async (c) => {
+    try {
+      // 检查环境变量配置
+      if (!VOD_SECRET_ID || !VOD_SECRET_KEY) {
+        return c.json({
+          code: 500,
+          message: 'VOD服务配置不完整,请检查VOD_SECRET_ID和VOD_SECRET_KEY环境变量'
+        }, 500);
+      }
+
+      // 生成VOD签名
+      const signature = generateVodSignature(VOD_SECRET_ID, VOD_SECRET_KEY);
+
+      return c.json({
+        signature
+      }, 200);
+    } catch (error) {
+      console.error('VOD签名生成错误:', error);
+      return c.json({
+        code: 500,
+        message: error instanceof Error ? error.message : 'VOD签名生成失败'
+      }, 500);
+    }
+  });
+
+export default app;