flowerpig hai 7 meses
pai
achega
b053c03c8a

+ 133 - 0
webServer/iosApi.md

@@ -0,0 +1,133 @@
+# iOS SDK API 文档
+
+## 接口说明
+
+根据第三方 API 文档实现 iOS 平台的鉴权功能。
+
+---
+
+## 1. 用户鉴权接口
+
+### 接口地址
+- **GET/POST** `/ios/checkUserToken`
+
+### 请求参数
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| userToken | string | 是 | 鉴权凭证,从 URL 上获取 |
+| gameid | number | 是 | 游戏的ID,商户后台游戏添加完成后可获取 |
+
+### 请求示例
+```bash
+# GET 请求
+GET /ios/checkUserToken?userToken=your_token_here&gameid=1540
+
+# POST 请求
+POST /ios/checkUserToken
+Content-Type: application/json
+
+{
+  "userToken": "your_token_here",
+  "gameid": 1540
+}
+```
+
+### 响应参数
+```json
+{
+  "uid": "",           // 用户UID
+  "nickname": "",      // 用户昵称
+  "headimgurl": "",    // 用户头像地址
+  "sex": "",           // 用户性别 0未知 1男 2女
+  "focus": "",         // 是否关注公众号 0否 1是
+  "usertype": "",      // 用户类型 1为微信用户 -1为非微信用户
+  "error": 0           // 错误码,0表示成功
+}
+```
+
+### 错误响应
+
+#### 参数错误 (401)
+```json
+{
+  "error": 401,
+  "msg": "参数有误,请检查接口所需参数是否都已经填写正确",
+  "uid": "",
+  "nickname": "",
+  "headimgurl": "",
+  "sex": "",
+  "focus": "",
+  "usertype": ""
+}
+```
+
+#### Token验证失败 (403)
+```json
+{
+  "error": 403,
+  "msg": "token验证失败,同一个userToken只能验证一次,可通过刷新游戏重新获取",
+  "uid": "",
+  "nickname": "",
+  "headimgurl": "",
+  "sex": "",
+  "focus": "",
+  "usertype": ""
+}
+```
+
+#### 系统错误 (-1)
+```json
+{
+  "error": -1,
+  "msg": "鉴权失败,请稍后重试",
+  "uid": "",
+  "nickname": "",
+  "headimgurl": "",
+  "sex": "",
+  "focus": "",
+  "usertype": ""
+}
+```
+
+---
+
+## 2. 获取用户信息接口(备用)
+
+### 接口地址
+- **GET/POST** `/ios/getUserInfo`
+
+### 请求参数
+同鉴权接口
+
+### 响应参数
+同鉴权接口
+
+---
+
+## 错误码说明
+
+| 错误码 | 类型 | 说明 |
+|--------|------|------|
+| 0 | Number | 成功 |
+| 401 | Number | 参数有误,请检查接口所需参数是否都已经填写正确 |
+| 403 | Number | token验证失败,同一个userToken只能验证一次,可通过刷新游戏重新获取 |
+| -1 | Number | 系统错误,鉴权失败,请稍后重试 |
+
+## 重要说明
+
+⚠️ **同一个token只能验证一次,不能多次重复请求**
+
+## 第三方API
+
+- **请求方式**: GET
+- **URL**: `https://api.11h5.com/login?cmd=checkUserToken`
+- **参数**: userToken, gameid
+
+## 实现特点
+
+1. **支持 GET 和 POST 请求**
+2. **参数验证**:检查必要参数
+3. **错误处理**:统一的错误响应格式
+4. **日志记录**:详细的请求和响应日志
+5. **超时设置**:10秒请求超时
+6. **直接透传**:直接返回第三方API的响应数据

+ 3 - 1
webServer/src/channels/factory/ChannelFactory.ts

@@ -9,6 +9,7 @@ import { MuZiChannelHandler } from "../handlers/MuZiChannelHandler";
 import { QiAiH5ChannelHandler } from "../handlers/QiAiH5ChannelHandler";
 import { MuZiIosChannelHandler } from "../handlers/MuZiIosChannelHandler";
 import { MiniappChannelHandler } from "../handlers/MiniappChannelHandler";
+import { SYIOSChannelHandler } from "../handlers/SYIOSChannelHandler";
 
 
 const logger = require("../../utils/log");
@@ -40,7 +41,8 @@ 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
+    this.registerHandler(11, new MiniappChannelHandler()); // miniapp
+    this.registerHandler(12, new SYIOSChannelHandler()); // sy ios
   }
 
   /**

+ 123 - 2
webServer/src/channels/handlers/MiniappChannelHandler.ts

@@ -38,13 +38,41 @@ export class MiniappChannelHandler implements ChannelHandler {
     }
 
     /**
-     * 小程序登录鉴权
+     * 统一登录鉴权(支持小程序和iOS)
      * @param ctx Koa上下文
      * @param config 渠道配置
      */
     async handleLogin(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
         try {
             const data = ctx.request.body as any;
+            const platform = data.platform; // 平台参数:ios、Android、miniapp、h5
+
+            logger.info("统一登录请求", { platform, data });
+
+            // 根据平台选择不同的登录方式
+            if (platform === 'ios') {
+                return await this.handleIOSLogin(data, config);
+            } else {
+                // 默认使用小程序登录方式
+                return await this.handleMiniappLogin(data, config);
+            }
+        } catch (error) {
+            logger.error('统一登录错误:', error);
+            return {
+                code: -1,
+                msg: error.message || "登录验证失败",
+                data: null,
+            };
+        }
+    }
+
+    /**
+     * 小程序登录鉴权
+     * @param data 请求数据
+     * @param config 渠道配置
+     */
+    private async handleMiniappLogin(data: any, config: ChannelConfig): Promise<LoginResult> {
+        try {
             const token = data.token;
 
             if (!token) {
@@ -76,7 +104,7 @@ export class MiniappChannelHandler implements ChannelHandler {
                 data: wxLogin.data,
             };
         } catch (error) {
-            logger.error('wxLogin error:', error);
+            logger.error('小程序登录错误:', error);
             return {
                 code: -1,
                 msg: error.message || "登录验证失败",
@@ -85,6 +113,99 @@ export class MiniappChannelHandler implements ChannelHandler {
         }
     }
 
+    /**
+     * iOS登录鉴权
+     * @param data 请求数据
+     * @param config 渠道配置
+     */
+    private async handleIOSLogin(data: any, config: ChannelConfig): Promise<LoginResult> {
+        try {
+            const { token } = data;
+            const gameid = config.paymentConfig.gameId;
+            // 验证必要参数
+            if (!token) {
+                logger.error("iOS登录鉴权失败 - 缺少token参数");
+                return {
+                    code: -1,
+                    msg: "缺少必要参数: token",
+                    data: null
+                };
+            }
+
+            logger.info("iOS登录鉴权请求参数:", { token });
+
+            // 调用第三方鉴权API
+            const apiUrl = `https://api.11h5.com/login?cmd=checkUserToken&userToken=${encodeURIComponent(token)}&gameid=${gameid}`;
+            
+            logger.info("调用iOS鉴权API:", { url: apiUrl });
+
+            const response = await axios.get(apiUrl, {
+                timeout: 10000,
+                headers: this.getCommonHeaders(),
+                httpsAgent: this.getHttpsAgent()
+            });
+
+            logger.info("iOS鉴权API响应:", response.data);
+
+            // 根据错误码判断成功与否
+            const responseData = response.data;
+            
+            if (responseData.error === 0) {
+                // 成功:error = 0
+                logger.info("iOS登录鉴权成功:", {
+                    uid: responseData.uid,
+                    nickname: responseData.nickname,
+                    usertype: responseData.usertype
+                });
+                
+                return {
+                    code: 0,
+                    msg: "登录成功",
+                    data: {
+                        uid: responseData.uid,
+                        nickname: responseData.nickname,
+                        headimgurl: responseData.headimgurl,
+                        sex: responseData.sex,
+                        focus: responseData.focus,
+                        usertype: responseData.usertype
+                    }
+                };
+            } else if (responseData.error === 401) {
+                // 参数有误
+                logger.error("iOS登录鉴权失败 - 参数有误:", responseData);
+                return {
+                    code: -1,
+                    msg: "参数有误,请检查接口所需参数是否都已经填写正确",
+                    data: null
+                };
+            } else if (responseData.error === 403) {
+                // token验证失败
+                logger.error("iOS登录鉴权失败 - token验证失败:", responseData);
+                return {
+                    code: -1,
+                    msg: "token验证失败,同一个userToken只能验证一次,可通过刷新游戏重新获取",
+                    data: null
+                };
+            } else {
+                // 其他错误
+                logger.error("iOS登录鉴权失败 - 未知错误:", responseData);
+                return {
+                    code: -1,
+                    msg: "鉴权失败,请稍后重试",
+                    data: null
+                };
+            }
+
+        } catch (error) {
+            logger.error("iOS登录鉴权出错:", error);
+            return {
+                code: -1,
+                msg: "登录鉴权失败",
+                data: null
+            };
+        }
+    }
+
     /**
      * 小程序支付回调处理
      * @param ctx Koa上下文

+ 498 - 0
webServer/src/channels/handlers/SYIOSChannelHandler.ts

@@ -0,0 +1,498 @@
+import { Context } from "koa";
+import { ChannelHandler, LoginResult, PaymentResult } from "../interfaces/ChannelHandler";
+import { ChannelConfig } from "../../config/channelConfig";
+import axios from "axios";
+
+const logger = require("../../utils/log");
+
+/**
+ * 三一iOS渠道处理器
+ * 渠道ID: 12
+ * 处理iOS平台的登录鉴权和支付回调
+ */
+export class SYIOSChannelHandler 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'
+        };
+    }
+
+    /**
+     * iOS登录鉴权
+     * @param ctx Koa上下文
+     * @param config 渠道配置
+     */
+    async handleLogin(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
+        try {
+            const { userToken, gameid } = ctx.request.body || ctx.request.query;
+            
+            // 验证必要参数
+            if (!userToken) {
+                logger.error("iOS登录鉴权失败 - 缺少userToken参数");
+                return {
+                    code: -1,
+                    msg: "缺少必要参数: userToken",
+                    data: null
+                };
+            }
+
+            if (!gameid) {
+                logger.error("iOS登录鉴权失败 - 缺少gameid参数");
+                return {
+                    code: -1,
+                    msg: "缺少必要参数: gameid",
+                    data: null
+                };
+            }
+
+            logger.info("iOS登录鉴权请求参数:", { userToken, gameid });
+
+            // 调用第三方鉴权API
+            const apiUrl = `https://api.11h5.com/login?cmd=checkUserToken&userToken=${encodeURIComponent(userToken)}&gameid=${gameid}`;
+            
+            logger.info("调用iOS鉴权API:", { url: apiUrl });
+
+            const response = await axios.get(apiUrl, {
+                timeout: 10000,
+                headers: this.getCommonHeaders(),
+                httpsAgent: this.getHttpsAgent()
+            });
+
+            logger.info("iOS鉴权API响应:", response.data);
+
+            // 根据错误码判断成功与否
+            const responseData = response.data;
+            
+            if (responseData.error === 0) {
+                // 成功:error = 0
+                logger.info("iOS登录鉴权成功:", {
+                    uid: responseData.uid,
+                    nickname: responseData.nickname,
+                    usertype: responseData.usertype
+                });
+                
+                return {
+                    code: 1,
+                    msg: "登录成功",
+                    data: {
+                        uid: responseData.uid,
+                        nickname: responseData.nickname,
+                        headimgurl: responseData.headimgurl,
+                        sex: responseData.sex,
+                        focus: responseData.focus,
+                        usertype: responseData.usertype
+                    }
+                };
+            } else if (responseData.error === 401) {
+                // 参数有误
+                logger.error("iOS登录鉴权失败 - 参数有误:", responseData);
+                return {
+                    code: -1,
+                    msg: "参数有误,请检查接口所需参数是否都已经填写正确",
+                    data: null
+                };
+            } else if (responseData.error === 403) {
+                // token验证失败
+                logger.error("iOS登录鉴权失败 - token验证失败:", responseData);
+                return {
+                    code: -1,
+                    msg: "token验证失败,同一个userToken只能验证一次,可通过刷新游戏重新获取",
+                    data: null
+                };
+            } else {
+                // 其他错误
+                logger.error("iOS登录鉴权失败 - 未知错误:", responseData);
+                return {
+                    code: -1,
+                    msg: "鉴权失败,请稍后重试",
+                    data: null
+                };
+            }
+
+        } catch (error) {
+            logger.error("iOS登录鉴权出错:", error);
+            return {
+                code: -1,
+                msg: "登录鉴权失败",
+                data: null
+            };
+        }
+    }
+
+    /**
+     * iOS支付回调处理
+     * @param ctx Koa上下文
+     * @param config 渠道配置
+     */
+    async handlePayment(ctx: Context, config: ChannelConfig): Promise<PaymentResult> {
+        try {
+            const data = ctx.request.query || ctx.request.body;
+            logger.info("iOS支付回调参数:", data);
+
+            // 验证必要参数(根据API文档)
+            const requiredParams = ['openid', 'rmb', 'reqid', 'trans_id', 'product_id', 'notify_id', 'sign'];
+            for (const param of requiredParams) {
+                if (!data[param]) {
+                    logger.error(`iOS支付回调缺少必要参数: ${param}`);
+                    return {
+                        code: 0,
+                        msg: `缺少必要参数: ${param}`
+                    };
+                }
+            }
+
+            // 验证签名(使用签名算法3)
+            if (!this.verifyPaymentSignature(data, config)) {
+                logger.error("iOS支付回调签名验证失败");
+                return {
+                    code: 0,
+                    msg: "签名验证失败"
+                };
+            }
+
+            // 提取notify_id进行订单校验
+            const notify_id = data.notify_id;
+            const gameid = data.product_id || config.paymentConfig?.gameId || '1540';
+            
+            logger.info(`开始订单校验 - notify_id: ${notify_id}, gameid: ${gameid}`);
+
+            // 调用订单校验
+            const verifyResult = await this.verifyOrderInternal(gameid, notify_id, config);
+            
+            if (!verifyResult.success) {
+                logger.error("订单校验失败:", verifyResult.message);
+                return {
+                    code: 0,
+                    msg: `订单校验失败: ${verifyResult.message}`
+                };
+            }
+
+            logger.info("订单校验成功,开始处理支付发货逻辑");
+
+            // 处理支付成功逻辑
+            logger.info(`iOS支付成功 - 用户: ${data.openid}, 金额: ${data.rmb}, 订单: ${data.reqid}`);
+            
+            // 返回SUCCESS表示处理成功(根据API文档要求)
+            ctx.body = "SUCCESS";
+            
+            return {
+                code: 1,
+                msg: "支付处理成功",
+                data: {
+                    openid: data.openid,
+                    rmb: data.rmb,
+                    reqid: data.reqid,
+                    trans_id: data.trans_id,
+                    product_id: data.product_id,
+                    notify_id: data.notify_id,
+                    userdata: data.userdata,
+                    txid: data.txid,
+                    product_count: data.product_count
+                }
+            };
+
+        } catch (error) {
+            logger.error("iOS支付回调处理出错:", error);
+            return {
+                code: 0,
+                msg: "支付处理失败"
+            };
+        }
+    }
+
+    /**
+     * 验证支付签名(签名算法3)
+     * @param data 支付数据
+     * @param config 渠道配置
+     * @returns 验证结果
+     */
+    private verifyPaymentSignature(data: any, config: ChannelConfig): boolean {
+        try {
+            const privateKey = config.paymentConfig?.signKey || '';
+            if (!privateKey) {
+                logger.error("iOS支付签名验证失败 - 缺少私钥");
+                return false;
+            }
+
+            // 1. 除去为空的参数
+            const filteredParams: any = {};
+            Object.keys(data).forEach(key => {
+                if (key !== 'sign' && data[key] !== null && data[key] !== undefined && data[key] !== '') {
+                    filteredParams[key] = data[key].toString();
+                }
+            });
+
+            // 2. 对参数名按字母顺序排序
+            const sortedKeys = Object.keys(filteredParams).sort();
+
+            // 3. 构建待签名字符串
+            const queryString = sortedKeys.map(key => {
+                return `${key}=${filteredParams[key]}`;
+            }).join('&');
+
+            // 4. 拼接私钥
+            const stringToSign = `${queryString}&key=${privateKey}`;
+
+            // 5. 计算MD5签名并转大写
+            const crypto = require('crypto');
+            const expectedSignature = crypto.createHash('md5').update(stringToSign).digest('hex').toUpperCase();
+            const actualSignature = data.sign;
+
+            logger.info("iOS支付签名验证详情:", {
+                filteredParams,
+                queryString,
+                stringToSign,
+                expectedSignature,
+                actualSignature,
+                isValid: expectedSignature === actualSignature
+            });
+
+            return expectedSignature === actualSignature;
+        } catch (error) {
+            logger.error("iOS支付签名验证出错:", error);
+            return false;
+        }
+    }
+
+    /**
+     * 生成支付签名(签名算法3)
+     * @param params 签名参数
+     * @param config 渠道配置
+     * @returns 签名字符串
+     */
+    private generatePaymentSignature(params: any, config: ChannelConfig): string {
+        try {
+            const privateKey = config.paymentConfig?.signKey || '';
+            if (!privateKey) {
+                logger.error("iOS支付签名生成失败 - 缺少私钥");
+                return "";
+            }
+
+            // 1. 除去为空的参数
+            const filteredParams: any = {};
+            Object.keys(params).forEach(key => {
+                if (key !== 'sign' && params[key] !== null && params[key] !== undefined && params[key] !== '') {
+                    filteredParams[key] = params[key].toString();
+                }
+            });
+
+            // 2. 对参数名按字母顺序排序
+            const sortedKeys = Object.keys(filteredParams).sort();
+
+            // 3. 构建待签名字符串
+            const queryString = sortedKeys.map(key => {
+                return `${key}=${filteredParams[key]}`;
+            }).join('&');
+
+            // 4. 拼接私钥
+            const stringToSign = `${queryString}&key=${privateKey}`;
+
+            // 5. 计算MD5签名并转大写
+            const crypto = require('crypto');
+            const signature = crypto.createHash('md5').update(stringToSign).digest('hex').toUpperCase();
+
+            logger.info("iOS支付签名生成详情:", {
+                filteredParams,
+                queryString,
+                stringToSign,
+                signature
+            });
+
+            return signature;
+        } catch (error) {
+            logger.error("iOS支付签名生成出错:", error);
+            return "";
+        }
+    }
+
+    /**
+     * 内部订单校验方法(不依赖Koa上下文)
+     * @param gameid 游戏ID
+     * @param notify_id 平台通知ID
+     * @param config 渠道配置
+     */
+    private async verifyOrderInternal(gameid: string, notify_id: string, config: ChannelConfig): Promise<{ success: boolean; message: string }> {
+        try {
+            // 生成订单校验签名
+            const sign = this.generateOrderVerifySignature(gameid, notify_id, config);
+            
+            if (!sign) {
+                logger.error("订单校验签名生成失败");
+                return {
+                    success: false,
+                    message: "签名生成失败"
+                };
+            }
+
+            logger.info("订单校验请求参数:", { gameid, notify_id, sign });
+
+            // 调用第三方订单校验API
+            const apiUrl = `https://login.11h5.com/pay/paygate/verify.php?gameid=${gameid}&notify_id=${encodeURIComponent(notify_id)}&sign=${encodeURIComponent(sign)}`;
+            
+            logger.info("调用订单校验API:", { url: apiUrl });
+
+            const response = await axios.get(apiUrl, {
+                timeout: 10000,
+                headers: this.getCommonHeaders(),
+                httpsAgent: this.getHttpsAgent()
+            });
+
+            logger.info("订单校验API响应:", response.data);
+
+            // 检查响应结果
+            const responseText = response.data.toString().trim();
+            if (responseText === "SUCCESS") {
+                logger.info("订单校验成功:", { notify_id, gameid });
+                return {
+                    success: true,
+                    message: "订单校验成功"
+                };
+            } else {
+                logger.warn("订单校验失败:", { notify_id, gameid, response: responseText });
+                return {
+                    success: false,
+                    message: `订单校验失败: ${responseText}`
+                };
+            }
+
+        } catch (error) {
+            logger.error("订单校验出错:", error);
+            return {
+                success: false,
+                message: "订单校验失败"
+            };
+        }
+    }
+
+    /**
+     * 订单校验(公开接口)
+     * @param ctx Koa上下文
+     * @param config 渠道配置
+     */
+    async verifyOrder(ctx: Context, config: ChannelConfig): Promise<{ success: boolean; message: string }> {
+        try {
+            const { gameid, notify_id, sign } = ctx.request.query || ctx.request.body;
+            
+            // 验证必要参数
+            if (!gameid) {
+                logger.error("订单校验失败 - 缺少gameid参数");
+                return {
+                    success: false,
+                    message: "缺少必要参数: gameid"
+                };
+            }
+
+            if (!notify_id) {
+                logger.error("订单校验失败 - 缺少notify_id参数");
+                return {
+                    success: false,
+                    message: "缺少必要参数: notify_id"
+                };
+            }
+
+            if (!sign) {
+                logger.error("订单校验失败 - 缺少sign参数");
+                return {
+                    success: false,
+                    message: "缺少必要参数: sign"
+                };
+            }
+
+            logger.info("订单校验请求参数:", { gameid, notify_id, sign });
+
+            // 验证签名
+            const verifyData = { gameid, notify_id, sign };
+            if (!this.verifyPaymentSignature(verifyData, config)) {
+                logger.error("订单校验签名验证失败");
+                return {
+                    success: false,
+                    message: "签名验证失败"
+                };
+            }
+
+            // 调用第三方订单校验API
+            const apiUrl = `https://login.11h5.com/pay/paygate/verify.php?gameid=${gameid}&notify_id=${encodeURIComponent(notify_id)}&sign=${encodeURIComponent(sign)}`;
+            
+            logger.info("调用订单校验API:", { url: apiUrl });
+
+            const response = await axios.get(apiUrl, {
+                timeout: 10000,
+                headers: this.getCommonHeaders(),
+                httpsAgent: this.getHttpsAgent()
+            });
+
+            logger.info("订单校验API响应:", response.data);
+
+            // 检查响应结果
+            const responseText = response.data.toString().trim();
+            if (responseText === "SUCCESS") {
+                logger.info("订单校验成功:", { notify_id, gameid });
+                return {
+                    success: true,
+                    message: "订单校验成功"
+                };
+            } else {
+                logger.warn("订单校验失败:", { notify_id, gameid, response: responseText });
+                return {
+                    success: false,
+                    message: `订单校验失败: ${responseText}`
+                };
+            }
+
+        } catch (error) {
+            logger.error("订单校验出错:", error);
+            return {
+                success: false,
+                message: "订单校验失败"
+            };
+        }
+    }
+
+    /**
+     * 生成订单校验签名
+     * @param gameid 游戏ID
+     * @param notify_id 平台通知ID
+     * @param config 渠道配置
+     * @returns 签名字符串
+     */
+    private generateOrderVerifySignature(gameid: string, notify_id: string, config: ChannelConfig): string {
+        try {
+            const privateKey = config.paymentConfig?.signKey || '';
+            if (!privateKey) {
+                logger.error("订单校验签名生成失败 - 缺少私钥");
+                return "";
+            }
+
+            // 构建参数对象
+            const params = {
+                gameid: gameid,
+                notify_id: notify_id
+            };
+
+            // 使用签名算法3生成签名
+            return this.generatePaymentSignature(params, config);
+        } catch (error) {
+            logger.error("订单校验签名生成出错:", error);
+            return "";
+        }
+    }
+}

+ 214 - 200
webServer/src/config/channelConfig.ts

@@ -1,211 +1,225 @@
 import {
-  QUICK_MD5_KEY,
-  QUICK_CALLBACK_KEY,
-  QUICK_PRODUCT_CODE,
-  QUICK_H5_CALLBACK_KEY,
-  QUICK_H5_PRODUCT_CODE,
-  QUICK_H5_MD5_KEY,
-  QUICK_IOS_PRODUCT_CODE,
-  QUICK_IOS_CALLBACK_KEY,
-  QUICK_IOS_MD5_KEY,
-  AppSecret360,
-  AppKey360,
-  MuziIosLoginKey,
-  MuziIosPayKey,
-  CALLBACK_KEY_4399,
-  SECRET_KEY_4399,
-  CALLBACK_KEY_4399_V2,
-  SECRET_KEY_4399_V2,
-  APP_ID_4399,
-  APP_ID_4399_V2,
-  SECRET_KEY_QIHU,
-  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,
+    QUICK_MD5_KEY,
+    QUICK_CALLBACK_KEY,
+    QUICK_PRODUCT_CODE,
+    QUICK_H5_CALLBACK_KEY,
+    QUICK_H5_PRODUCT_CODE,
+    QUICK_H5_MD5_KEY,
+    QUICK_IOS_PRODUCT_CODE,
+    QUICK_IOS_CALLBACK_KEY,
+    QUICK_IOS_MD5_KEY,
+    AppSecret360,
+    AppKey360,
+    MuziIosLoginKey,
+    MuziIosPayKey,
+    CALLBACK_KEY_4399,
+    SECRET_KEY_4399,
+    CALLBACK_KEY_4399_V2,
+    SECRET_KEY_4399_V2,
+    APP_ID_4399,
+    APP_ID_4399_V2,
+    SECRET_KEY_QIHU,
+    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,
+    SY_IOS_PRIVATE_KEY, SY_IOS_GAME_ID
 } from "./thirdParams";
 
 // 渠道配置接口定义
 export interface ChannelConfig {
-  channelId: number; // 渠道ID
-  name: string; // 渠道名称
-  platform: string; // 平台标识
-  paymentConfig: {
-    // 支付相关配置
-    signKey?: string; // 签名密钥
-    callbackKey?: string; // 回调密钥
-    appSecret?: string; // 应用密钥
-    apiUrl?: string; // API地址
-    clientSecret?: string; // 客户端密钥
-    ClientId?: string; // 客户端id
-    gameId?: string; // 游戏ID
-  };
-  loginConfig?: {
-    // 登录相关配置
-    productCode?: string; // 产品代码
-    appId?: string; // 应用ID
-    signKey?: string; // 签名密钥
-    callKey?: string; // 签名密钥
-    apiKey?: string; // API密钥
-    statApiKey?: string; // 统计API密钥
-  };
+    channelId: number; // 渠道ID
+    name: string; // 渠道名称
+    platform: string; // 平台标识
+    paymentConfig: {
+        // 支付相关配置
+        signKey?: string; // 签名密钥
+        callbackKey?: string; // 回调密钥
+        appSecret?: string; // 应用密钥
+        apiUrl?: string; // API地址
+        clientSecret?: string; // 客户端密钥
+        ClientId?: string; // 客户端id
+        gameId?: string; // 游戏ID
+    };
+    loginConfig?: {
+        // 登录相关配置
+        productCode?: string; // 产品代码
+        appId?: string; // 应用ID
+        signKey?: string; // 签名密钥
+        callKey?: string; // 签名密钥
+        apiKey?: string; // API密钥
+        statApiKey?: string; // 统计API密钥
+    };
 }
 
 // 渠道配置对象
 export const channelConfigs: Record<number, ChannelConfig> = {
-  1: {
-    // 木子
-    channelId: 1,
-    name: "木子",
-    platform: "木子",
-    paymentConfig: {
-      signKey: AppSecret360,
-    },
-    loginConfig: {
-      signKey: AppKey360,
-    },
-  },
-  2: {
-    // 三狸安卓
-    channelId: 2,
-    name: "三狸安卓",
-    platform: "quick",
-    paymentConfig: {
-      signKey: QUICK_MD5_KEY,
-      callbackKey: QUICK_CALLBACK_KEY,
-    },
-    loginConfig: {
-      productCode: QUICK_PRODUCT_CODE,
-    },
-  },
-  3: {
-    // 三狸iOS
-    channelId: 3,
-    name: "三狸iOS",
-    platform: "quickIos",
-    paymentConfig: {
-      signKey: QUICK_IOS_MD5_KEY,
-      callbackKey: QUICK_IOS_CALLBACK_KEY,
-    },
-    loginConfig: {
-      productCode: QUICK_IOS_PRODUCT_CODE,
-    },
-  },
-  4: {
-    // QQ大厅
-    channelId: 4,
-    name: "QQ大厅",
-    platform: "qqgame",
-    paymentConfig: {},
-  },
-  5: {
-    // 三狸H5
-    channelId: 5,
-    name: "三狸H5",
-    platform: "quickH5",
-    paymentConfig: {
-      signKey: QUICK_H5_MD5_KEY,
-      callbackKey: QUICK_H5_CALLBACK_KEY,
-    },
-    loginConfig: {
-      productCode: QUICK_H5_PRODUCT_CODE,
-    },
-  },
-  6: {
-    // 4399
-    channelId: 6,
-    name: "4399",
-    platform: "4399h5",
-    paymentConfig: {
-      signKey: CALLBACK_KEY_4399,
-    },
-    loginConfig: {
-      signKey: SECRET_KEY_4399,
-      callKey:CALLBACK_KEY_4399,
-      appId: APP_ID_4399
-    },
-  },
-  7: {
-    // 360
-    channelId: 7,
-    name: "360",
-    platform: "360",
-    paymentConfig: {
-      signKey: SECRET_KEY_QIHU,
-    },
-    loginConfig: {
-        signKey: SECRET_KEY_QIHU,
-    },
-  },
-  999: {
-    // 4399
-    channelId: 6,
-    name: "4399new",
-    platform: "4399h5new",
-    paymentConfig: {
-      signKey: CALLBACK_KEY_4399_V2,
-    },
-    loginConfig: {
-      signKey: SECRET_KEY_4399_V2,
-      callKey:CALLBACK_KEY_4399_V2,
-      appId: APP_ID_4399_V2
-    },
-  },
-  8: {
-    // 七艾H5
-    channelId: 8,
-    name: "七艾",
-    platform: "qiaiH5",
-    paymentConfig: {
-      signKey: QIAI_QUICK_H5_MD5_KEY,
-      callbackKey: QIAI_QUICK_H5_CALLBACK_KEY,
-    },
-    loginConfig: {
-      productCode: QIAI_QUICK_H5_PRODUCT_CODE,
-    },
-  },
-  9: {
-    // 木子
-    channelId: 9,
-    name: "木子ios",
-    platform: "木子ios",
-    paymentConfig: {
-      signKey: MuziIosPayKey,
-    },
-    loginConfig: {
-      signKey: MuziIosLoginKey,
-    },
-  },
-  10: {
-    // 三狸安卓
-    channelId: 10,
-    name: "互视",
-    platform: "quick",
-    paymentConfig: {
-      signKey: QUICK_MD5_KEY,
-      callbackKey: QUICK_CALLBACK_KEY,
-    },
-    loginConfig: {
-      productCode: QUICK_PRODUCT_CODE,
-    },
-  },
-  11: {
-    // 小程序
-    channelId: 11,
-    name: "小程序",
-    platform: "miniapp",
-    paymentConfig: {
-      signKey: MINI_APP_PRIVATE_KEY,
-      apiUrl: MINI_APP_DOMAIN,
-      gameId: MINI_APP_GAME_ID,
-    },
-    loginConfig: {
-      apiKey: MINI_APP_API_KEY,
-      statApiKey: MINI_APP_STAT_API_KEY,
+    1: {
+        // 木子
+        channelId: 1,
+        name: "木子",
+        platform: "木子",
+        paymentConfig: {
+            signKey: AppSecret360,
+        },
+        loginConfig: {
+            signKey: AppKey360,
+        },
+    },
+    2: {
+        // 三狸安卓
+        channelId: 2,
+        name: "三狸安卓",
+        platform: "quick",
+        paymentConfig: {
+            signKey: QUICK_MD5_KEY,
+            callbackKey: QUICK_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: QUICK_PRODUCT_CODE,
+        },
+    },
+    3: {
+        // 三狸iOS
+        channelId: 3,
+        name: "三狸iOS",
+        platform: "quickIos",
+        paymentConfig: {
+            signKey: QUICK_IOS_MD5_KEY,
+            callbackKey: QUICK_IOS_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: QUICK_IOS_PRODUCT_CODE,
+        },
+    },
+    4: {
+        // QQ大厅
+        channelId: 4,
+        name: "QQ大厅",
+        platform: "qqgame",
+        paymentConfig: {},
+    },
+    5: {
+        // 三狸H5
+        channelId: 5,
+        name: "三狸H5",
+        platform: "quickH5",
+        paymentConfig: {
+            signKey: QUICK_H5_MD5_KEY,
+            callbackKey: QUICK_H5_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: QUICK_H5_PRODUCT_CODE,
+        },
+    },
+    6: {
+        // 4399
+        channelId: 6,
+        name: "4399",
+        platform: "4399h5",
+        paymentConfig: {
+            signKey: CALLBACK_KEY_4399,
+        },
+        loginConfig: {
+            signKey: SECRET_KEY_4399,
+            callKey: CALLBACK_KEY_4399,
+            appId: APP_ID_4399
+        },
+    },
+    7: {
+        // 360
+        channelId: 7,
+        name: "360",
+        platform: "360",
+        paymentConfig: {
+            signKey: SECRET_KEY_QIHU,
+        },
+        loginConfig: {
+            signKey: SECRET_KEY_QIHU,
+        },
+    },
+    999: {
+        // 4399
+        channelId: 6,
+        name: "4399new",
+        platform: "4399h5new",
+        paymentConfig: {
+            signKey: CALLBACK_KEY_4399_V2,
+        },
+        loginConfig: {
+            signKey: SECRET_KEY_4399_V2,
+            callKey: CALLBACK_KEY_4399_V2,
+            appId: APP_ID_4399_V2
+        },
+    },
+    8: {
+        // 七艾H5
+        channelId: 8,
+        name: "七艾",
+        platform: "qiaiH5",
+        paymentConfig: {
+            signKey: QIAI_QUICK_H5_MD5_KEY,
+            callbackKey: QIAI_QUICK_H5_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: QIAI_QUICK_H5_PRODUCT_CODE,
+        },
+    },
+    9: {
+        // 木子
+        channelId: 9,
+        name: "木子ios",
+        platform: "木子ios",
+        paymentConfig: {
+            signKey: MuziIosPayKey,
+        },
+        loginConfig: {
+            signKey: MuziIosLoginKey,
+        },
+    },
+    10: {
+        // 三狸安卓
+        channelId: 10,
+        name: "互视",
+        platform: "quick",
+        paymentConfig: {
+            signKey: QUICK_MD5_KEY,
+            callbackKey: QUICK_CALLBACK_KEY,
+        },
+        loginConfig: {
+            productCode: QUICK_PRODUCT_CODE,
+        },
+    },
+    11: {
+        // 小程序
+        channelId: 11,
+        name: "小程序",
+        platform: "miniapp",
+        paymentConfig: {
+            signKey: MINI_APP_PRIVATE_KEY,
+            apiUrl: MINI_APP_DOMAIN,
+            gameId: MINI_APP_GAME_ID,
+        },
+        loginConfig: {
+            apiKey: MINI_APP_API_KEY,
+            statApiKey: MINI_APP_STAT_API_KEY,
+        },
+    },
+    12: {
+        // ios
+        channelId: 12,
+        name: "ios",
+        platform: "sy_ios",
+        paymentConfig: {
+            signKey: SY_IOS_PRIVATE_KEY,
+            gameId: SY_IOS_GAME_ID,
+        },
+        loginConfig: {
+            signKey: SY_IOS_PRIVATE_KEY,
+        },
     },
-  },
 };

+ 5 - 0
webServer/src/config/thirdParams.ts

@@ -99,3 +99,8 @@ 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";
 
+//圣扬ios
+export const SY_IOS_PRIVATE_KEY = "rDfOG8nq4y9dH0oXfUwghcBQqllmJwrR";
+export const SY_IOS_GAME_ID = "1550";
+export const SY_IOS_API_KEY = "your_api_key_here";
+export const SY_IOS_STAT_API_KEY = "your_stat_api_key_here";

+ 14 - 1
webServer/src/controller/ApiController.ts

@@ -425,8 +425,15 @@ class ApiController {
   async thirdLogin(ctx) {
     const data = ctx.request.body;
     let channelId = parseInt(data.channel_id) || 1;
+    const platform = data.platform; // 平台参数:ios、Android、miniapp、h5
 
-    logger.info("thirdLogin请求参数:", { data, channelId });
+    logger.info("thirdLogin请求参数:", { data, channelId, platform });
+
+    // 渠道11和渠道12数据打通,统一使用渠道11
+    if (channelId === 12) {
+      channelId = 11;
+      logger.info("渠道12映射到渠道11,平台参数:", platform);
+    }
 
     // 获取渠道配置
     let channelConfig = ChannelConfigManager.getConfig(channelId);
@@ -459,11 +466,17 @@ class ApiController {
     logger.info("使用渠道处理器处理登录:", {
       channelId: channelId,
       channelName: channelConfig.name,
+      platform: platform
     });
 
     // 调用渠道处理器的登录方法
     const result = await handler.handleLogin(ctx, channelConfig);
 
+    // 在返回结果中添加平台信息
+    if (result && result.data) {
+      result.data.platform = platform || 'unknown';
+    }
+
     // 根据不同渠道的返回格式要求处理结果
     ctx.body = result;
   }

+ 75 - 9
webServer/src/controller/MiniAppController.ts

@@ -1,20 +1,23 @@
 import { Context } from "koa";
 import { getRoleInfoById,getGuildInfoById } from "../mongo/mongodb";
+import { getServerList } from "../utils/common";
+import axios from "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 
+import {
+  MINI_APP_DOMAIN,
+  MINI_APP_PRIVATE_KEY,
+  MINI_APP_GAME_ID,
+  MINI_APP_API_KEY,
+  MINI_APP_STAT_API_KEY, Account
 } from "../config/thirdParams";
 
 // 导入渠道处理器和配置
 import { channelFactory } from "../channels/factory/ChannelFactory";
 import { channelConfigs } from "../config/channelConfig";
+import Msg from "../utils/msg";
 
 /**
  * 小程序控制器
@@ -323,7 +326,26 @@ class MiniappController {
         reason: data.reason,
         ext: data.ext
       });
+
+      let url = getServerList(data.serverId, data.channel_id || 1);
+      if (!url) {
+        logger.error("区服id错误,无法获取游戏服地址:", data.serverId);
+        return;
+      }
       //调用游戏服禁言接口
+      let param = JSON.stringify({
+        uuid: data.roleid,
+        type: "forbidChat",
+        time: data.forbidDays,
+        reason: data.reason
+      });
+      let sendMsg = new Msg();
+      sendMsg.connect(url, Account);
+      new Promise((resolve) => {
+        setTimeout(async () => {
+          sendMsg.CG_TEST_PROTO(data.accountid, param);
+        }, 1000);
+      });
       return true
 
     } catch (error) {
@@ -347,9 +369,23 @@ class MiniappController {
         roleid: data.roleid,
         ext: data.ext
       });
-      //调用游戏服接口
-
-      // 临时返回成功,实际需要调用游戏服
+      let url = getServerList(data.serverId, data.channel_id || 1);
+      if (!url) {
+        logger.error("区服id错误,无法获取游戏服地址:", data.serverId);
+        return;
+      }
+      //调用游戏服禁言接口
+      let param = JSON.stringify({
+        uuid: data.roleid,
+        type: "freeChat",
+      });
+      let sendMsg = new Msg();
+      sendMsg.connect(url, Account);
+      new Promise((resolve) => {
+        setTimeout(async () => {
+          sendMsg.CG_TEST_PROTO(data.accountid, param);
+        }, 1000);
+      });
       return true
 
     } catch (error) {
@@ -417,6 +453,36 @@ class MiniappController {
       return null;
     }
   }
+
+  /**
+   * 订单校验接口
+   * @param ctx Koa上下文
+   */
+  async verifyOrder(ctx: Context) {
+    try {
+      const handler = MiniappController.getChannelHandler();
+      const config = MiniappController.getChannelConfig();
+      
+      if (!handler) {
+        ctx.body = {
+          success: false,
+          message: "渠道处理器未找到"
+        };
+        return;
+      }
+
+      // 调用渠道处理器的订单校验方法
+      const result = await (handler as any).verifyOrder(ctx, config);
+      ctx.body = result;
+
+    } catch (error) {
+      logger.error("订单校验出错:", error);
+      ctx.body = {
+        success: false,
+        message: "订单校验失败"
+      };
+    }
+  }
   
 }
 

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

@@ -12,6 +12,10 @@ miniAppRouter.post("/editUserRoleInfo", MiniAppController.editUserRoleInfo);
 // 禁言接口
 miniAppRouter.post("/forbidChat", MiniAppController.forbidChat);
 
+// 订单校验接口
+miniAppRouter.get("/verifyOrder", MiniAppController.verifyOrder);
+miniAppRouter.post("/verifyOrder", MiniAppController.verifyOrder);
+
 // 解除禁言接口
 miniAppRouter.post("/freeChat", MiniAppController.freeChat);
 

+ 24 - 0
webServer/src/utils/msg.ts

@@ -267,4 +267,28 @@ export default class Msg {
     this.close(); // 主动断开连接
     return true;
   }
+
+  CG_CHAT_NEW_BAN(
+      uuid: string,
+      type: number,
+      time: number,
+      reason: string,
+  ) {
+    logger.info("发送禁言消息开始", {uuid:uuid,type:type,time:time,reason:reason, readyState: this.websocket.readyState, isConnect: this.isConnect });
+    // console.log("发送登录消息", this.websocket.readyState, this.isConnect);
+    if (this.isConnect != true || this.websocket.readyState != 1) return false;
+    this.sendBufLen = 4;
+    this.writeString(uuid);
+    this.writeInt(type);
+    this.writeInt(time);
+    this.writeString(reason);
+    this.sendBufDV.setInt16(2, 62);
+    this.sendBufDV.setInt16(0, this.sendBufLen - 4);
+    this.send(62);
+    this.close(); // 主动断开连接
+    return true;
+  }
+
+
+
 }

+ 242 - 0
webServer/syiosApi.md

@@ -0,0 +1,242 @@
+# SYIOS 渠道 API 文档
+
+## 渠道信息
+- **渠道ID**: 12
+- **平台**: sy_ios
+- **处理器**: SYIOSChannelHandler
+
+---
+
+## 1. 登录鉴权接口
+
+### 接口地址
+- **GET/POST** `/thirdLogin` (通过渠道ID=12调用)
+
+### 请求参数
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| userToken | string | 是 | 鉴权凭证,从 URL 上获取 |
+| gameid | number | 是 | 游戏的ID,商户后台游戏添加完成后可获取 |
+
+### 请求示例
+```bash
+# POST 请求
+POST /thirdLogin
+Content-Type: application/json
+
+{
+  "channelId": 12,
+  "userToken": "your_token_here",
+  "gameid": 1540
+}
+```
+
+### 响应参数
+```json
+{
+  "code": 1,           // 1成功,-1失败
+  "msg": "登录成功",    // 提示信息
+  "data": {
+    "uid": "",         // 用户UID
+    "nickname": "",    // 用户昵称
+    "headimgurl": "",  // 用户头像地址
+    "sex": "",         // 用户性别 0未知 1男 2女
+    "focus": "",       // 是否关注公众号 0否 1是
+    "usertype": ""     // 用户类型 1为微信用户 -1为非微信用户
+  }
+}
+```
+
+### 错误响应
+```json
+{
+  "code": -1,
+  "msg": "参数有误,请检查接口所需参数是否都已经填写正确",
+  "data": null
+}
+```
+
+---
+
+## 2. 支付回调接口
+
+### 接口地址
+- **GET** `/callback` (通过渠道ID=12调用)
+
+### 请求参数
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| openid | string | 是 | 用户UID |
+| rmb | number | 是 | 付费金额,单位人民币 |
+| reqid | string | 是 | 不重复的请求ID |
+| trans_id | number | 是 | 平台支付订单号 |
+| product_id | number | 是 | 商品ID |
+| notify_id | string | 是 | 平台通知ID |
+| userdata | string | 否 | 支付的透传参数,商户自定义参数,最多128个字节 |
+| txid | string | 否 | 支付的透传参数,商户订单号,最多64个字节 |
+| product_count | number | 否 | 购买的商品数量,默认为1 |
+| sign | string | 是 | 签名,签名算法3 |
+
+### 请求示例
+```bash
+GET /callback?openid=12345678&rmb=1&reqid=20152392834940&trans_id=123456&product_id=6000&notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c&userdata=test_data&txid=merchant_order_123&product_count=1&sign=7761AF5E944ABC6060B3192861FA0281
+```
+
+### 响应
+- **成功**: 返回字符串 `"SUCCESS"` (不包含引号,全大写)
+- **失败**: 返回错误信息
+
+### 支付处理流程
+1. **接收支付回调**: 接收第三方支付平台的回调通知
+2. **验证支付签名**: 使用签名算法3验证支付回调的签名
+3. **提取notify_id**: 从支付回调中提取 `notify_id` 参数
+4. **订单校验**: 调用第三方订单校验API验证订单是否真实有效
+5. **发货处理**: 只有订单校验成功后才进行实际的发货处理
+6. **返回响应**: 返回 `"SUCCESS"` 给第三方支付平台
+
+### 订单校验集成
+支付回调处理中会自动进行订单校验,确保:
+- 防止恶意第三方通知
+- 验证订单的真实性
+- 只有校验成功的订单才会发货
+- 提高支付安全性
+
+---
+
+## 3. 订单校验接口
+
+### 接口地址
+- **GET/POST** `/miniapp/verifyOrder`
+
+### 请求参数
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| gameid | number | 是 | 游戏ID,商户后台游戏添加完成后可获取 |
+| notify_id | string | 是 | 平台通知ID,商户通过notify_id查询订单是否付费成功 |
+| sign | string | 是 | 签名,签名算法3 |
+
+### 请求示例
+```bash
+# GET 请求
+GET /miniapp/verifyOrder?gameid=1540&notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c&sign=A3EA3EF39B43BA762DFBFB78229DB33B
+
+# POST 请求
+POST /miniapp/verifyOrder
+Content-Type: application/json
+
+{
+  "gameid": 1540,
+  "notify_id": "f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c",
+  "sign": "A3EA3EF39B43BA762DFBFB78229DB33B"
+}
+```
+
+### 响应参数
+```json
+{
+  "success": true,        // 校验是否成功
+  "message": "订单校验成功" // 提示信息
+}
+```
+
+### 错误响应
+```json
+{
+  "success": false,
+  "message": "缺少必要参数: gameid"
+}
+```
+
+### 第三方API
+- **请求方式**: GET
+- **URL**: `https://login.11h5.com/pay/paygate/verify.php`
+- **成功响应**: `"SUCCESS"` (不包含引号,全大写)
+- **失败响应**: 其他任何信息
+
+---
+
+## 4. 签名算法3
+
+### 算法步骤
+
+1. **除去为空的参数**: 过滤掉值为空、null、undefined的参数,以及sign参数
+2. **参数排序**: 对参数名按字母顺序排序 (a-z)
+3. **构建字符串**: 用 `&` 连接所有参数,格式为 `key=value`
+4. **拼接私钥**: 在字符串末尾添加 `&key=私钥`
+5. **MD5签名**: 对最终字符串进行MD5哈希,并转换为大写
+
+### 示例
+
+**原始参数**:
+```
+openid=12345678
+rmb=1
+reqid=20152392834940
+trans_id=123456
+product_id=6000
+notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c
+nick=                    // 空参数,会被过滤
+userdata=test_data
+txid=merchant_order_123
+product_count=1
+```
+
+**排序后的待签名字符串**:
+```
+notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c&openid=12345678&product_count=1&product_id=6000&reqid=20152392834940&rmb=1&trans_id=123456&txid=merchant_order_123&userdata=test_data
+```
+
+**最终签名字符串**:
+```
+notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c&openid=12345678&product_count=1&product_id=6000&reqid=20152392834940&rmb=1&trans_id=123456&txid=merchant_order_123&userdata=test_data&key=yduLY3ovg4NwTHMMemGg1vO6VHuYBcYD
+```
+
+**生成的签名**:
+```
+7761AF5E944ABC6060B3192861FA0281
+```
+
+### 订单校验签名示例
+
+**原始参数**:
+```
+gameid=1540
+notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c
+```
+
+**排序后的待签名字符串**:
+```
+gameid=1540&notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c
+```
+
+**最终签名字符串**:
+```
+gameid=1540&notify_id=f2c90bc120cdef27c8cc4d1bdf8341a74625588c6edcd9c&key=yduLY3ovg4NwTHMMemGg1vO6VHuYBcYD
+```
+
+**生成的签名**:
+```
+A3EA3EF39B43BA762DFBFB78229DB33B
+```
+
+---
+
+## 4. 错误码说明
+
+| 错误码 | 说明 |
+|--------|------|
+| 0 | 参数有误,请检查接口所需参数是否都已经填写正确 |
+| 403 | token验证失败,同一个userToken只能验证一次,可通过刷新游戏重新获取 |
+| -1 | 系统错误,鉴权失败,请稍后重试 |
+
+---
+
+## 5. 重要说明
+
+⚠️ **同一个token只能验证一次,不能多次重复请求**
+
+## 6. 第三方API
+
+- **登录鉴权**: `https://api.11h5.com/login?cmd=checkUserToken`
+- **私钥**: `yduLY3ovg4NwTHMMemGg1vO6VHuYBcYD`
+- **游戏ID**: `1540`