소스 검색

小程序sdk优化

flowerpig 8 달 전
부모
커밋
c62f69769c

+ 2 - 0
webServer/src/channels/factory/ChannelFactory.ts

@@ -8,6 +8,7 @@ import { ThreeSixZeroChannelHandler } from "../handlers/ThreeSixZeroChannelHandl
 import { MuZiChannelHandler } from "../handlers/MuZiChannelHandler";
 import { QiAiH5ChannelHandler } from "../handlers/QiAiH5ChannelHandler";
 import { MuZiIosChannelHandler } from "../handlers/MuZiIosChannelHandler";
+import { MiniappChannelHandler } from "../handlers/MiniappChannelHandler";
 
 
 const logger = require("../../utils/log");
@@ -39,6 +40,7 @@ class ChannelFactory {
     this.registerHandler(8, new QiAiH5ChannelHandler()); // qi ai
     this.registerHandler(9, new MuZiIosChannelHandler()); // muzi ios
     this.registerHandler(10, new SanLiAndroidChannelHandler()); // muzi ios
+    this.registerHandler(11, new MiniappChannelHandler()); // muzi ios
   }
 
   /**

+ 725 - 0
webServer/src/channels/handlers/MiniappChannelHandler.ts

@@ -0,0 +1,725 @@
+import { Context } from "koa";
+import {
+  ChannelHandler,
+  LoginResult,
+  PaymentResult,
+} from "../interfaces/ChannelHandler";
+import { ChannelConfig } from "../../config/channelConfig";
+import { PaymentHelper } from "../../utils/PaymentHelper";
+import { getServerList, formatDate } from "../../utils/common";
+import { Account } from "../../config/thirdParams";
+import Msg from "../../utils/msg";
+import axios from "axios";
+
+const Order = require("../../model/OrderModel");
+const CryptoJS = require("crypto-js");
+const logger = require("../../utils/log");
+
+export class MiniappChannelHandler implements ChannelHandler {
+  /**
+   * 获取HTTPS代理配置
+   * @returns HTTPS代理配置
+   */
+  private getHttpsAgent() {
+    const https = require('https');
+    return new https.Agent({
+      rejectUnauthorized: false,
+      secureProtocol: 'TLSv1_2_method',
+      timeout: 10000
+    });
+  }
+
+  /**
+   * 获取通用请求头
+   * @returns 请求头配置
+   */
+  private getCommonHeaders() {
+    return {
+      'User-Agent': 'Mozilla/5.0 (compatible; WebServer/1.0)',
+      'Accept': 'application/json',
+      'Content-Type': 'application/json'
+    };
+  }
+
+  /**
+   * 小程序登录鉴权
+   * @param ctx Koa上下文
+   * @param config 渠道配置
+   */
+    async handleLogin(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
+    try {
+      const data = ctx.request.body;
+      const token = data.token;
+      
+      if (!token) {
+        return {
+          code: -1,
+          msg: "缺少token参数",
+          data: null
+        };
+      }
+
+      const loginUrl = `https://wxlogin.${config.paymentConfig.apiUrl}/wxlogin?cmd=checkUserToken&token=${token}`;
+      logger.info("小程序登录请求", { token, loginUrl });
+      
+      const wxLogin = await axios.get(loginUrl, {
+        httpsAgent: this.getHttpsAgent(),
+        headers: this.getCommonHeaders()
+      });
+      logger.info("小程序登录响应", { data: wxLogin.data });
+
+      return {
+        code: 0,
+        msg: "success",
+        data: wxLogin.data,
+      };
+    } catch (error) {
+      logger.error('wxLogin error:', error);
+      return {
+        code: -1,
+        msg: error.message || "登录验证失败",
+        data: null,
+      };
+    }
+  }
+
+  /**
+   * 小程序支付回调处理
+   * @param ctx Koa上下文
+   * @param config 渠道配置
+   */
+  async handlePayment(ctx: Context, config: ChannelConfig): Promise<PaymentResult> {
+    try {
+      // 获取请求参数
+      const params = ctx.request.query;
+      logger.info("小程序支付回调参数:", { url: ctx.href, params: params });
+
+      // 验证必要参数
+      const requiredParams = ['uid', 'rmb', 'reqid', 'trans_id', 'product_id', 'notify_id', 'sign'];
+      for (const param of requiredParams) {
+        if (!params[param]) {
+          logger.error(`缺少必要参数: ${param}`);
+          return {
+            code: -1,
+            msg: `缺少必要参数: ${param}`,
+            data: null
+          };
+        }
+      }
+
+      // 验证签名
+      const parameters = Object.keys(params)
+        .filter(key => key !== 'sign')
+        .map(key => `${key}=${params[key]}`);
+
+      const expectedSignature = this.generateSignature(parameters, config.paymentConfig.signKey!);
+      if (params.sign !== expectedSignature) {
+        logger.error("小程序支付签名验证失败", {
+          received: params.sign,
+          expected: expectedSignature
+        });
+        return {
+          code: -1,
+          msg: "签名验证失败",
+          data: null
+        };
+      }
+
+      // 获取订单信息
+      const orderId = params.reqid;
+      const orderInfo = (await Order.getOrder(orderId))[0];
+
+      if (!orderInfo) {
+        logger.error(`订单${orderId}不存在`);
+        return {
+          code: -1,
+          msg: "订单不存在",
+          data: null
+        };
+      }
+
+      if (orderInfo.status == 2) {
+        logger.info(`订单${orderId}已经重复发货`);
+        return {
+          code: 0,
+          msg: "订单已发货",
+          data: null
+        };
+      }
+
+      // 验证金额
+      const amount = parseFloat(params.rmb);
+      if (orderInfo.amount != amount) {
+        logger.error("订单金额不一致", {
+          "orderInfo.amount": orderInfo.amount,
+          "params.amount": amount,
+        });
+        return {
+          code: -1,
+          msg: "订单金额不一致",
+          data: null
+        };
+      }
+
+      // 订单校验 - 验证支付是否成功
+      const orderCheckResult = await this.wxOrderCheck(params.notify_id, config);
+      if (!orderCheckResult.success) {
+        logger.error(`订单${orderId}校验失败: ${orderCheckResult.message}`);
+        return {
+          code: -1,
+          msg: `订单校验失败: ${orderCheckResult.message}`,
+          data: null
+        };
+      }
+
+      // 获取服务器URL
+      const url = await getServerList(orderInfo.server_id, orderInfo.channel_id);
+      if (!url) {
+        logger.error(`区服id错误: serverId ${orderInfo.server_id}`);
+        return {
+          code: -1,
+          msg: "区服id错误",
+          data: null
+        };
+      }
+
+      // 发货处理
+      logger.info(`小程序支付订单${orderId}通知游戏发货开始`);
+      const result = await this.deliverOrder(
+        orderInfo,
+        ctx.request.ip,
+        url,
+        params.trans_id
+      );
+
+      if ((result as any).code === 1) {
+        logger.info(`小程序支付订单${orderId}发货成功`);
+        return {
+          code: 0,
+          msg: "发货成功",
+          data: null
+        };
+      } else {
+        logger.error(`小程序支付订单${orderId}发货失败: ${(result as any).msg}`);
+        return {
+          code: -1,
+          msg: `发货失败: ${(result as any).msg}`,
+          data: null
+        };
+      }
+
+    } catch (error) {
+      logger.error("小程序支付处理出错:", error);
+      return {
+        code: -1,
+        msg: "支付处理失败",
+        data: null
+      };
+    }
+  }
+
+  /**
+   * 订单校验 - 验证支付是否成功
+   * @param notifyId 平台通知ID
+   * @param config 渠道配置
+   * @returns 校验结果
+   */
+  async wxOrderCheck(notifyId: string, config: ChannelConfig): Promise<{ success: boolean; message: string }> {
+    try {
+      // 构建验证参数
+      const parameters = [
+        `gameid=${config.paymentConfig.gameId}`,
+        `notify_id=${notifyId}`
+      ];
+
+      // 生成签名
+      const signature = this.generateSignature(parameters, config.paymentConfig.signKey!);
+      
+      // 构建验证URL
+      const verifyUrl = `https://login.${config.paymentConfig.apiUrl}/pay/paygate/verify.php?gameid=${config.paymentConfig.gameId}&notify_id=${notifyId}&sign=${signature}`;
+      
+      logger.info("订单校验请求", { notifyId, verifyUrl });
+
+      // 调用平台验证接口
+      const response = await axios.get(verifyUrl, {
+        httpsAgent: this.getHttpsAgent(),
+        headers: {
+          ...this.getCommonHeaders(),
+          'Accept': 'text/plain'
+        }
+      });
+      
+      logger.info("订单校验响应", { notifyId, response: response.data });
+
+      // 检查返回结果
+      if (response.data === "SUCCESS") {
+        return {
+          success: true,
+          message: "订单支付成功"
+        };
+      } else {
+        return {
+          success: false,
+          message: "订单支付失败或无效"
+        };
+      }
+
+    } catch (error) {
+      logger.error("订单校验出错:", { notifyId, error: error.message });
+      return {
+        success: false,
+        message: "订单校验失败"
+      };
+    }
+  }
+
+  /**
+   * 内容安全审核接口
+   * @param ctx Koa上下文
+   * @param config 渠道配置
+   */
+  async contentSecurityCheck(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
+    try {
+      const data = ctx.request.body;
+      logger.info("内容安全审核请求参数:", data);
+
+      // 验证必要参数
+      const requiredParams = ['uid', 'gameid', 'signature', 'timestamp', 'nonce', 'scene', 'content'];
+      for (const param of requiredParams) {
+        if (!data[param]) {
+          logger.error(`缺少必要参数: ${param}`);
+          return {
+            code: -1,
+            msg: `缺少必要参数: ${param}`,
+            data: null
+          };
+        }
+      }
+
+      // 验证签名算法1
+      const isValidSignature = this.verifySignatureAlgorithm1(data, config);
+      if (!isValidSignature) {
+        logger.error("内容安全审核签名验证失败");
+        return {
+          code: -1,
+          msg: "签名验证失败",
+          data: null
+        };
+      }
+
+      // 构建请求参数
+      const requestData = {
+        uid: data.uid,
+        gameid: data.gameid,
+        signature: data.signature,
+        timestamp: data.timestamp,
+        nonce: data.nonce,
+        scene: data.scene,
+        content: data.content,
+        nickname: data.nickname || '',
+        title: data.title || '',
+        usersign: data.usersign || ''
+      };
+
+      // 调用内容安全API
+      const apiUrl = `https://api.${config.paymentConfig.apiUrl}/mpcommon/?cmd=wxaMsgSecCheck`;
+      logger.info("调用内容安全API:", { url: apiUrl, data: requestData });
+
+      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) {
+        const result = response.data.result;
+        return {
+          code: 0,
+          msg: "success",
+          data: {
+            suggest: result.suggest, // pass/review/reject
+            label: result.label,
+            trace_id: response.data.trace_id,
+            detail: response.data.detail
+          }
+        };
+      } else {
+        return {
+          code: -1,
+          msg: response.data?.errmsg || "内容安全检测失败",
+          data: null
+        };
+      }
+
+    } catch (error) {
+      logger.error("内容安全审核出错:", error);
+      return {
+        code: -1,
+        msg: "内容安全审核失败",
+        data: null
+      };
+    }
+  }
+
+  /**
+   * 角色名称修改上报
+   * @param ctx Koa上下文
+   * @param config 渠道配置
+   */
+  async editUserRoleInfo(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
+    try {
+        const data = ctx.request.body;
+      logger.info("角色名称修改上报请求参数:", data);
+
+      // 验证必要参数
+      const requiredParams = ['openId', 'time', 'gameid', 'serverid', 'playerName', 'sign'];
+      for (const param of requiredParams) {
+        if (!data[param]) {
+          logger.error(`缺少必要参数: ${param}`);
+          return {
+            code: -1,
+            msg: `缺少必要参数: ${param}`,
+            data: null
+          };
+        }
+      }
+
+      // 验证签名算法2
+      const isValidSignature = this.verifySignatureAlgorithm2(data, config);
+      if (!isValidSignature) {
+        logger.error("角色名称修改上报签名验证失败");
+        return {
+          code: -1,
+          msg: "签名验证失败",
+          data: null
+        };
+      }
+
+      // 构建请求参数
+      const requestData = {
+        openId: data.openId,
+        time: data.time,
+        gameid: data.gameid,
+        serverid: data.serverid,
+        playerName: encodeURIComponent(data.playerName), // 中文URL编码
+        sign: data.sign
+      };
+
+      // 调用角色信息修改API
+      const apiUrl = `https://platform.${config.paymentConfig.apiUrl}/stat/api/?cmd=editUserRoleInfo`;
+      logger.info("调用角色信息修改API:", { url: apiUrl, data: requestData });
+
+      const response = await axios.get(apiUrl, { 
+        params: requestData,
+        timeout: 10000,
+        headers: {
+          'User-Agent': 'Mozilla/5.0 (compatible; WebServer/1.0)',
+          'Accept': 'application/json'
+        },
+        httpsAgent: this.getHttpsAgent()
+      });
+      logger.info("角色信息修改API响应:", response.data);
+
+      // 处理响应结果
+      if (response.data && response.data.error === 0) {
+        return {
+          code: 0,
+          msg: "success",
+          data: null
+        };
+      } else {
+        return {
+          code: -1,
+          msg: response.data?.errmsg || "角色信息修改失败",
+          data: null
+        };
+      }
+
+    } catch (error) {
+      logger.error("角色名称修改上报出错:", error);
+      return {
+        code: -1,
+        msg: "角色信息修改失败",
+        data: null
+      };
+    }
+  }
+
+  /**
+   * 签名算法2验证
+   * @param data 请求数据
+   * @param config 渠道配置
+   * @returns 验证结果
+   */
+  private verifySignatureAlgorithm2(data: any, config: ChannelConfig): boolean {
+    try {
+      const { openId, time, gameid, serverid, playerName, sign } = data;
+      
+      // 构建待签名字符串 - 按字母顺序排序
+      const params: any = {
+        openId: openId.toString(),
+        time: time.toString(),
+        gameid: gameid.toString(),
+        serverid: serverid.toString(),
+        playerName: playerName.toString()
+      };
+
+      // 按字母顺序排序并拼接
+      const sortedKeys = Object.keys(params).sort();
+      const queryString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
+      
+      // 添加统计API密钥
+      const stringToSign = `${queryString}&key=${config.loginConfig?.statApiKey}`;
+      
+      // 计算MD5签名
+      const expectedSignature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
+      
+      logger.info("签名算法2验证详情:", {
+        queryString,
+        stringToSign,
+        expectedSignature,
+        receivedSignature: sign
+      });
+
+      return sign === expectedSignature;
+    } catch (error) {
+      logger.error("签名算法2验证出错:", error);
+      return false;
+    }
+  }
+
+  /**
+   * 生成角色信息修改签名(供客户端使用)
+   * @param params 签名参数
+   * @param config 渠道配置
+   * @returns 签名结果
+   */
+  generateRoleInfoSignature(params: any, config: ChannelConfig): string | null {
+    try {
+      const { openId, time, gameid, serverid, playerName } = params;
+      
+      // 构建待签名字符串 - 按字母顺序排序
+      const signParams: any = {
+        openId: openId.toString(),
+        time: time.toString(),
+        gameid: gameid.toString(),
+        serverid: serverid.toString(),
+        playerName: playerName.toString()
+      };
+
+      // 按字母顺序排序并拼接
+      const sortedKeys = Object.keys(signParams).sort();
+      const queryString = sortedKeys.map(key => `${key}=${signParams[key]}`).join('&');
+      
+      // 添加统计API密钥
+      const stringToSign = `${queryString}&key=${config.loginConfig?.statApiKey}`;
+      
+      // 计算MD5签名
+      const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
+      
+      return signature;
+    } catch (error) {
+      logger.error("生成角色信息修改签名出错:", error);
+      return null;
+    }
+  }
+
+  /**
+   * 签名算法1验证
+   * @param data 请求数据
+   * @param config 渠道配置
+   * @returns 验证结果
+   */
+  private verifySignatureAlgorithm1(data: any, config: ChannelConfig): boolean {
+    try {
+      const { uid, gameid, timestamp, nonce, scene, content, nickname, title, usersign, signature } = data;
+      
+      // 构建待签名字符串 - 按字母顺序排序
+      const params: any = {
+        uid: uid.toString(),
+        gameid: gameid.toString(),
+        timestamp: timestamp.toString(),
+        nonce: nonce.toString(),
+        scene: scene.toString(),
+        content: content
+      };
+
+      // 添加可选参数(如果存在)
+      if (nickname) params.nickname = nickname;
+      if (title) params.title = title;
+      if (usersign) params.usersign = usersign;
+
+      // 按字母顺序排序并拼接
+      const sortedKeys = Object.keys(params).sort();
+      const queryString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
+      
+      // 添加API密钥
+      const stringToSign = `${queryString}&key=${config.loginConfig?.apiKey}`;
+      
+      // 计算MD5签名
+      const expectedSignature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
+      
+      logger.info("签名验证详情:", {
+        queryString,
+        stringToSign,
+        expectedSignature,
+        receivedSignature: signature
+      });
+
+      return signature === expectedSignature;
+    } catch (error) {
+      logger.error("签名算法1验证出错:", error);
+      return false;
+    }
+  }
+
+  /**
+   * 生成内容安全签名(供客户端使用)
+   * @param params 签名参数
+   * @param config 渠道配置
+   * @returns 签名结果
+   */
+  generateContentSecuritySignature(params: any, config: ChannelConfig): string | null {
+    try {
+      const { uid, gameid, timestamp, nonce, scene, content, nickname, title, usersign } = params;
+      
+      // 构建待签名字符串 - 按字母顺序排序
+      const signParams: any = {
+        uid: uid.toString(),
+        gameid: gameid.toString(),
+        timestamp: timestamp.toString(),
+        nonce: nonce.toString(),
+        scene: scene.toString(),
+        content: content
+      };
+
+      // 添加可选参数(如果存在)
+      if (nickname) signParams.nickname = nickname;
+      if (title) signParams.title = title;
+      if (usersign) signParams.usersign = usersign;
+
+      // 按字母顺序排序并拼接
+      const sortedKeys = Object.keys(signParams).sort();
+      const queryString = sortedKeys.map(key => `${key}=${signParams[key]}`).join('&');
+      
+      // 添加API密钥
+      const stringToSign = `${queryString}&key=${config.loginConfig?.apiKey}`;
+      
+      // 计算MD5签名
+      const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
+      
+      return signature;
+    } catch (error) {
+      logger.error("生成内容安全签名出错:", error);
+      return null;
+    }
+  }
+
+  /**
+   * 发货处理方法
+   * @param orderInfo 订单信息
+   * @param ip 客户端IP
+   * @param url 游戏服务器URL
+   * @param out_trade_no 外部交易号
+   * @returns 发货结果
+   */
+  private async deliverOrder(orderInfo: any, ip: string, url: string, out_trade_no: string): Promise<{ code: number; msg: string }> {
+    return new Promise((resolve) => {
+      const sendMsg = new Msg();
+      logger.info("通知游戏服务器url", { url: url });
+
+      sendMsg.connect(url, Account);
+      setTimeout(async () => {
+        try {
+          // 构建消息参数
+          const params = JSON.stringify({
+            account: orderInfo.uid,
+            channel_id: orderInfo.channel_id,
+            order: orderInfo.order_id,
+            id: orderInfo.product_id,
+            cnt: 100,
+            money: orderInfo.amount,
+          });
+
+          logger.info("通知游戏服务器参数", { data: params });
+          logger.info("通知游戏服务器orderInfo", { orderInfo: orderInfo });
+          let send_res = sendMsg.CG_ASK_LOGIN(
+            Account,
+            0,
+            "",
+            "cn",
+            "CN",
+            ip,
+            params,
+            orderInfo.server_id
+          );
+
+          if (!send_res) {
+            resolve({ code: 0, msg: "通知服务器失败" });
+            return;
+          }
+
+          // 更新订单状态
+          const update_time = formatDate(new Date());
+          const res = await Order.updateOrderStats(
+            orderInfo.order_id,
+            2,
+            out_trade_no,
+            update_time,
+            orderInfo.uid
+          );
+
+          if (res.affectedRows <= 0) {
+            logger.info(`订单${orderInfo.order_id} 发货失败`);
+            resolve({ code: 0, msg: "发货失败" });
+            return;
+          }
+
+          resolve({ code: 1, msg: "发货成功" });
+        } catch (error) {
+          logger.error("发货过程出错:", error);
+          resolve({ code: 0, msg: "发货失败" });
+        }
+      }, 1500);
+    });
+  }
+
+  /**
+   * 小程序签名函数(签名算法3)
+   * @param parameters 参数数组
+   * @param privateKey 私钥
+   * @returns 签名结果
+   */
+  private generateSignature(parameters: string[], privateKey: string): string {
+    // 1. 过滤掉空值和sign参数
+    const filteredParams = parameters.filter(param => {
+      const [key, value] = param.split('=');
+      return key !== 'sign' && value && value.trim() !== '';
+    });
+
+    // 2. 对参数进行URL编码
+    const encodedParams = filteredParams.map(param => {
+      const [key, value] = param.split('=');
+      const encodedValue = encodeURIComponent(value);
+      return `${key}=${encodedValue}`;
+    });
+
+    // 3. 按字母顺序排序
+    encodedParams.sort((a, b) => {
+      return a.localeCompare(b);
+    });
+
+    // 4. 用&连接所有参数
+    const queryString = encodedParams.join('&');
+
+    // 5. 拼接私钥
+    const stringToSign = `${queryString}&key=${privateKey}`;
+
+    // 6. 计算MD5并转大写
+    const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
+
+    return signature;
+      }
+}

+ 16 - 6
webServer/src/config/channelConfig.ts

@@ -22,6 +22,11 @@ import {
   QIAI_QUICK_H5_CALLBACK_KEY,
   QIAI_QUICK_H5_PRODUCT_CODE,
   QIAI_QUICK_H5_MD5_KEY,
+  MINI_APP_DOMAIN,
+  MINI_APP_PRIVATE_KEY,
+  MINI_APP_GAME_ID,
+  MINI_APP_API_KEY,
+  MINI_APP_STAT_API_KEY,
 } from "./thirdParams";
 
 // 渠道配置接口定义
@@ -37,6 +42,7 @@ export interface ChannelConfig {
     apiUrl?: string; // API地址
     clientSecret?: string; // 客户端密钥
     ClientId?: string; // 客户端id
+    gameId?: string; // 游戏ID
   };
   loginConfig?: {
     // 登录相关配置
@@ -44,6 +50,8 @@ export interface ChannelConfig {
     appId?: string; // 应用ID
     signKey?: string; // 签名密钥
     callKey?: string; // 签名密钥
+    apiKey?: string; // API密钥
+    statApiKey?: string; // 统计API密钥
   };
 }
 
@@ -186,16 +194,18 @@ export const channelConfigs: Record<number, ChannelConfig> = {
     },
   },
   11: {
-    // 三狸安卓
+    // 小程序
     channelId: 11,
-    name: "小游戏",
-    platform: "minigame",
+    name: "小程序",
+    platform: "miniapp",
     paymentConfig: {
-      signKey: QUICK_MD5_KEY,
-      callbackKey: QUICK_CALLBACK_KEY,
+      signKey: MINI_APP_PRIVATE_KEY,
+      apiUrl: MINI_APP_DOMAIN,
+      gameId: MINI_APP_GAME_ID,
     },
     loginConfig: {
-      productCode: QUICK_PRODUCT_CODE,
+      apiKey: MINI_APP_API_KEY,
+      statApiKey: MINI_APP_STAT_API_KEY,
     },
   },
 };

+ 10 - 1
webServer/src/config/thirdParams.ts

@@ -89,4 +89,13 @@ export const SECRET_KEY_QIHU = "IrIRKXs674NiNZiNSaaPQsgX904LwFgu";
 
 export const QIAI_QUICK_H5_MD5_KEY = "qnevushjm7deklbc1mbr55iqejzxnyco";
 export const QIAI_QUICK_H5_CALLBACK_KEY = "37750567448382738619439231053656";
-export const QIAI_QUICK_H5_PRODUCT_CODE = "80939198711722706880933346971719";
+export const QIAI_QUICK_H5_PRODUCT_CODE = "80939198711722706880933346971719";
+
+//小程序
+
+export const MINI_APP_DOMAIN = "wefunol.com";
+export const MINI_APP_PRIVATE_KEY = "yduLY3ovg4NwTHMMemGg1vO6VHuYBcYD";
+export const MINI_APP_GAME_ID = "1540";
+export const MINI_APP_API_KEY = "your_api_key_here";
+export const MINI_APP_STAT_API_KEY = "your_stat_api_key_here";
+

+ 3 - 62
webServer/src/controller/ApiController.ts

@@ -532,6 +532,9 @@ class ApiController {
       case 7:
         ctx.body = result.code === 1 ? "success" : "fail";
         break;
+      case 11:
+        ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
+        break;
       default:
         ctx.body = result;
     }
@@ -1317,68 +1320,6 @@ class ApiController {
     ctx.body = ApiController.success("success", 0, false, data);
   }
 
-
-  //小程序SDK接入
-  //游光文档:http://platform-doc.ttwmz.com/docs/channel/channel/awy/xyx-fear-end.html#%E9%89%B4%E6%9D%83
-  miniAppDomain = "wefunol.com ";
-  //登录鉴权
-  async wxLogin(ctx) {
-    try {
-    let data = ctx.request.body;
-    let token = data.token;
-      let loginUrl = `https://wxlogin.${this.miniAppDomain}.com/wxlogin?cmd=checkUserToken&token=${token}`
-    let wxLogin = await axios.get(loginUrl);
-
-    ctx.body = {
-        code: 0,
-        msg: "success",
-      data: wxLogin.data,
-      }
-    } catch (error) {
-      console.error('wxLogin error:', error);
-      ctx.body = {
-        code: -1,
-        msg: error.message || "登录验证失败",
-        data: null,
-      }
-    }
-  }
-
-  // 小程序签名函数
-  generateSignature(parameters, privateKey) {
-    // 1. 过滤掉空值和sign参数
-    const filteredParams = parameters.filter(param => {
-      const [key, value] = param.split('=');
-      return key !== 'sign' && value && value.trim() !== '';
-    });
-
-    // 2. 对参数进行URL编码
-    const encodedParams = filteredParams.map(param => {
-      const [key, value] = param.split('=');
-      const encodedValue = encodeURIComponent(value);
-      return `${key}=${encodedValue}`;
-    });
-
-    // 3. 按字母顺序排序
-    encodedParams.sort((a, b) => {
-      return a.localeCompare(b);
-    });
-
-    // 4. 用&连接所有参数
-    const queryString = encodedParams.join('&');
-
-    // 5. 拼接私钥
-    const stringToSign = `${queryString}&key=${privateKey}`;
-
-    // 6. 计算MD5并转大写
-    const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
-
-    return signature;
-  }
-
-
- 
-   
  
   
 }

+ 45 - 628
webServer/src/controller/MiniAppController.ts

@@ -1,330 +1,72 @@
-// 导入必要的模块
-import Msg from "../utils/msg";
+import { Context } from "koa";
 import { getServerList, formatDate } from "../utils/common";
 import { Account } from "../config/thirdParams";
+import Msg from "../utils/msg";
+import axios from "axios";
 
 const Order = require("../model/OrderModel");
 const CryptoJS = require("crypto-js");
-const axios = require("axios");
 const logger = require("../utils/log");
 
+// 导入小程序配置
+import { 
+  MINI_APP_DOMAIN, 
+  MINI_APP_PRIVATE_KEY, 
+  MINI_APP_GAME_ID, 
+  MINI_APP_API_KEY, 
+  MINI_APP_STAT_API_KEY 
+} from "../config/thirdParams";
+
+// 导入渠道处理器和配置
+import { channelFactory } from "../channels/factory/ChannelFactory";
+import { channelConfigs } from "../config/channelConfig";
+
 /**
  * 小程序控制器
- * 处理小程序相关的登录、支付、内容安全等功能
+ * 处理内容安全审核和角色名称修改上报功能
  */
-class MiniAppController {
-  // 小程序SDK接入配置
-  // 游光文档:http://platform-doc.ttwmz.com/docs/channel/channel/awy/xyx-fear-end.html#%E9%89%B4%E6%9D%83
-  private miniAppDomain: string = "wefunol.com"; // 小程序域名
-  private miniAppPrivateKey: string = "yduLY3ovg4NwTHMMemGg1vO6VHuYBcYD"; // 发货私钥
-  private miniAppGameId: string = "1540"; // 游戏ID
-  private miniAppApiKey: string = "your_api_key_here"; // 内容安全API密钥
-  private miniAppStatApiKey: string = "your_stat_api_key_here"; // 统计API密钥
-
+class MiniappController {
   constructor() {
     // 初始化配置
   }
 
   /**
-   * 获取HTTPS代理配置
-   * @returns HTTPS代理配置
+   * 获取小程序渠道处理器
+   * @returns 渠道处理器实例
    */
-  private getHttpsAgent() {
-    const https = require('https');
-    return new https.Agent({
-      rejectUnauthorized: false,
-      secureProtocol: 'TLSv1_2_method',
-      timeout: 10000
-    });
+  private static getChannelHandler() {
+    return channelFactory.getHandler(11); // 小程序渠道ID
   }
 
   /**
-   * 获取通用请求头
-   * @returns 请求头配置
+   * 获取小程序渠道配置
+   * @returns 渠道配置
    */
-  private getCommonHeaders() {
-    return {
-      'User-Agent': 'Mozilla/5.0 (compatible; WebServer/1.0)',
-      'Accept': 'application/json',
-      'Content-Type': 'application/json'
-    };
+  private static getChannelConfig() {
+    return channelConfigs[11]; // 小程序渠道ID
   }
 
   /**
-   * 小程序登录鉴权
+   * 内容安全审核接口
    * @param ctx Koa上下文
    */
-  async wxLogin(ctx: any) {
+  async contentSecurityCheck(ctx: Context) {
     try {
-      const data = ctx.request.body;
-      const token = data.token;
+      const handler = MiniappController.getChannelHandler();
+      const config = MiniappController.getChannelConfig();
       
-      if (!token) {
+      if (!handler) {
         ctx.body = {
           code: -1,
-          msg: "缺少token参数",
+          msg: "渠道处理器未找到",
           data: null
         };
         return;
       }
 
-      const loginUrl = `https://wxlogin.${this.miniAppDomain}.com/wxlogin?cmd=checkUserToken&token=${token}`;
-      logger.info("小程序登录请求", { token, loginUrl });
-      
-      const wxLogin = await axios.get(loginUrl, {
-        httpsAgent: this.getHttpsAgent(),
-        headers: this.getCommonHeaders()
-      });
-      logger.info("小程序登录响应", { data: wxLogin.data });
-
-      ctx.body = {
-        code: 0,
-        msg: "success",
-        data: wxLogin.data,
-      };
-    } catch (error) {
-      logger.error('wxLogin error:', error);
-      ctx.body = {
-        code: -1,
-        msg: error.message || "登录验证失败",
-        data: null,
-      };
-    }
-  }
-  /**
-   * 小程序发货接口
-   * @param ctx Koa上下文
-   */
-  async wxPay(ctx: any) {
-    try {
-      // 获取请求参数
-      const params = ctx.request.query;
-      logger.info("小程序支付回调参数:", { url: ctx.href, params: params });
-
-      // 验证必要参数
-      const requiredParams = ['uid', 'rmb', 'reqid', 'trans_id', 'product_id', 'notify_id', 'sign'];
-      for (const param of requiredParams) {
-        if (!params[param]) {
-          logger.error(`缺少必要参数: ${param}`);
-          ctx.body = "FAIL";
-          return;
-        }
-      }
-
-      // 验证签名
-      const parameters = Object.keys(params)
-        .filter(key => key !== 'sign')
-        .map(key => `${key}=${params[key]}`);
-
-      const expectedSignature = this.generateSignature(parameters, this.miniAppPrivateKey);
-      if (params.sign !== expectedSignature) {
-        logger.error("小程序支付签名验证失败", {
-          received: params.sign,
-          expected: expectedSignature
-        });
-        ctx.body = "FAIL";
-        return;
-      }
-
-      // 获取订单信息
-      const orderId = params.reqid;
-      const orderInfo = (await Order.getOrder(orderId))[0];
-
-      if (!orderInfo) {
-        logger.error(`订单${orderId}不存在`);
-        ctx.body = "FAIL";
-        return;
-      }
-
-      if (orderInfo.status == 2) {
-        logger.info(`订单${orderId}已经重复发货`);
-        ctx.body = "SUCCESS";
-        return;
-      }
-
-      // 验证金额
-      const amount = parseFloat(params.rmb);
-      if (orderInfo.amount != amount) {
-        logger.error("订单金额不一致", {
-          "orderInfo.amount": orderInfo.amount,
-          "params.amount": amount,
-        });
-        ctx.body = "FAIL";
-        return;
-      }
-
-      // 订单校验 - 验证支付是否成功
-      const orderCheckResult = await this.wxOrderCheck(params.notify_id);
-      if (!orderCheckResult.success) {
-        logger.error(`订单${orderId}校验失败: ${orderCheckResult.message}`);
-        ctx.body = "FAIL";
-        return;
-      }
-
-      // 获取服务器URL
-      const url = await getServerList(orderInfo.server_id, orderInfo.channel_id);
-      if (!url) {
-        logger.error(`区服id错误: serverId ${orderInfo.server_id}`);
-        ctx.body = "FAIL";
-        return;
-      }
-
-      // 发货处理
-      logger.info(`小程序支付订单${orderId}通知游戏发货开始`);
-      const result = await this.deliverOrder(
-        orderInfo,
-        ctx.request.ip,
-        url,
-        params.trans_id
-      );
-
-      if ((result as any).code === 1) {
-        logger.info(`小程序支付订单${orderId}发货成功`);
-        ctx.body = "SUCCESS";
-      } else {
-        logger.error(`小程序支付订单${orderId}发货失败: ${(result as any).msg}`);
-        ctx.body = "FAIL";
-      }
-
-    } catch (error) {
-      logger.error("小程序支付处理出错:", error);
-      ctx.body = "FAIL";
-    }
-  }
-  /**
-   * 订单校验 - 验证支付是否成功
-   * @param notifyId 平台通知ID
-   * @returns 校验结果
-   */
-  async wxOrderCheck(notifyId: string): Promise<{ success: boolean; message: string }> {
-    try {
-      // 构建验证参数
-      const parameters = [
-        `gameid=${this.miniAppGameId}`,
-        `notify_id=${notifyId}`
-      ];
-
-      // 生成签名
-      const signature = this.generateSignature(parameters, this.miniAppPrivateKey);
-      
-      // 构建验证URL
-      const verifyUrl = `https://login.${this.miniAppDomain}/pay/paygate/verify.php?gameid=${this.miniAppGameId}&notify_id=${notifyId}&sign=${signature}`;
-      
-      logger.info("订单校验请求", { notifyId, verifyUrl });
-
-      // 调用平台验证接口
-      const response = await axios.get(verifyUrl, {
-        httpsAgent: this.getHttpsAgent(),
-        headers: {
-          ...this.getCommonHeaders(),
-          'Accept': 'text/plain'
-        }
-      });
-      
-      logger.info("订单校验响应", { notifyId, response: response.data });
-
-      // 检查返回结果
-      if (response.data === "SUCCESS") {
-        return {
-          success: true,
-          message: "订单支付成功"
-        };
-      } else {
-        return {
-          success: false,
-          message: "订单支付失败或无效"
-        };
-      }
-
-    } catch (error) {
-      logger.error("订单校验出错:", { notifyId, error: error.message });
-      return {
-        success: false,
-        message: "订单校验失败"
-      };
-    }
-  }
-
-  /**
-   * 内容安全审核接口
-   * @param ctx Koa上下文
-   */
-  async contentSecurityCheck(ctx: any) {
-    try {
-      const data = ctx.request.body;
-      logger.info("内容安全审核请求参数:", data);
-
-      // 验证必要参数
-      const requiredParams = ['uid', 'gameid', 'signature', 'timestamp', 'nonce', 'scene', 'content'];
-      for (const param of requiredParams) {
-        if (!data[param]) {
-          logger.error(`缺少必要参数: ${param}`);
-          ctx.body = {
-            code: -1,
-            msg: `缺少必要参数: ${param}`,
-            data: null
-          };
-          return;
-        }
-      }
-
-      // 验证签名算法1
-      const isValidSignature = this.verifySignatureAlgorithm1(data);
-      if (!isValidSignature) {
-        logger.error("内容安全审核签名验证失败");
-        ctx.body = {
-          code: -1,
-          msg: "签名验证失败",
-          data: null
-        };
-        return;
-      }
-
-      // 构建请求参数
-      const requestData = {
-        uid: data.uid,
-        gameid: data.gameid,
-        signature: data.signature,
-        timestamp: data.timestamp,
-        nonce: data.nonce,
-        scene: data.scene,
-        content: data.content,
-        nickname: data.nickname || '',
-        title: data.title || '',
-        usersign: data.usersign || ''
-      };
-
-      // 调用内容安全API
-      const apiUrl = `https://api.${this.miniAppDomain}/mpcommon/?cmd=wxaMsgSecCheck`;
-      logger.info("调用内容安全API:", { url: apiUrl, data: requestData });
-
-      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) {
-        const result = response.data.result;
-        ctx.body = {
-          code: 0,
-          msg: "success",
-          data: {
-            suggest: result.suggest, // pass/review/reject
-            label: result.label,
-            trace_id: response.data.trace_id,
-            detail: response.data.detail
-          }
-        };
-      } else {
-        ctx.body = {
-          code: -1,
-          msg: response.data?.errmsg || "内容安全检测失败",
-          data: null
-        };
-      }
+      // 调用渠道处理器的内容安全审核方法
+      const result = await (handler as any).contentSecurityCheck(ctx, config);
+      ctx.body = result;
 
     } catch (error) {
       logger.error("内容安全审核出错:", error);
@@ -340,75 +82,22 @@ class MiniAppController {
    * 角色名称修改上报
    * @param ctx Koa上下文
    */
-  async editUserRoleInfo(ctx: any) {
+  async editUserRoleInfo(ctx: Context) {
     try {
-      const data = ctx.request.body;
-      logger.info("角色名称修改上报请求参数:", data);
-
-      // 验证必要参数
-      const requiredParams = ['openId', 'time', 'gameid', 'serverid', 'playerName', 'sign'];
-      for (const param of requiredParams) {
-        if (!data[param]) {
-          logger.error(`缺少必要参数: ${param}`);
-          ctx.body = {
-            error: -1,
-            errmsg: `缺少必要参数: ${param}`
-          };
-          return;
-        }
-      }
-
-      // 验证签名算法2
-      const isValidSignature = this.verifySignatureAlgorithm2(data);
-      if (!isValidSignature) {
-        logger.error("角色名称修改上报签名验证失败");
+      const handler = MiniappController.getChannelHandler();
+      const config = MiniappController.getChannelConfig();
+      
+      if (!handler) {
         ctx.body = {
           error: -1,
-          errmsg: "签名验证失败"
+          errmsg: "渠道处理器未找到"
         };
         return;
       }
 
-      // 构建请求参数
-      const requestData = {
-        openId: data.openId,
-        time: data.time,
-        gameid: data.gameid,
-        serverid: data.serverid,
-        playerName: encodeURIComponent(data.playerName), // 中文URL编码
-        sign: data.sign
-      };
-
-      // 调用角色信息修改API
-      const apiUrl = `https://platform.${this.miniAppDomain}.com/stat/api/?cmd=editUserRoleInfo`;
-      logger.info("调用角色信息修改API:", { url: apiUrl, data: requestData });
-
-      const response = await axios.get(apiUrl, { 
-        params: requestData,
-        timeout: 10000,
-        headers: {
-          'User-Agent': 'Mozilla/5.0 (compatible; WebServer/1.0)',
-          'Accept': 'application/json'
-        },
-        httpsAgent: new (require('https').Agent)({
-          rejectUnauthorized: false,
-          secureProtocol: 'TLSv1_2_method'
-        })
-      });
-      logger.info("角色信息修改API响应:", response.data);
-
-      // 处理响应结果
-      if (response.data && response.data.error === 0) {
-        ctx.body = {
-          error: 0,
-          errmsg: ""
-        };
-      } else {
-        ctx.body = {
-          error: response.data?.error || -1,
-          errmsg: response.data?.errmsg || "角色信息修改失败"
-        };
-      }
+      // 调用渠道处理器的角色名称修改上报方法
+      const result = await (handler as any).editUserRoleInfo(ctx, config);
+      ctx.body = result;
 
     } catch (error) {
       logger.error("角色名称修改上报出错:", error);
@@ -418,278 +107,6 @@ class MiniAppController {
       };
     }
   }
-
-  /**
-   * 签名算法2验证
-   * @param data 请求数据
-   * @returns 验证结果
-   */
-  private verifySignatureAlgorithm2(data: any): boolean {
-    try {
-      const { openId, time, gameid, serverid, playerName, sign } = data;
-      
-      // 构建待签名字符串 - 按字母顺序排序
-      const params: any = {
-        openId: openId.toString(),
-        time: time.toString(),
-        gameid: gameid.toString(),
-        serverid: serverid.toString(),
-        playerName: playerName.toString()
-      };
-
-      // 按字母顺序排序并拼接
-      const sortedKeys = Object.keys(params).sort();
-      const queryString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
-      
-      // 添加统计API密钥
-      const stringToSign = `${queryString}&key=${this.miniAppStatApiKey}`;
-      
-      // 计算MD5签名
-      const expectedSignature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
-      
-      logger.info("签名算法2验证详情:", {
-        queryString,
-        stringToSign,
-        expectedSignature,
-        receivedSignature: sign
-      });
-
-      return sign === expectedSignature;
-    } catch (error) {
-      logger.error("签名算法2验证出错:", error);
-      return false;
-    }
-  }
-
-  /**
-   * 生成角色信息修改签名(供客户端使用)
-   * @param params 签名参数
-   * @returns 签名结果
-   */
-  generateRoleInfoSignature(params: any): string | null {
-    try {
-      const { openId, time, gameid, serverid, playerName } = params;
-      
-      // 构建待签名字符串 - 按字母顺序排序
-      const signParams: any = {
-        openId: openId.toString(),
-        time: time.toString(),
-        gameid: gameid.toString(),
-        serverid: serverid.toString(),
-        playerName: playerName.toString()
-      };
-
-      // 按字母顺序排序并拼接
-      const sortedKeys = Object.keys(signParams).sort();
-      const queryString = sortedKeys.map(key => `${key}=${signParams[key]}`).join('&');
-      
-      // 添加统计API密钥
-      const stringToSign = `${queryString}&key=${this.miniAppStatApiKey}`;
-      
-      // 计算MD5签名
-      const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
-      
-      return signature;
-    } catch (error) {
-      logger.error("生成角色信息修改签名出错:", error);
-      return null;
-    }
-  }
-
-  /**
-   * 签名算法1验证
-   * @param data 请求数据
-   * @returns 验证结果
-   */
-  private verifySignatureAlgorithm1(data: any): boolean {
-    try {
-      const { uid, gameid, timestamp, nonce, scene, content, nickname, title, usersign, signature } = data;
-      
-      // 构建待签名字符串 - 按字母顺序排序
-      const params: any = {
-        uid: uid.toString(),
-        gameid: gameid.toString(),
-        timestamp: timestamp.toString(),
-        nonce: nonce.toString(),
-        scene: scene.toString(),
-        content: content
-      };
-
-      // 添加可选参数(如果存在)
-      if (nickname) params.nickname = nickname;
-      if (title) params.title = title;
-      if (usersign) params.usersign = usersign;
-
-      // 按字母顺序排序并拼接
-      const sortedKeys = Object.keys(params).sort();
-      const queryString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
-      
-      // 添加API密钥
-      const stringToSign = `${queryString}&key=${this.miniAppApiKey}`;
-      
-      // 计算MD5签名
-      const expectedSignature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
-      
-      logger.info("签名验证详情:", {
-        queryString,
-        stringToSign,
-        expectedSignature,
-        receivedSignature: signature
-      });
-
-      return signature === expectedSignature;
-    } catch (error) {
-      logger.error("签名算法1验证出错:", error);
-      return false;
-    }
-  }
-
-  /**
-   * 生成内容安全签名(供客户端使用)
-   * @param params 签名参数
-   * @returns 签名结果
-   */
-  generateContentSecuritySignature(params: any): string | null {
-    try {
-      const { uid, gameid, timestamp, nonce, scene, content, nickname, title, usersign } = params;
-      
-      // 构建待签名字符串 - 按字母顺序排序
-      const signParams: any = {
-        uid: uid.toString(),
-        gameid: gameid.toString(),
-        timestamp: timestamp.toString(),
-        nonce: nonce.toString(),
-        scene: scene.toString(),
-        content: content
-      };
-
-      // 添加可选参数(如果存在)
-      if (nickname) signParams.nickname = nickname;
-      if (title) signParams.title = title;
-      if (usersign) signParams.usersign = usersign;
-
-      // 按字母顺序排序并拼接
-      const sortedKeys = Object.keys(signParams).sort();
-      const queryString = sortedKeys.map(key => `${key}=${signParams[key]}`).join('&');
-      
-      // 添加API密钥
-      const stringToSign = `${queryString}&key=${this.miniAppApiKey}`;
-      
-      // 计算MD5签名
-      const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
-      
-      return signature;
-    } catch (error) {
-      logger.error("生成内容安全签名出错:", error);
-      return null;
-    }
-  }
-
-  /**
-   * 发货处理方法
-   * @param orderInfo 订单信息
-   * @param ip 客户端IP
-   * @param url 游戏服务器URL
-   * @param out_trade_no 外部交易号
-   * @returns 发货结果
-   */
-  private async deliverOrder(orderInfo: any, ip: string, url: string, out_trade_no: string): Promise<{ code: number; msg: string }> {
-    return new Promise((resolve) => {
-      const sendMsg = new Msg();
-      logger.info("通知游戏服务器url", { url: url });
-
-      sendMsg.connect(url, Account);
-      setTimeout(async () => {
-        try {
-          // 构建消息参数
-          const params = JSON.stringify({
-            account: orderInfo.uid,
-            channel_id: orderInfo.channel_id,
-            order: orderInfo.order_id,
-            id: orderInfo.product_id,
-            cnt: 100,
-            money: orderInfo.amount,
-          });
-
-          logger.info("通知游戏服务器参数", { data: params });
-          logger.info("通知游戏服务器orderInfo", { orderInfo: orderInfo });
-          let send_res = sendMsg.CG_ASK_LOGIN(
-            Account,
-            0,
-            "",
-            "cn",
-            "CN",
-            ip,
-            params,
-            orderInfo.server_id
-          );
-
-          if (!send_res) {
-            resolve({ code: 0, msg: "通知服务器失败" });
-            return;
-          }
-
-          // 更新订单状态
-          const update_time = formatDate(new Date());
-          const res = await Order.updateOrderStats(
-            orderInfo.order_id,
-            2,
-            out_trade_no,
-            update_time,
-            orderInfo.uid
-          );
-
-          if (res.affectedRows <= 0) {
-            logger.info(`订单${orderInfo.order_id} 发货失败`);
-            resolve({ code: 0, msg: "发货失败" });
-            return;
-          }
-
-          resolve({ code: 1, msg: "发货成功" });
-        } catch (error) {
-          logger.error("发货过程出错:", error);
-          resolve({ code: 0, msg: "发货失败" });
-        }
-      }, 1500);
-    });
-  }
-
-  /**
-   * 小程序签名函数(签名算法3)
-   * @param parameters 参数数组
-   * @param privateKey 私钥
-   * @returns 签名结果
-   */
-  private generateSignature(parameters: string[], privateKey: string): string {
-    // 1. 过滤掉空值和sign参数
-    const filteredParams = parameters.filter(param => {
-      const [key, value] = param.split('=');
-      return key !== 'sign' && value && value.trim() !== '';
-    });
-
-    // 2. 对参数进行URL编码
-    const encodedParams = filteredParams.map(param => {
-      const [key, value] = param.split('=');
-      const encodedValue = encodeURIComponent(value);
-      return `${key}=${encodedValue}`;
-    });
-
-    // 3. 按字母顺序排序
-    encodedParams.sort((a, b) => {
-      return a.localeCompare(b);
-    });
-
-    // 4. 用&连接所有参数
-    const queryString = encodedParams.join('&');
-
-    // 5. 拼接私钥
-    const stringToSign = `${queryString}&key=${privateKey}`;
-
-    // 6. 计算MD5并转大写
-    const signature = CryptoJS.MD5(stringToSign).toString().toUpperCase();
-
-    return signature;
-  }
 }
 
-module.exports = new MiniAppController();
+module.exports = new MiniappController();

+ 3 - 17
webServer/src/router/index.ts

@@ -1,14 +1,16 @@
 import Router from "@koa/router";
 import adminRouter from "./admin";
+import miniApprouter from "./miniapp";
 const router = new Router();
 
 // 使用管理员路由
 router.use(adminRouter.routes(), adminRouter.allowedMethods());
+//小程序路由
+router.use("/miniapp", miniApprouter.routes(), miniApprouter.allowedMethods());
 
 //用户
 const ApiController = require("../controller/ApiController");
 const TencentController = require("../controller/TencentController");
-const MiniAppController = require("../controller/MiniAppController");
 //支付回调
 router.post("/callback", ApiController.callPay);
 router.get("/callback", ApiController.callPay);
@@ -87,21 +89,5 @@ router.get("/qqGift", TencentController.qqGift);
 
 router.post("/qqReport", TencentController.qqReport);
 
-// 小程序相关路由
-// 小程序登录鉴权
-router.post("/wxLogin", MiniAppController.wxLogin.bind(MiniAppController));
-
-// 小程序支付回调
-router.get("/wxPay", MiniAppController.wxPay.bind(MiniAppController));
-
-// 内容安全审核
-router.post("/contentSecurityCheck", MiniAppController.contentSecurityCheck.bind(MiniAppController));
-
-// 角色名称修改上报
-router.post("/editUserRoleInfo", MiniAppController.editUserRoleInfo.bind(MiniAppController));
-
-//验证支付是否成功
-router.post("/wxOrderCheck", MiniAppController.wxOrderCheck.bind(MiniAppController));
-
 
 module.exports = router;

+ 12 - 0
webServer/src/router/miniapp.ts

@@ -0,0 +1,12 @@
+import Router from "@koa/router";
+const MiniappController = require("../controller/MiniappController");
+
+const miniApprouter = new Router();
+
+// 内容安全审核
+miniApprouter.post("/contentSecurityCheck", MiniappController.contentSecurityCheck);
+
+// 角色名称修改上报
+miniApprouter.post("/editUserRoleInfo", MiniappController.editUserRoleInfo);
+
+export default miniApprouter;