From 6c4247c8ea8706faefda20ae5867b52cc971f34f Mon Sep 17 00:00:00 2001 From: imeepos Date: Fri, 26 Sep 2025 22:46:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(sdk):=20=E6=A0=B9=E6=8D=AEAPI=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=85=A8=E9=9D=A2=E5=8D=87=E7=BA=A7sdk-server.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 完整实现Mixvideo Workflow API的所有接口 - 新增模板管理:创建、更新、删除、激活、禁用、同步Stripe等17个接口 - 新增支付处理:Stripe结账、成功/取消回调、退款、支付历史等8个接口 - 新增任务管理:创建任务、获取状态、进度追踪等3个接口 - 新增Google OAuth:登录、令牌刷新、用户信息、撤销等5个接口 - 完善TypeScript类型定义,新增15+个接口类型 - 优化中文注释和文档,添加emoji增强可读性 - 更新默认API基础URL为生产环境 - 改进错误处理和日志输出 - 保持向后兼容性 API支持: - 模板管理 (Template Controller) - 支付处理 (Payment Controller) - 任务管理 (Task Controller) - OAuth认证 (Auth Controller) --- API.md | 956 ++++++++++++++++++++++++++++++++++++++++++ src/sdk/sdk-server.ts | 727 ++++++++++++++++++++++++++++---- 2 files changed, 1606 insertions(+), 77 deletions(-) create mode 100644 API.md diff --git a/API.md b/API.md new file mode 100644 index 0000000..dd4c0fd --- /dev/null +++ b/API.md @@ -0,0 +1,956 @@ +# Mixvideo Workflow API Documentation + +## Overview +This document describes the REST API endpoints for the Mixvideo Workflow service, which provides video generation capabilities with Google OAuth integration, payment processing, and template management. + +## Base URL +``` +https://mixvideo-workflow.bowong.cc/ +``` + +## Authentication +Most endpoints require authentication via OAuth tokens or API keys. Include tokens in the Authorization header: +``` +Authorization: Bearer +``` + +--- + +## Auth Controller (`/auth/google`) + +### Google OAuth Authentication + +#### `GET /auth/google/authorize` +Initiates Google OAuth authorization flow. + +**Query Parameters:** +- `redirect_url` (optional): URL to redirect after authorization +- `scopes` (optional): Comma-separated OAuth scopes (default: openid,email,profile) + +**Response:** +- Redirects to Google OAuth consent screen + +--- + +#### `GET /auth/google/callback` +Handles OAuth callback from Google. + +**Query Parameters:** +- `code`: Authorization code from Google +- `state`: State parameter for CSRF protection +- `error` (optional): Error code if authorization failed + +**Success Response (200):** +```json +{ + "success": true, + "code": 200, + "message": "OAuth authorization successful", + "data": { + "user": { + "id": "user_id", + "email": "user@example.com", + "name": "User Name" + }, + "access_token": "ya29.xxx", + "expires_in": 3600 + } +} +``` + +--- + +#### `POST /auth/google/refresh` +Refreshes OAuth access token. + +**Request Body:** +```json +{ + "refresh_token": "refresh_token_here", + "user_id": "optional_user_id" +} +``` + +**Response (200):** +```json +{ + "success": true, + "code": 200, + "message": "Token refreshed successfully", + "data": { + "access_token": "new_access_token", + "expires_in": 3600, + "scope": "openid email profile" + } +} +``` + +--- + +#### `GET /auth/google/userinfo` +Retrieves user information from Google. + +**Headers:** +- `Authorization: Bearer ` OR +- Query parameter: `access_token=` + +**Response (200):** +```json +{ + "success": true, + "code": 200, + "message": "User info retrieved successfully", + "data": { + "id": "user_id", + "email": "user@example.com", + "name": "User Name", + "picture": "https://..." + } +} +``` + +--- + +#### `POST /auth/google/revoke` +Revokes OAuth token. + +**Request Body:** +```json +{ + "token": "token_to_revoke", + "user_id": "optional_user_id" +} +``` + +**Response (200):** +```json +{ + "success": true, + "code": 200, + "message": "Token revoked successfully" +} +``` + +--- + +## Payment Controller (`/payment`) + +### Stripe Payment Integration + +#### `POST /payment/checkout/:templateCode` +Creates Stripe checkout session for a template. + +**Path Parameters:** +- `templateCode`: Template identifier + +**Request Body:** +```json +{ + "userId": "user_123", + "metadata": { + "imageUrl": "https://example.com/image.jpg" + } +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Checkout session created successfully", + "data": { + "sessionId": "cs_xxx", + "url": "https://checkout.stripe.com/pay/cs_xxx", + "paymentId": "payment_123" + }, + "timestamp": "2024-01-01T00:00:00Z", + "traceId": "trace_123" +} +``` + +--- + +#### `POST /payment/webhook` +Handles Stripe webhook events. + +**Headers:** +- `stripe-signature`: Stripe webhook signature + +**Request Body:** Raw webhook payload from Stripe + +**Response (200):** +```json +{ + "code": 200, + "message": "Webhook processed successfully" +} +``` + +--- + +#### `GET /payment/success` +Handles successful payment callback. + +**Query Parameters:** +- `session_id`: Stripe session ID +- `payment_id`: Internal payment ID + +**Response (200):** +```json +{ + "code": 200, + "message": "Payment successful, template execution started", + "data": { + "payment": { + "id": "payment_123", + "status": "completed", + "templateCode": "template_001" + }, + "execution": { + "executionId": "exec_123", + "taskId": "task_123" + } + } +} +``` + +--- + +#### `GET /payment/cancel` +Handles payment cancellation. + +**Query Parameters:** +- `session_id`: Stripe session ID +- `payment_id`: Internal payment ID + +**Response (200):** +```json +{ + "code": 200, + "message": "Payment cancelled", + "data": { + "payment": { + "id": "payment_123", + "status": "cancelled" + } + } +} +``` + +--- + +#### `GET /payment/history` +Retrieves user payment history. + +**Query Parameters:** +- `userId`: User identifier + +**Response (200):** +```json +{ + "code": 200, + "message": "Payment history retrieved successfully", + "data": { + "payments": [ + { + "id": "payment_123", + "templateCode": "template_001", + "status": "completed", + "amount": 1000, + "currency": "usd", + "createdAt": "2024-01-01T00:00:00Z" + } + ], + "total": 1 + } +} +``` + +--- + +#### `POST /payment/refund/:paymentId` +Processes refund for a payment. + +**Path Parameters:** +- `paymentId`: Payment identifier + +**Request Body:** +```json +{ + "reason": "user_request", + "amount": 1000, + "metadata": { + "note": "Customer requested refund" + } +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Refund processed successfully", + "data": { + "refundId": "re_xxx", + "amount": 1000, + "status": "succeeded" + } +} +``` + +--- + +#### `GET /payment/:paymentId` +Retrieves payment details. + +**Path Parameters:** +- `paymentId`: Payment identifier + +**Response (200):** +```json +{ + "code": 200, + "message": "Payment details retrieved successfully", + "data": { + "id": "payment_123", + "templateCode": "template_001", + "userId": "user_123", + "status": "completed", + "amount": 1000, + "currency": "usd", + "stripeSessionId": "cs_xxx", + "executionId": "exec_123", + "createdAt": "2024-01-01T00:00:00Z" + } +} +``` + +--- + +#### `GET /payment/health` +Payment service health check. + +**Response (200):** +```json +{ + "code": 200, + "message": "Payment service is healthy", + "data": { + "timestamp": "2024-01-01T00:00:00Z", + "service": "PaymentController" + } +} +``` + +--- + +## Task Controller (`/task`) + +### Task Management + +#### `GET /task/:taskId` +Retrieves task status and details. + +**Path Parameters:** +- `taskId`: Task identifier + +**Response (200):** +```json +{ + "code": 200, + "message": "Task status retrieved", + "data": { + "id": "task_123", + "status": "completed", + "progress": 100, + "result": { + "videoUrl": "https://example.com/output.mp4" + }, + "createdAt": "2024-01-01T00:00:00Z", + "completedAt": "2024-01-01T00:05:00Z" + } +} +``` + +--- + +#### `POST /task` +Creates a new task. + +**Request Body:** +```json +{ + "type": "video_generation", + "templateCode": "template_001", + "userId": "user_123", + "parameters": { + "imageUrl": "https://example.com/input.jpg" + } +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Sent message to the queue", + "data": "task_123" +} +``` + +--- + +#### `POST /task/:taskId` +Creates task with specific ID. + +**Path Parameters:** +- `taskId`: Desired task identifier + +**Request Body:** +```json +{ + "type": "video_generation", + "templateCode": "template_001", + "parameters": { + "imageUrl": "https://example.com/input.jpg" + } +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Sent message to the queue", + "data": "task_123" +} +``` + +--- + +## Template Controller (`/templates`) + +### Template Management + +#### `GET /templates` +Retrieves all active templates. + +**Response (200):** +```json +{ + "code": 200, + "message": "Templates retrieved successfully", + "data": { + "templates": [ + { + "code": "template_001", + "name": "AI Video Generator", + "description": "Generate videos from images using AI", + "creditCost": 10, + "templateType": "VIDEO", + "isActive": true, + "tags": ["ai", "video", "generation"] + } + ], + "total": 1 + } +} +``` + +--- + +#### `GET /templates/get/:code` +Retrieves specific template by code. + +**Path Parameters:** +- `code`: Template code + +**Response (200):** +```json +{ + "code": 200, + "message": "Template retrieved successfully", + "data": { + "code": "template_001", + "name": "AI Video Generator", + "description": "Generate videos from images using AI", + "creditCost": 10, + "templateType": "VIDEO", + "workflow": "video-generation-workflow", + "isActive": true, + "stripeProductId": "prod_xxx", + "createdAt": "2024-01-01T00:00:00Z" + } +} +``` + +--- + +#### `POST /templates` +Creates a new template. + +**Request Body:** +```json +{ + "code": "template_002", + "name": "New Template", + "description": "Template description", + "workflow": "workflow-name", + "creditCost": 15, + "version": "1.0.0", + "templateType": "IMAGE", + "tags": ["new", "template"], + "imageModel": "dall-e-3", + "imagePrompt": "Generate image based on: {prompt}" +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Template created successfully", + "data": { + "code": "template_002", + "stripeProductId": "prod_yyy", + "stripePriceId": "price_yyy" + } +} +``` + +--- + +#### `PUT /templates/update/:code` +Updates existing template. + +**Path Parameters:** +- `code`: Template code + +**Request Body:** +```json +{ + "name": "Updated Template Name", + "description": "Updated description", + "creditCost": 20, + "isActive": true +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Template updated successfully", + "data": { + "updated": true, + "stripeSynced": true + } +} +``` + +--- + +#### `DELETE /templates/delete/:code` +Deletes template. + +**Path Parameters:** +- `code`: Template code + +**Response (200):** +```json +{ + "code": 200, + "message": "Template deleted successfully", + "data": { + "deleted": true + } +} +``` + +--- + +#### `POST /templates/execute/:code` +Executes template workflow. + +**Path Parameters:** +- `code`: Template code + +**Request Body:** +```json +{ + "userId": "user_123", + "imageUrl": "https://example.com/input.jpg" +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Template execution started", + "data": { + "executionId": "exec_123", + "taskId": "task_123", + "status": "running" + } +} +``` + +--- + +#### `POST /templates/activate/:code` +Activates template and syncs to Stripe. + +**Path Parameters:** +- `code`: Template code + +**Response (200):** +```json +{ + "code": 200, + "message": "Template activated successfully", + "data": { + "isActive": true, + "stripeSynced": true + } +} +``` + +--- + +#### `POST /templates/deactivate/:code` +Deactivates template. + +**Path Parameters:** +- `code`: Template code + +**Response (200):** +```json +{ + "code": 200, + "message": "Template deactivated successfully", + "data": { + "isActive": false, + "stripeSynced": true + } +} +``` + +--- + +#### `POST /templates/sync/:code` +Syncs template to Stripe. + +**Path Parameters:** +- `code`: Template code + +**Request Body (optional):** +```json +{ + "forceUpdate": true +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Template sync completed", + "data": { + "synced": true, + "stripeProductId": "prod_xxx", + "stripePriceId": "price_xxx" + } +} +``` + +--- + +#### `GET /templates/execution/:taskId/progress` +Gets execution progress. + +**Path Parameters:** +- `taskId`: Task identifier + +**Response (200):** +```json +{ + "code": 200, + "message": "Execution progress retrieved", + "data": { + "taskId": "task_123", + "executionId": "exec_123", + "status": "completed", + "progress": 100, + "result": { + "videoUrl": "https://example.com/output.mp4" + } + } +} +``` + +--- + +#### `GET /templates/executions/user/:userId` +Gets user execution history. + +**Path Parameters:** +- `userId`: User identifier + +**Response (200):** +```json +{ + "code": 200, + "message": "User executions retrieved successfully", + "data": { + "executions": [ + { + "executionId": "exec_123", + "templateCode": "template_001", + "status": "completed", + "createdAt": "2024-01-01T00:00:00Z" + } + ], + "total": 1 + } +} +``` + +--- + +#### `POST /templates/bulk` +Performs bulk operations on templates. + +**Request Body:** +```json +{ + "templateCodes": ["template_001", "template_002"], + "operation": "sync_stripe" +} +``` + +**Response (200):** +```json +{ + "code": 200, + "message": "Bulk operation completed", + "data": { + "successful": ["template_001", "template_002"], + "failed": [], + "total": 2 + } +} +``` + +--- + +#### `GET /templates/sync-all-stripe` +Syncs all templates to Stripe. + +**Response (200):** +```json +{ + "code": 200, + "message": "All templates synced to Stripe", + "data": { + "successful": 10, + "failed": 0, + "total": 10 + } +} +``` + +--- + +#### `GET /templates/sync-status` +Checks template-Stripe sync status. + +**Response (200):** +```json +{ + "code": 200, + "message": "Sync status retrieved", + "data": { + "totalTemplates": 10, + "withStripeProduct": 8, + "activeTemplates": 9, + "needsSync": 1, + "templates": [ + { + "code": "template_001", + "name": "Template Name", + "isActive": true, + "hasStripeProduct": true, + "lastStripeSyncAt": "2024-01-01T00:00:00Z" + } + ] + } +} +``` + +--- + +#### `GET /templates/verify-sync/:code` +Verifies template Stripe sync status. + +**Path Parameters:** +- `code`: Template code + +**Response (200):** +```json +{ + "code": 200, + "message": "Template sync verified successfully", + "data": { + "templateCode": "template_001", + "synced": true, + "issues": [], + "stripeProductId": "prod_xxx", + "stripePriceId": "price_xxx", + "recommendations": ["Template is properly synced with Stripe"] + } +} +``` + +--- + +#### `GET /templates/diagnose-stripe` +Diagnoses Stripe environment and configuration. + +**Response (200):** +```json +{ + "code": 200, + "message": "Stripe environment is healthy", + "data": { + "environment": "test", + "apiKeyValid": true, + "issues": [], + "accountInfo": { + "chargesEnabled": true, + "country": "US" + }, + "recommendations": ["Stripe configuration appears healthy"] + } +} +``` + +--- + +#### `GET /templates/health` +Template service health check. + +**Response (200):** +```json +{ + "code": 200, + "message": "Template service is healthy", + "data": { + "totalTemplates": 10, + "timestamp": "2024-01-01T00:00:00Z", + "service": "TemplateService" + } +} +``` + +--- + +#### `GET /templates/init` +Initializes templates from JSON data. + +**Response (200):** +```json +{ + "code": 200, + "message": "Templates initialization completed", + "data": { + "total": 10, + "imported": 9, + "failed": 1, + "details": [ + { + "code": "template_001", + "status": "success" + }, + { + "code": "template_002", + "status": "error", + "error": "Template already exists" + } + ] + } +} +``` + +--- + +#### `POST /templates/test/create` +Creates a test template for development. + +**Response (200):** +```json +{ + "code": 200, + "message": "Test template created successfully", + "data": { + "code": "test-image-generation", + "stripeProductId": "prod_test", + "stripePriceId": "price_test" + } +} +``` + +--- + +## Error Responses + +All endpoints return standardized error responses: + +**Error Response Format:** +```json +{ + "code": 400, + "message": "Error description", + "timestamp": "2024-01-01T00:00:00Z", + "traceId": "trace_123" +} +``` + +**Common HTTP Status Codes:** +- `200` - Success +- `400` - Bad Request (validation errors, missing parameters) +- `401` - Unauthorized (missing or invalid authentication) +- `404` - Not Found (resource not found) +- `500` - Internal Server Error (server-side errors) + +## Rate Limiting + +API endpoints may be subject to rate limiting. Check response headers for rate limit information: +- `X-RateLimit-Limit`: Requests per time window +- `X-RateLimit-Remaining`: Remaining requests in current window +- `X-RateLimit-Reset`: Time when rate limit resets + +## Data Types + +### Template Types +- `IMAGE` - Image generation templates +- `VIDEO` - Video generation templates + +### Payment Status +- `pending` - Payment initiated but not completed +- `completed` - Payment successfully processed +- `failed` - Payment failed +- `cancelled` - Payment cancelled by user +- `refunded` - Payment refunded + +### Task Status +- `pending` - Task queued but not started +- `running` - Task currently executing +- `completed` - Task finished successfully +- `failed` - Task failed with error + +### Refund Reasons +- `user_request` - User requested refund +- `technical_issue` - Technical problem occurred +- `duplicate` - Duplicate payment +- `fraudulent` - Fraudulent transaction \ No newline at end of file diff --git a/src/sdk/sdk-server.ts b/src/sdk/sdk-server.ts index 0ff8aae..baaee02 100644 --- a/src/sdk/sdk-server.ts +++ b/src/sdk/sdk-server.ts @@ -3,67 +3,234 @@ import Taro from "@tarojs/taro" import { IToken, IUser } from "./types"; import { createPlatformFactory } from "../platforms"; -const TOKEN_STORAGE_KEY = 'access_token'; -const TOKEN_UID_KEY = 'user_uid'; +// ==================== 常量定义 ==================== + +const TOKEN_STORAGE_KEY = 'access_token'; // OAuth访问令牌存储键 +const TOKEN_UID_KEY = 'user_uid'; // 用户ID存储键 /** * 模板信息接口 - 匹配后端Template抽象类 */ export interface Template { - code: string; // 模板唯一标识码 - name: string; // 模板名称 - description: string; // 模板详细描述 - creditCost: number; // 积分消耗 - version: string; // 版本号 - inputExampleUrl: string; // 原始图片 - outputExampleUrl: string; // 输出图片 - tags: string[]; // 标签数组 - templateType: string; // 模板类型 + code: string; // 模板唯一标识码 + name: string; // 模板名称 + description: string; // 模板详细描述 + creditCost: number; // 积分消耗 + version?: string; // 版本号 + inputExampleUrl?: string; // 原始图片示例 + outputExampleUrl?: string; // 输出图片示例 + tags: string[]; // 标签数组 + templateType: 'IMAGE' | 'VIDEO'; // 模板类型:图片或视频 + workflow?: string; // 工作流名称 + isActive: boolean; // 是否激活 + stripeProductId?: string; // Stripe产品ID + stripePriceId?: string; // Stripe价格ID + imageModel?: string; // 图片模型(如dall-e-3) + imagePrompt?: string; // 图片生成提示词 + createdAt?: string; // 创建时间 + lastStripeSyncAt?: string; // 最后同步Stripe时间 } /** * API 响应基础接口 - 匹配后端NestJS控制器的响应格式 */ interface ApiResponse { - status: boolean | string; - success: boolean | string; - code: number; - data: T; - msg: string; + success?: boolean; // 请求是否成功 + code: number; // 状态码 + message?: string; // 响应消息 + msg?: string; // 兼容旧版本消息字段 + data: T; // 响应数据 + timestamp?: string; // 时间戳 + traceId?: string; // 链路追踪ID } /** * 模板执行参数 */ export interface ExecuteTemplateParams { - templateCode: string; - imageUrl: string; + templateCode: string; // 模板代码 + userId: string; // 用户ID + imageUrl: string; // 图片URL } /** - * 模板执行结果 - 后端返回字符串结果 + * 模板执行结果 */ export interface ExecuteTemplateResult { - result: string | null; - success: boolean; - message: string; + executionId: string; // 执行ID + taskId: string; // 任务ID + status: 'pending' | 'running' | 'completed' | 'failed'; // 任务状态 } /** - * SDK服务端客户端 - * 用于与后端模板服务进行通信 + * 任务执行进度信息 + */ +export interface TaskProgress { + taskId: string; // 任务ID + executionId: string; // 执行ID + status: 'pending' | 'running' | 'completed' | 'failed'; // 任务状态 + progress: number; // 进度百分比 (0-100) + result?: { + videoUrl?: string; // 生成的视频URL + imageUrl?: string; // 生成的图片URL + }; + createdAt: string; // 创建时间 + completedAt?: string; // 完成时间 +} + +/** + * 支付会话创建参数 + */ +export interface CreateCheckoutParams { + templateCode: string; // 模板代码 + userId: string; // 用户ID + metadata: { + imageUrl: string; // 图片URL + [key: string]: any; // 其他元数据 + }; +} + +/** + * 支付会话结果 + */ +export interface CheckoutSessionResult { + sessionId: string; // Stripe会话ID + url: string; // 支付页面URL + paymentId: string; // 内部支付ID +} + +/** + * 支付历史记录 + */ +export interface PaymentHistory { + id: string; // 支付ID + templateCode: string; // 模板代码 + status: 'pending' | 'completed' | 'failed' | 'cancelled' | 'refunded'; // 支付状态 + amount: number; // 金额(分) + currency: string; // 货币类型 + createdAt: string; // 创建时间 +} + +/** + * 退款参数 + */ +export interface RefundParams { + reason: 'user_request' | 'technical_issue' | 'duplicate' | 'fraudulent'; // 退款原因 + amount?: number; // 退款金额(分),不指定则全额退款 + metadata?: { + note?: string; // 退款说明 + [key: string]: any; // 其他元数据 + }; +} + +/** + * Google OAuth用户信息 + */ +export interface GoogleUserInfo { + id: string; // Google用户ID + email: string; // 邮箱 + name: string; // 姓名 + picture?: string; // 头像URL +} + +/** + * OAuth令牌刷新参数 + */ +export interface RefreshTokenParams { + refresh_token: string; // 刷新令牌 + user_id?: string; // 用户ID(可选) +} + +/** + * OAuth令牌响应 + */ +export interface TokenResponse { + access_token: string; // 访问令牌 + expires_in: number; // 过期时间(秒) + scope?: string; // 权限范围 + refresh_token?: string; // 刷新令牌 +} + +/** + * 创建任务参数 + */ +export interface CreateTaskParams { + type: 'video_generation' | 'image_generation'; // 任务类型 + templateCode: string; // 模板代码 + userId?: string; // 用户ID + parameters: { + imageUrl: string; // 图片URL + [key: string]: any; // 其他参数 + }; +} + +/** + * 用户执行历史 + */ +export interface UserExecution { + executionId: string; // 执行ID + templateCode: string; // 模板代码 + status: 'pending' | 'running' | 'completed' | 'failed'; // 状态 + createdAt: string; // 创建时间 + result?: { + videoUrl?: string; // 生成的视频URL + imageUrl?: string; // 生成的图片URL + }; +} + +/** + * 批量操作参数 + */ +export interface BulkOperationParams { + templateCodes: string[]; // 模板代码数组 + operation: 'sync_stripe' | 'activate' | 'deactivate'; // 操作类型 +} + +/** + * 模板同步状态 + */ +export interface TemplateSyncStatus { + code: string; // 模板代码 + name: string; // 模板名称 + isActive: boolean; // 是否激活 + hasStripeProduct: boolean; // 是否有Stripe产品 + lastStripeSyncAt?: string; // 最后同步时间 +} + +/** + * Mixvideo Workflow SDK客户端 + * 用于与Mixvideo Workflow API进行通信,支持: + * - 模板管理(创建、更新、删除、激活、禁用) + * - 支付处理(Stripe集成、结账、退款) + * - 任务管理(视频生成、进度追踪) + * - Google OAuth认证(登录、令牌刷新、撤销) + * + * @example + * const sdk = new SdkServer('https://mixvideo-workflow.bowong.cc'); + * const templates = await sdk.getAllTemplates(); */ export class SdkServer { - private readonly baseUrl: string; - private readonly timeout: number; + private readonly baseUrl: string; // API基础URL + private readonly timeout: number; // 请求超时时间(毫秒) - constructor(url: string = `http://127.0.0.1:8787`, timeout: number = 5 * 60 * 1000) { + /** + * 初始化SDK客户端 + * @param url API基础URL,默认为Mixvideo Workflow的生产环境 + * @param timeout 请求超时时间(毫秒),默认5分钟 + */ + constructor(url: string = `https://mixvideo-workflow.bowong.cc`, timeout: number = 5 * 60 * 1000) { this.baseUrl = url.endsWith('/') ? url.slice(0, -1) : url; this.timeout = timeout; } /** * 发送HTTP请求的通用方法 + * 支持自动重试、错误处理、认证头部添加 + * @param url 请求路径 + * @param method HTTP方法 + * @param data 请求数据 + * @param retryCount 当前重试次数 + * @returns API响应数据 */ private async request( url: string, @@ -75,7 +242,7 @@ export class SdkServer { const retryDelay = 1000 * (retryCount + 1); // 递增延迟 try { - console.log(`SDK Server request: ${method} ${this.baseUrl}${url}`, { data, retryCount }); + console.log(`🚀 SDK Server request: ${method} ${this.baseUrl}${url}`, { data, retryCount }); const requestConfig: any = { url: `${this.baseUrl}${url}`, @@ -112,7 +279,7 @@ export class SdkServer { mode: `cors` }); - console.log(`SDK Server response:`, { + console.log(`✅ SDK Server response:`, { statusCode: response.statusCode, data: response.data, header: response.header @@ -122,18 +289,15 @@ export class SdkServer { const apiResponse = response.data as ApiResponse; // 检查API响应状态 - if (apiResponse.success) { + if (apiResponse.success || apiResponse.code === 200) { return apiResponse; } - if (apiResponse.code === 200) { - return apiResponse - } - throw new Error(apiResponse.msg || 'API request failed'); + throw new Error(apiResponse.message || apiResponse.msg || 'API request failed'); } else { throw new Error(`HTTP ${response.statusCode}: ${response.data?.msg || 'Request failed'}`); } } catch (error: any) { - console.error('SDK Server request error:', { + console.error('❌ SDK Server request error:', { url: `${this.baseUrl}${url}`, method, data, @@ -148,7 +312,7 @@ export class SdkServer { error.errMsg?.includes('request:fail'); if (isNetworkError && retryCount < maxRetries) { - console.log(`Retrying request in ${retryDelay}ms... (${retryCount + 1}/${maxRetries})`); + console.log(`♾️ Retrying request in ${retryDelay}ms... (${retryCount + 1}/${maxRetries})`); // 等待后重试 await new Promise(resolve => setTimeout(resolve, retryDelay)); @@ -158,26 +322,28 @@ export class SdkServer { // 包装错误信息 const errorMessage = error.message || error.errMsg || 'Unknown network error'; - throw new Error(`网络请求失败: ${errorMessage}`); + throw new Error(`😫 网络请求失败: ${errorMessage}`); } } + // ==================== 模板管理相关接口 ==================== + /** - * 获取所有模板列表 - * GET / + * 获取所有活跃模板列表 + * GET /templates */ async getAllTemplates(): Promise { - const response = await this.request<{ templates: Template[] }>('/templates'); + const response = await this.request<{ templates: Template[]; total: number }>('/templates'); return response.data.templates || []; } /** * 根据模板代码获取单个模板信息 - * GET /:templateCode + * GET /templates/get/:code */ async getTemplate(templateCode: string): Promise