TJC.Cyclops.Wechat 2024.8.6.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package TJC.Cyclops.Wechat --version 2024.8.6.2                
NuGet\Install-Package TJC.Cyclops.Wechat -Version 2024.8.6.2                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TJC.Cyclops.Wechat" Version="2024.8.6.2" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add TJC.Cyclops.Wechat --version 2024.8.6.2                
#r "nuget: TJC.Cyclops.Wechat, 2024.8.6.2"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install TJC.Cyclops.Wechat as a Cake Addin
#addin nuget:?package=TJC.Cyclops.Wechat&version=2024.8.6.2

// Install TJC.Cyclops.Wechat as a Cake Tool
#tool nuget:?package=TJC.Cyclops.Wechat&version=2024.8.6.2                

Cyclops.FrameWork

Cyclops.FrameWork 基于aspnetcore封装的api框架,集成了一线开发的常用设置和基础功能;可以用较少的时间代价,让开发人员将精力更多地集中在业务上。

  • [√] 全局api调用和框架级异常日志,支持Knife4j接口文档的查看、调试和代码生成
  • [√] 接口入参校验,Cyclops.FrameWork中的接口参数校验完全基于System.ComponentModel.DataAnnotations,且在此基础上提供了验证数据是否存在ExistAttribute等扩展功能
  • [√] 统一返回值,无论是使用Cyclops.FrameWork中的Result及其子类,或者CSharp中的裸类型都自动返回全局统一值,从框架上避免对接混乱
  • [√] 标准化快捷文件上传、下载和excel的导入、导出,支持MS Azure和阿里OSS
  • [√] 在安全方面集成jwt认证和SafeComparisonFilter防重放攻击,并且支持多租户权限
  • [√] 标准化配置,支持Nacos

NuGet version (SAEA) License

一、配置示例

{
  "ServiceName": "Cyclops.WebApplication1",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "AppConfig": {
    "Urls": [ "https://127.0.0.1:7000" ],
    "DisableSwagger": false,
    "HideConsoleLog": false,
    //jwt TokenManagement
    "JWTAuthConfig": {
      "Secret": "base64:HU8MlQQDHfGaQ+k+0q3z4HKJvNQUTjK5uRGodDATyKc=",
      "Issuer": "yswenli.cnblogs.com",
      "Audience": "Cyclops.FrameWork.WebApi",
      "AccessExpiration": 30
    },
    "MaxRequestSize": 5242880, //5242880,
    "UserStaticPath": true,
    "StaticPaths": [ "upload" ],
    "DisableSafeComparisonFilter": false,
    "SafeComparisonExpired": 5,
    "GloabVerifyCode": "9365"
  },
  "Domain": "https://dev-cyclops.xxx.com/service",
  "SnowId": {
    "WorkerId": 1, // 机器码 全局唯一
    "WorkerIdBitLength": 1, // 机器码位长 默认值6,取值范围 [1, 19]
    "SeqBitLength": 6 // 序列数位长 默认值6,取值范围 [3, 21](建议不小于4,值越大性能越高、Id位数也更长)
  },
  //详细数据库配置见SqlSugar官网(第一个为默认库)
  "DbConnectionOptions": {
    "EnableConsoleSql": false, // 启用控制台打印SQL
    "ConnectionConfigs": [
      {
        "ConfigId": "1300000000001", // 默认库标识-禁止修改
        "DbType": "MySql", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、QuestDB、HG、ClickHouse、GBase、Odbc、Custom
        "ConnectionString": "server=xxx.mysql.rds.aliyuncs.com;user id=xxx; password=xxx; Port=3306;database=xxx; pooling=true",
        //"DbType": "MySql",
        //"ConnectionString": "",
        "DbSettings": {
          "EnableInitDb": false, // 启用库初始化
          "EnableDiffLog": false, // 启用库表差异日志
          "EnableUnderLine": true // 启用驼峰转下划线
        },
        "TableSettings": {
          "EnableInitTable": false, // 启用表初始化
          "EnableIncreTable": false // 启用表增量更新-特性[IncreTable]
        },
        "SeedSettings": {
          "EnableInitSeed": false, // 启用种子初始化
          "EnableIncreSeed": true // 启用种子增量更新-特性[IncreSeed]
        }
      }
      // 日志独立数据库配置
      //,{
      //  "ConfigId": "1300000000002", // 日志库标识-禁止修改
      //  "DbType": "Sqlite",
      //  "ConnectionString": "DataSource=./TJCES.Cyclops.Log.db", // 库连接字符串
      //  "DbSettings": {
      //    "EnableInitDb": true, // 启用库初始化
      //    "EnableDiffLog": false, // 启用库表差异日志
      //    "EnableUnderLine": false // 启用驼峰转下划线
      //  },
      //  "TableSettings": {
      //    "EnableInitTable": true, // 启用表初始化
      //    "EnableIncreTable": false // 启用表增量更新-特性[IncreTable]
      //  },
      //  "SeedSettings": {
      //    "EnableInitSeed": false, // 启用种子初始化
      //    "EnableIncreSeed": false // 启用种子增量更新-特性[IncreSeed]
      //  }
      //}
      //// 其他数据库配置(可以配置多个)
      //,{
      //  "ConfigId": "test", // 库标识
      //  "DbType": "Sqlite", // 库类型
      //  "ConnectionString": "DataSource=./TJCES.Cyclops.Test.db", // 库连接字符串
      //  "DbSettings": {
      //    "EnableInitDb": true, // 启用库初始化
      //    "EnableDiffLog": false, // 启用库表差异日志
      //    "EnableUnderLine": false // 启用驼峰转下划线
      //  },
      //  "TableSettings": {
      //    "EnableInitTable": true, // 启用表初始化
      //    "EnableIncreTable": false // 启用表增量更新-特性[IncreTable]
      //  },
      //  "SeedSettings": {
      //    "EnableInitSeed": true, // 启用种子初始化
      //    "EnableIncreSeed": false // 启用种子增量更新-特性[IncreSeed]
      //  }
      //}
    ]
  },
  //图形验证码
  "CaptchaOptions": {
    "CaptchaType": 2, // 验证码类型0、1、2、3、4、5、6、7、8、9、10、11
    "CodeLength": 4, // 验证码长度, 要放在CaptchaType设置后  当类型为算术表达式时,长度代表操作的个数, 例如2
    "ExpirySeconds": 60, // 验证码过期秒数
    "IgnoreCase": true, // 比较时是否忽略大小写
    "StoreageKeyPrefix": "", // 存储键前缀
    "ImageOption": {
      "Animation": false, // 是否启用动画
      "FontSize": 36, // 字体大小
      "Width": 150, // 验证码宽度
      "Height": 50, // 验证码高度
      "BubbleMinRadius": 5, // 气泡最小半径
      "BubbleMaxRadius": 10, // 气泡最大半径
      "BubbleCount": 3, // 气泡数量
      "BubbleThickness": 1.0, // 气泡边沿厚度
      "InterferenceLineCount": 3, // 干扰线数量
      "FontFamily": "kaiti", // 包含actionj,epilog,fresnel,headache,lexo,prefix,progbot,ransom,robot,scandal,kaiti
      "FrameDelay": 300, // 每帧延迟,Animation=true时有效, 默认300
      "BackgroundColor": "#ffffff", //  格式: rgb, rgba, rrggbb, or rrggbbaa format to match web syntax, 默认#fff
      "ForegroundColors": "", //  颜色格式同BackgroundColor,多个颜色逗号分割,随机选取。不填,空值,则使用默认颜色集
      "Quality": 100, // 图片质量(质量越高图片越大,gif调整无效可能会更大)
      "TextBold": true // 粗体
    },
    "DefaultCode": "9365"
  },
  //redis配置
  "RedisConfig": {
    "SectionName": "Redis",
    "Type": 0,
    "Password": "xxx=",
    "Masters": "xxxx:6379",
    "Slaves": null,
    "ServiceName": "mymaster",
    "DefaultDatabase": 0,
    "AllowAdmin": true,
    "KeepAlive": 180,
    "ConnectTimeout": 10000,
    "ConnectRetry": 1,
    "BusyRetry": 3,
    "BusyRetryWaitMS": 15000,
    "PoolSize": 1,
    "CommandTimeout": 60000,
    "Extention": null
  },
  //微信公众号/小程序
  "WechatOptions": {
    // 公众号-正式版公众测试号
    "WechatAppId": "xxx",
    "WechatAppSecret": "xxx",
    // 小程序
    "WxOpenAppId": "",
    "WxOpenAppSecret": ""
  },
  // 微信支付
  "WechatPayOptions": {
    "AppId": "xxx", // 微信公众平台AppId、开放平台AppId、小程序AppId、企业微信CorpId
    "MerchantId": "xxx", // 商户平台的商户号
    "MerchantV3Secret": "xxx", // 商户平台的APIv3密钥
    "MerchantCertificateSerialNumber": "xxx", // 商户平台的证书序列号
    "MerchantCertificatePrivateKey": "/WxPayCert/apiclient_key.pem", // 商户平台的API证书私钥(apiclient_key.pem文件内容)
    "WechatPayUrl": "/api/sysWechatPay/payCallBack" // 微信支付回调
  },
  //上传文件
  "UploadOptions": {
    "Path": "Upload/{yyyy}/{MM}/{dd}", // 文件上传目录
    "MaxSize": 5242880, // 文件最大限制1024*1024*50
    "ContentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif", "image/bmp", "text/plain", "application/pdf", "application/msword", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "video/mp4" ],
    "EnableMd5": true // 启用文件MDF5验证-防止重复上传
  },

  //短信
  "SmsOption": {
    "ZhuTong": {
      "UserName": "xxx",
      "Password": "xxx",
      "Signature": "【Cyclops】"
    }
  },

  //直播配置
  "LiveConfig": {
    "AppId": "xxx",
    "AppSecret": "xxx",
    "Url": "https://devapimeeting.xxx.com",
    "AuthorizeUrl": "https://devmeeting.xxx.com"
  },

  //语音转换
  "SpeechConfig": {
    "SpeechType": 1,
    "ClientId": "xxx",
    "ClientSecret": "xxx"
  }

}

AppConfig节点以下的可以与nacos集成

二、初始化代码示例

public class Program
{
    public static void Main(string[] args)
    {
        WebApp.OnStarted += WebApp_OnStarted;
        WebApp.OnStopped += WebApp_OnStopped;
        WebApp.RunWebHost<Startup>(args);
    }


    static void WebApp_OnStarted()
    {
        Logger.Info($"{WebApp.ServiceName}应用已启动");
    }


    static void WebApp_OnStopped()
    {
        Logger.Info($"{WebApp.ServiceName}应用已停止");
    }
}
    /// <summary>
    /// Startup
    /// </summary>
    public class Startup : BaseStartup
    {
        /// <summary>
        /// Startup
        /// </summary>
        /// <param name="configuration"></param>
        public Startup(IConfiguration configuration) : base(configuration)
        {

        }
    }

三、控制器示例

继承基类即可

public class AuthController : BaseApiController

方法示例

    /// <summary>
    /// Login
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [AllowAnonymous, HttpPost, DisplayName("Login")]
    public async Task<Result> Login([Required(ErrorMessage = "请输入用户名或密码"), FromBody] UserLoginInput input)
    {
        var user = new SysUser();
        return SuccessResult(await CreateToken(user));
    }

    /// <summary>
    /// 获取验证码
    /// </summary>
    /// <returns></returns>
    [AllowAnonymous]
    [SuppressMonitor]
    [DisplayName("获取验证码"), HttpGet]
    public Result GetCaptcha()
    {
        ICaptcha captcha = ServiceProviderUtil.GetRequiredService<ICaptcha>();
        var codeId = YitIdHelper.NextId().ToString();
        var captchas = captcha.Generate(codeId, 180);
        return SuccessResult(new { Id = codeId, Img = captchas.Base64 });
    }

四、集成数据校验

/// <summary>
/// 登录信息
/// </summary>
public class UserLoginInput
{
    /// <summary>
    /// 请输入用户名
    /// </summary>
    [Required(ErrorMessage = "请输入用户名"), Exists("用户名不存在", TableName = "bus_user", ColumnName = "user_name")]
    public string UserName { get; set; }
    /// <summary>
    /// 请输入密码
    /// </summary>
    [Required(ErrorMessage = "请输入密码"), Custom<UserLoginInput>("密码不正确", "Valide")]
    public string Password { get; set; }

    /// <summary>
    /// 验证密码
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public bool Valide(object? input)
    {
        if (input == null) return false;
        if (input is string password && password == "123456")
        {
            return true;
        }
        return false;

    }
}

五、防重放攻击示例

    /// <summary>
    /// 接口安全参数校验测试
    /// </summary>
    [SafeComparisonFilter]
    public class SafeController : BaseApiController
    {
        /// <summary>
        /// Test
        /// </summary>
        /// <param name="testInfo"></param>
        /// <returns></returns>
        [HttpPost]
        public Result Test([FromBody] TestInfo testInfo)
        {
            return SuccessResult(testInfo);
        }

        /// <summary>
        /// test2
        /// </summary>
        /// <returns></returns>
        [HttpGet, AllowAnonymous, NoSafeComparisonFilter]
        public Result Test2()
        {
            return SuccessResult();
        }
    }

六、文件上传下载Excel导入导出示例

   public class FileAdminController : BaseApiController
   {
       /// <summary>
       /// 导入
       /// </summary>
       /// <returns></returns>
       [HttpPost]
       [NoLoginAuth, AllowAnonymous]
       public Result Import(IFormCollection collection)
       {
           var data = collection.SaveAsDataTable();
           return SuccessResult(data);
       }


       /// <summary>
       /// 导出
       /// </summary>
       /// <returns></returns>
       [HttpPost]
       [NoLoginAuth, AllowAnonymous]
       public IActionResult Export()
       {
           return _env.Download("export.png");
       }

       /// <summary>
       /// 导出数据文件
       /// </summary>
       /// <returns></returns>
       [HttpGet]
       [NoLoginAuth, AllowAnonymous]
       public IActionResult ExportFile([FromQuery] bool isExcel = false)
       {
           var fileName = "export.xlsx";
           if (!isExcel)
           {
               fileName = "export.csv";
           }
           var dt = new DataTable();
           //return _env.ExportFile(dt, fileName);
           return Export(dt, fileName);
       }


       /// <summary>
       /// 导出数据文件
       /// </summary>
       /// <returns></returns>
       [HttpGet]
       [NoLoginAuth, AllowAnonymous]
       public IActionResult ExportDataFile([FromQuery] bool isExcel = false)
       {
           var fileName = "export.xlsx";
           if (!isExcel)
           {
               fileName = "export.csv";
           }
           var list = new List<BusUser>
           {
               new BusUser()
               {
                   Id = 1,
                   UserName = "张三"
               }
           };
           //return _env.ExportFile(list, fileName);
           return Export(list, fileName);
       }



       /// <summary>
       /// 测试上传文件大小
       /// </summary>
       /// <returns></returns>
       [HttpPost]
       public async Task<IActionResult> UploadFile(IFormCollection form)
       {
           var fileStream = await form.SaveAsStreamsAsync();

           return fileStream.First().Value.Download("test.jpg");
       }

       /// <summary>
       /// 测试限制上传文件大小
       /// </summary>
       /// <param name="form"></param>
       /// <returns></returns>

       [HttpPost, RequestSizeLimit(2 * 1024 * 1024)]
       public async Task<IActionResult> UploadFileByLimit(IFormCollection form)
       {
           var fileStream = await form.SaveAsStreamsAsync();

           return fileStream.First().Value.Download("test.jpg");
       }

       /// <summary>
       /// 测试不限制上传文件大小
       /// </summary>
       /// <param name="form"></param>
       /// <returns></returns>

       [HttpPost, DisableRequestSizeLimit]
       public async Task<IActionResult> UploadFileByNonLimit(IFormCollection form)
       {
           var fileStream = await form.SaveAsStreamsAsync();

           return fileStream.First().Value.Download("test.jpg");
       }       

      /// <summary>
      /// 示例获取流
      /// </summary>
      /// <returns></returns>
      [HttpGet]
      public async Task<Stream> GetStream()
      {
          var ms = new MemoryStream(RandomUtil.GetBytes(1024));
          return await Task.FromResult(ms);
      }

      /// <summary>
      /// 示例获取字节数组
      /// </summary>
      /// <returns></returns>
      [HttpGet]
      public async Task<byte[]> GetBytes()
      {
          return await Task.FromResult(RandomUtil.GetBytes(1024));
      }
   }

七、支持非api接口内容

        /// <summary>
        /// 返回指定内容结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="text"></param>
        /// <param name="contentType"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        public async Task<IActionResult> ContentAsync(string text, string contentType = "text/plain", int statusCode = 200)
        {
            var contentResult = new ContentResult()
            {
                Content = text,
                ContentType = contentType,
                StatusCode = statusCode
            };
            return await Task.FromResult(contentResult);
        }

        /// <summary>
        /// 返回空结果
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public async Task<IActionResult> EmptyAsync()
        {
            return await Task.FromResult(new EmptyResult());
        }

        /// <summary>
        /// 返回下载结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="fileContent">下载时的文件名称</param>
        /// <param name="fileContent">内容字节数组</param>
        /// <param name="contentType">内容mime类型</param>
        /// <returns></returns>
        public async Task<IActionResult> DownloadAsync(string fileDownloadName,
            byte[] fileContent,
            string contentType)
        {
            return await Task.FromResult(new FileContentResult(fileContent, contentType) { FileDownloadName = fileDownloadName });
        }

        /// <summary>
        /// 返回下载结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="fileName">内容文件地址</param>
        /// <param name="contentType">内容mime类型</param>
        /// <returns></returns>
        public async Task<IActionResult> DownloadAsync(string fileName,
            string contentType)
        {
            return await Task.FromResult(new VirtualFileResult(fileName, contentType)
            {
                EnableRangeProcessing = true,
                FileDownloadName = PathUtil.GetFileName(fileName)
            });
        }
        /// <summary>
        /// 返回流结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="fileDownloadName"></param>
        /// <param name="fileStream"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public async Task<IActionResult> DownloadAsync(string fileDownloadName,
            Stream fileStream,
            string contentType
            )
        {
            return await Task.FromResult(new FileStreamResult(fileStream, contentType)
            {
                EnableRangeProcessing = true,
                FileDownloadName = fileDownloadName
            });
        }
        /// <summary>
        /// 返回跳转结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<IActionResult> RedirectAsync(string url)
        {
            return await Task.FromResult(new RedirectResult(url));
        }
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2024.11.8.1 38 11/8/2024
2024.11.6.1 64 11/6/2024
2024.11.5.1 60 11/5/2024
2024.10.29.2 72 10/29/2024
2024.10.29.1 73 10/29/2024
2024.10.28.1 66 10/28/2024
2024.10.25.1 67 10/25/2024
2024.10.24.1 63 10/24/2024
2024.10.21.1 73 10/21/2024
2024.10.18.2 98 10/18/2024
2024.10.18.1 101 10/18/2024
2024.10.16.1 75 10/16/2024
2024.10.12.1 77 10/12/2024
2024.10.11.1 73 10/11/2024
2024.10.10.1 88 10/10/2024
2024.10.9.1 82 10/9/2024
2024.10.8.1 70 10/8/2024
2024.9.26.1 144 9/26/2024
2024.9.25.1 117 9/25/2024
2024.9.23.4 85 9/23/2024
2024.9.23.3 79 9/23/2024
2024.9.23.2 74 9/23/2024
2024.9.23.1 86 9/23/2024
2024.9.19.1 78 9/19/2024
2024.9.14.1 92 9/14/2024
2024.9.10.3 110 9/10/2024
2024.9.10.2 154 9/10/2024
2024.9.10.1 103 9/10/2024
2024.9.5.1 101 9/5/2024
2024.8.22.1 147 8/22/2024
2024.8.21.1 114 8/21/2024
2024.8.19.1 131 8/19/2024
2024.8.15.1 103 8/15/2024
2024.8.14.1 100 8/14/2024
2024.8.13.2 107 8/13/2024
2024.8.13.1 115 8/13/2024
2024.8.12.2 104 8/12/2024
2024.8.12.1 121 8/12/2024
2024.8.9.2 92 8/9/2024
2024.8.9.1 99 8/9/2024
2024.8.7.1 88 8/7/2024
2024.8.6.2 93 8/6/2024
2024.8.6.1 94 8/6/2024
2024.8.5.5 72 8/5/2024
2024.8.5.4 67 8/5/2024
2024.8.5.3 79 8/5/2024
2024.8.5.2 57 8/5/2024
2024.8.5.1 79 8/5/2024
2024.8.2.4 80 8/2/2024
2024.8.2.3 78 8/2/2024
2024.8.2.2 80 8/2/2024
2024.8.2.1 57 8/2/2024
2024.8.1.1 95 8/1/2024
2024.7.31.2 54 7/31/2024
2024.7.31.1 49 7/31/2024
2024.7.25.1 63 7/25/2024
2024.7.17.1 120 7/17/2024
2024.7.12.2 106 7/12/2024
2024.7.12.1 98 7/12/2024
2024.7.11.2 97 7/11/2024
2024.7.11.1 78 7/11/2024
2024.7.10.4 98 7/10/2024
2024.7.10.3 107 7/10/2024
2024.7.10.2 71 7/10/2024
2024.7.10.1 99 7/10/2024
2024.5.29.1 137 5/29/2024
2024.5.28.1 151 5/28/2024
2024.5.15.1 140 5/15/2024
2024.5.13.1 94 5/13/2024
2024.5.11.1 104 5/11/2024
2024.3.15.1 136 3/15/2024
2024.1.9.1 126 1/9/2024
2024.1.4.1 126 1/4/2024
2024.1.2.3 241 1/2/2024
2024.1.2.2 149 1/2/2024
2024.1.2.1 122 1/2/2024
2023.12.29.3 129 12/29/2023
2023.12.29.2 117 12/29/2023
2023.12.29.1 136 12/29/2023
2023.12.28.4 133 12/28/2023
2023.12.28.3 131 12/28/2023
2023.12.28.2 141 12/28/2023
2023.12.28.1 123 12/28/2023
2023.12.27.2 118 12/27/2023
2023.12.27.1 121 12/27/2023
2023.12.26.1 116 12/26/2023
2023.12.25.1 124 12/25/2023
2023.12.22.4 121 12/22/2023
2023.12.22.3 117 12/22/2023
2023.12.22.2 111 12/22/2023
2023.12.22.1 113 12/22/2023
2023.12.21.2 116 12/21/2023
2023.12.21.1 130 12/21/2023
2023.12.20.2 130 12/20/2023
2023.12.20.1 101 12/20/2023
2023.12.14.4 158 12/14/2023
2023.12.14.3 116 12/14/2023
2023.12.14.2 110 12/14/2023
2023.12.14.1 114 12/14/2023
2023.12.13.9 98 12/14/2023
2023.12.13.8 101 12/14/2023
2023.12.13.7 118 12/13/2023
2023.12.13.6 104 12/13/2023
2023.12.13.5 123 12/13/2023
2023.12.13.4 116 12/13/2023
2023.12.13.3 110 12/13/2023
2023.12.13.1 112 12/13/2023
2023.12.13 109 12/13/2023

企服版框架中微信对接相关业务核心项目