Explorar el Código

添加抖音安全审核

flowerpig hace 5 meses
padre
commit
34084f339e

+ 162 - 30
webServer/src/channels/handlers/MiniappChannelHandler.ts

@@ -36,6 +36,10 @@ export class MiniappChannelHandler implements ChannelHandler {
                     ...baseConfig.paymentConfig,
                     signKey: DOUYIN_MINI_APP_PRIVATE_KEY,
                     gameId: DOUYIN_MINI_APP_GAME_ID,
+                },
+                loginConfig: {
+                    ...baseConfig.loginConfig,
+                    apiKey: DOUYIN_MINI_APP_PRIVATE_KEY, // 抖音使用privateKey作为apiKey
                 }
             };
         } else {
@@ -517,12 +521,12 @@ export class MiniappChannelHandler implements ChannelHandler {
     }
 
     /**
-     * 执行内容安全审核(内部通用方法)
+     * 执行小程序内容安全审核
      * @param params 审核参数
      * @param config 渠道配置
      * @returns 审核结果
      */
-    private async performContentSecurityCheck(params: {
+    private async performMiniappContentSecurityCheck(params: {
         uid: string;
         content: string;
         scene?: string;
@@ -541,8 +545,14 @@ export class MiniappChannelHandler implements ChannelHandler {
             const timestamp = Math.floor(Date.now() / 1000);
             const nonce = Math.floor(Math.random() * 1000000);
 
+            // 使用小程序配置
+            let actualConfig = config;
+            if (config.channelId === 11) {
+                actualConfig = this.getChannel11Config('miniapp');
+            }
+
             // 生成签名
-            const signature = this.generateContentSecuritySignature({ timestamp, nonce }, config);
+            const signature = this.generateContentSecuritySignature({ timestamp, nonce }, actualConfig);
             if (!signature) {
                 return {
                     success: false,
@@ -554,7 +564,7 @@ export class MiniappChannelHandler implements ChannelHandler {
             // 构建请求参数
             const requestData = {
                 uid: params.uid,
-                gameid: config.paymentConfig.gameId,
+                gameid: actualConfig.paymentConfig.gameId,
                 signature: signature,
                 timestamp: timestamp,
                 nonce: nonce,
@@ -565,16 +575,19 @@ export class MiniappChannelHandler implements ChannelHandler {
                 usersign: params.usersign || ''
             };
 
-            // 调用内容安全API
-            const apiUrl = `https://api.${config.paymentConfig.apiUrl}/mpcommon/?cmd=wxaMsgSecCheck`;
-            logger.info("调用内容安全API:", { url: apiUrl, content: params.content.substring(0, 50) + '...' });
+            // 调用小程序内容安全API
+            const apiUrl = `https://api.${actualConfig.paymentConfig.apiUrl}/mpcommon/?cmd=wxaMsgSecCheck`;
+            logger.info("调用小程序内容安全API:", { 
+                url: apiUrl, 
+                content: params.content.substring(0, 50) + '...' 
+            });
 
             const response = await axios.post(apiUrl, requestData, {
                 httpsAgent: this.getHttpsAgent(),
                 headers: this.getCommonHeaders()
             });
 
-            logger.info("内容安全API响应:", response.data);
+            logger.info("小程序内容安全API响应:", response.data);
 
             // 处理响应结果
             if (response.data && response.data.error === 0) {
@@ -593,7 +606,102 @@ export class MiniappChannelHandler implements ChannelHandler {
                 };
             }
         } catch (error) {
-            logger.error("内容安全审核出错:", error);
+            logger.error("小程序内容安全审核出错:", error);
+            return {
+                success: false,
+                error: -1,
+                errmsg: "内容安全审核失败"
+            };
+        }
+    }
+
+    /**
+     * 执行抖音内容安全审核
+     * @param params 审核参数
+     * @param config 渠道配置
+     * @returns 审核结果
+     */
+    private async performByteDanceContentSecurityCheck(params: {
+        uid: string;
+        content: string;
+        scene?: string;
+        nickname?: string;
+        title?: string;
+        usersign?: string;
+    }, config: ChannelConfig): Promise<{
+        success: boolean;
+        error?: number;
+        errmsg?: string;
+        result?: any;
+        trace_id?: string;
+        detail?: any;
+    }> {
+        try {
+            const timestamp = Math.floor(Date.now() / 1000);
+            const nonce = Math.floor(Math.random() * 1000000);
+
+            // 使用抖音小程序配置
+            let actualConfig = config;
+            if (config.channelId === 11) {
+                actualConfig = this.getChannel11Config('ttminiapp');
+            }
+
+            // 生成签名
+            const signature = this.generateContentSecuritySignature({ timestamp, nonce }, actualConfig);
+            if (!signature) {
+                return {
+                    success: false,
+                    error: -1,
+                    errmsg: "签名生成失败"
+                };
+            }
+
+            // 构建请求参数
+            const requestData = {
+                uid: params.uid,
+                gameid: actualConfig.paymentConfig.gameId,
+                signature: signature,
+                timestamp: timestamp,
+                nonce: nonce,
+                scene: params.scene || '1',
+                content: params.content,
+                nickname: params.nickname || '',
+                title: params.title || '',
+                usersign: params.usersign || ''
+            };
+
+            // 调用抖音内容安全API
+            const apiUrl = `https://api.${actualConfig.paymentConfig.apiUrl}/mpcommon/?cmd=byteDanceMsgSecCheck`;
+            logger.info("调用抖音内容安全API:", { 
+                url: apiUrl, 
+                content: params.content.substring(0, 50) + '...' 
+            });
+
+            const response = await axios.post(apiUrl, requestData, {
+                httpsAgent: this.getHttpsAgent(),
+                headers: this.getCommonHeaders()
+            });
+
+            logger.info("抖音内容安全API响应:", response.data);
+
+            // 处理响应结果
+            if (response.data && response.data.error === 0) {
+                return {
+                    success: true,
+                    error: 0,
+                    result: response.data.result,
+                    trace_id: response.data.trace_id,
+                    detail: response.data.detail
+                };
+            } else {
+                return {
+                    success: false,
+                    error: response.data?.error || -1,
+                    errmsg: response.data?.errmsg || "内容安全检测失败"
+                };
+            }
+        } catch (error) {
+            logger.error("抖音内容安全审核出错:", error);
             return {
                 success: false,
                 error: -1,
@@ -610,7 +718,9 @@ export class MiniappChannelHandler implements ChannelHandler {
     async contentSecurityCheck(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
         try {
             const data = ctx.request.body as any;
-            logger.info("内容安全审核请求参数:", data);
+            // 支持从GET query参数或POST body中获取platform参数
+            const platform = ctx.request.query.platform || data.platform || 'miniapp';
+            logger.info("内容安全审核请求参数:", { ...data, platform });
 
             // 验证必要参数
             const requiredParams = ['uid', 'scene', 'content'];
@@ -625,15 +735,24 @@ export class MiniappChannelHandler implements ChannelHandler {
                 }
             }
 
-            // 调用通用内容安全审核方法
-            const checkResult = await this.performContentSecurityCheck({
-                uid: data.uid,
-                content: data.content,
-                scene: data.scene,
-                nickname: data.nickname,
-                title: data.title,
-                usersign: data.usersign
-            }, config);
+            // 根据platform调用对应的内容安全审核方法
+            const checkResult = platform === 'ttminiapp' 
+                ? await this.performByteDanceContentSecurityCheck({
+                    uid: data.uid,
+                    content: data.content,
+                    scene: data.scene,
+                    nickname: data.nickname,
+                    title: data.title,
+                    usersign: data.usersign
+                }, config)
+                : await this.performMiniappContentSecurityCheck({
+                    uid: data.uid,
+                    content: data.content,
+                    scene: data.scene,
+                    nickname: data.nickname,
+                    title: data.title,
+                    usersign: data.usersign
+                }, config);
 
             // 处理审核结果
             if (checkResult.success && checkResult.result) {
@@ -670,21 +789,30 @@ export class MiniappChannelHandler implements ChannelHandler {
      * @param uid 用户ID
      * @param config 渠道配置
      * @param scene 场景类型,默认为'1'(角色名称)
+     * @param platform 平台类型:miniapp(小程序)或 ttminiapp(抖音小程序),默认为 miniapp
      * @returns 检查结果,suggest: pass/review/reject/risky
      */
     private async checkContentSecurity(
         content: string, 
         uid: string, 
         config: ChannelConfig,
-        scene: string = '1'
+        scene: string = '1',
+        platform: string = 'miniapp'
     ): Promise<{ success: boolean; suggest?: string; message: string }> {
-        // 调用通用内容安全审核方法
-        const checkResult = await this.performContentSecurityCheck({
-            uid: uid,
-            content: content,
-            scene: scene
-        }, config);
+        // 根据platform调用对应的内容安全审核方法
+        const checkResult = platform === 'ttminiapp'
+            ? await this.performByteDanceContentSecurityCheck({
+                uid: uid,
+                content: content,
+                scene: scene
+            }, config)
+            : await this.performMiniappContentSecurityCheck({
+                uid: uid,
+                content: content,
+                scene: scene
+            }, config);
 
+        console.log("checkResult:", checkResult);
         // 处理审核结果
         if (checkResult.success && checkResult.result) {
             const suggest = checkResult.result.suggest; // pass/review/reject/risky
@@ -741,8 +869,9 @@ export class MiniappChannelHandler implements ChannelHandler {
             // API错误时,为了不影响用户体验,可以选择允许通过或拒绝
             // 这里选择允许通过,但记录错误日志
             return {
-                success: true,
-                message: "内容安全审核失败,已允许通过"
+                success: false, 
+                suggest: "reject",
+                message: "内容安全审核失败,已拒绝"
             };
         }
     }
@@ -755,7 +884,10 @@ export class MiniappChannelHandler implements ChannelHandler {
     async editUserRoleInfo(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
         try {
             const data = ctx.request.body as any;
-            logger.info("角色名称修改上报请求参数:", data);
+            // 支持从GET query参数或POST body中获取platform参数
+            const platform = ctx.request.query.platform || data.platform || 'miniapp';
+            logger.info("角色名称修改上报请求参数:", { ...data, platform });
+            
             // 验证必要参数
             const requiredParams = ['openId', 'serverid', 'playerName'];
             for (const param of requiredParams) {
@@ -798,7 +930,7 @@ export class MiniappChannelHandler implements ChannelHandler {
             console.log("playerName for signature:", data.playerName);
 
             // 内容安全审核:验证角色名称是否包含敏感内容
-            const securityCheck = await this.checkContentSecurity(decodedPlayerName, data.openId, config);
+            const securityCheck = await this.checkContentSecurity(decodedPlayerName, data.openId, config, '1', platform as string);
             if (!securityCheck.success) {
                 logger.warn("角色名称内容安全审核未通过:", {
                     playerName: decodedPlayerName,

+ 2 - 0
webServer/src/controller/ApiController.ts

@@ -1081,6 +1081,8 @@ class ApiController {
                 "gf100",
                 "gf200",
                 "gf300",
+                "YDKL888",
+                "SDKL888",
             ];
             let param: string = "";
 

+ 12 - 12
webServer/src/controller/MiniAppController.ts

@@ -101,22 +101,22 @@ class MiniappController {
       if (result.code === -1) {
         // 失败情况(包括内容安全审核失败)
         ctx.body = {
-          error: -1,
-          errmsg: result.msg || "角色名称修改失败"
+          code: -1,
+          msg: result.msg || "角色名称修改失败"
         };
       } else {
         // 成功情况
         ctx.body = {
-          error: 0,
-          errmsg: result.msg || "修改成功"
+          code: 0,
+          msg: result.msg || "修改成功"
         };
       }
 
     } catch (error) {
       logger.error("角色名称修改上报出错:", error);
       ctx.body = {
-        error: -1,
-        errmsg: error.message || "角色名称修改失败"
+        code: -1,
+        msg: error.message || "角色名称修改失败"
       };
     }
   }
@@ -230,8 +230,8 @@ class MiniappController {
       if (expectedSignature !== data.sign) {
         logger.error("解除禁言接口签名验证失败");
         ctx.body = {
-          error: -1,
-          errmsg: "签名验证失败"
+          code: -1,
+          msg: "签名验证失败"
         };
         return;
       }
@@ -241,13 +241,13 @@ class MiniappController {
       
       if (gameResult) {
         ctx.body = {
-          error: 0,
-          errmsg: ""
+          code: 0,
+          msg: ""
         };
       } else {
         ctx.body = {
-          error: -1,
-          errmsg: "解除禁言失败"
+          code: -1,
+          msg: "解除禁言失败"
         };
       }
 

+ 2 - 2
webServer/src/router/miniapp.ts

@@ -3,10 +3,10 @@ const MiniAppController = require("../controller/MiniappController");
 
 const miniAppRouter = new Router();
 
-// 内容安全审核
+// 内容安全审核(支持platform query参数)
 miniAppRouter.post("/contentSecurityCheck", MiniAppController.contentSecurityCheck);
 
-// 角色名称修改上报
+// 角色名称修改上报(支持platform query参数)
 miniAppRouter.post("/editUserRoleInfo", MiniAppController.editUserRoleInfo);
 
 // 禁言接口