// Admin.NET 项目的版æƒã€å•†æ ‡ã€ä¸“利和其他相关æƒåˆ©å‡å—ç›¸åº”æ³•å¾‹æ³•è§„çš„ä¿æŠ¤ã€‚ä½¿ç”¨æœ¬é¡¹ç›®åº”éµå®ˆç›¸å…³æ³•律法规和许å¯è¯çš„è¦æ±‚。 // // 本项目主è¦éµå¾ª MIT 许å¯è¯å’Œ Apache 许å¯è¯ï¼ˆç‰ˆæœ¬ 2.0)进行分å‘和使用。许å¯è¯ä½äºŽæºä»£ç æ ‘æ ¹ç›®å½•ä¸çš„ LICENSE-MIT å’Œ LICENSE-APACHE 文件。 // // ä¸å¾—利用本项目从事å±å®³å›½å®¶å®‰å…¨ã€æ‰°ä¹±ç¤¾ä¼šç§©åºã€ä¾µçŠ¯ä»–äººåˆæ³•æƒç›Šç‰æ³•å¾‹æ³•è§„ç¦æ¢çš„æ´»åЍï¼ä»»ä½•基于本项目二次开å‘è€Œäº§ç”Ÿçš„ä¸€åˆ‡æ³•å¾‹çº çº·å’Œè´£ä»»ï¼Œæˆ‘ä»¬ä¸æ‰¿æ‹…ä»»ä½•è´£ä»»ï¼ namespace Admin.NET.Core.Service; /// <summary> /// 微信å°ç¨‹åºæœåŠ¡ 🧩 /// </summary> [ApiDescriptionSettings(Order = 240)] public class SysWxOpenService : IDynamicApiController, ITransient { private readonly SqlSugarRepository<SysWechatUser> _sysWechatUserRep; private readonly SysConfigService _sysConfigService; private readonly WechatApiClient _wechatApiClient; public SysWxOpenService(SqlSugarRepository<SysWechatUser> sysWechatUserRep, SysConfigService sysConfigService, WechatApiClientFactory wechatApiClientFactory) { _sysWechatUserRep = sysWechatUserRep; _sysConfigService = sysConfigService; _wechatApiClient = wechatApiClientFactory.CreateWxOpenClient(); } /// <summary> /// 获å–微信用户OpenId 🔖 /// </summary> /// <param name="input"></param> [AllowAnonymous] [DisplayName("获å–微信用户OpenId")] public async Task<WxOpenIdOutput> GetWxOpenId([FromQuery] JsCode2SessionInput input) { var reqJsCode2Session = new SnsJsCode2SessionRequest() { JsCode = input.JsCode, }; var resCode2Session = await _wechatApiClient.ExecuteSnsJsCode2SessionAsync(reqJsCode2Session); if (resCode2Session.ErrorCode != (int)WechatReturnCodeEnum.请求æˆåŠŸ) throw Oops.Oh(resCode2Session.ErrorMessage + " " + resCode2Session.ErrorCode); var wxUser = await _sysWechatUserRep.GetFirstAsync(p => p.OpenId == resCode2Session.OpenId); if (wxUser == null) { wxUser = new SysWechatUser { OpenId = resCode2Session.OpenId, UnionId = resCode2Session.UnionId, SessionKey = resCode2Session.SessionKey, PlatformType = PlatformTypeEnum.微信å°ç¨‹åº }; wxUser = await _sysWechatUserRep.AsInsertable(wxUser).ExecuteReturnEntityAsync(); } else { await _sysWechatUserRep.AsUpdateable(wxUser).IgnoreColumns(true).ExecuteCommandAsync(); } return new WxOpenIdOutput { OpenId = resCode2Session.OpenId }; } /// <summary> /// 获å–微信用户电è¯å·ç 🔖 /// </summary> /// <param name="input"></param> [AllowAnonymous] [DisplayName("获å–微信用户电è¯å·ç ")] public async Task<WxPhoneOutput> GetWxPhone([FromQuery] WxPhoneInput input) { var accessToken = await GetCgibinToken(); var reqUserPhoneNumber = new WxaBusinessGetUserPhoneNumberRequest() { Code = input.Code, AccessToken = accessToken, }; var resUserPhoneNumber = await _wechatApiClient.ExecuteWxaBusinessGetUserPhoneNumberAsync(reqUserPhoneNumber); if (resUserPhoneNumber.ErrorCode != (int)WechatReturnCodeEnum.请求æˆåŠŸ) throw Oops.Oh(resUserPhoneNumber.ErrorMessage + " " + resUserPhoneNumber.ErrorCode); var wxUser = await _sysWechatUserRep.GetFirstAsync(p => p.OpenId == input.OpenId); if (wxUser == null) { wxUser = new SysWechatUser { OpenId = input.OpenId, Mobile = resUserPhoneNumber.PhoneInfo?.PhoneNumber, PlatformType = PlatformTypeEnum.微信å°ç¨‹åº }; wxUser = await _sysWechatUserRep.AsInsertable(wxUser).ExecuteReturnEntityAsync(); } else { wxUser.Mobile = resUserPhoneNumber.PhoneInfo?.PhoneNumber; await _sysWechatUserRep.AsUpdateable(wxUser).IgnoreColumns(true).ExecuteCommandAsync(); } return new WxPhoneOutput { PhoneNumber = resUserPhoneNumber.PhoneInfo?.PhoneNumber }; } /// <summary> /// 微信å°ç¨‹åºç™»å½•OpenId 🔖 /// </summary> /// <param name="input"></param> /// <returns></returns> [AllowAnonymous] [DisplayName("微信å°ç¨‹åºç™»å½•OpenId")] public async Task<dynamic> WxOpenIdLogin(WxOpenIdLoginInput input) { var wxUser = await _sysWechatUserRep.GetFirstAsync(p => p.OpenId == input.OpenId); if (wxUser == null) throw Oops.Oh("微信å°ç¨‹åºç™»å½•失败"); var tokenExpire = await _sysConfigService.GetTokenExpire(); return new { wxUser.Avatar, accessToken = JWTEncryption.Encrypt(new Dictionary<string, object> { { ClaimConst.UserId, wxUser.Id }, { ClaimConst.RealName, wxUser.NickName }, { ClaimConst.LoginMode, LoginModeEnum.APP }, }, tokenExpire) }; } /// <summary> /// 获å–è®¢é˜…æ¶ˆæ¯æ¨¡æ¿åˆ—表 🔖 /// </summary> [DisplayName("获å–è®¢é˜…æ¶ˆæ¯æ¨¡æ¿åˆ—表")] public async Task<dynamic> GetMessageTemplateList() { var accessToken = await GetCgibinToken(); var reqTemplate = new WxaApiNewTemplateGetTemplateRequest() { AccessToken = accessToken }; var resTemplate = await _wechatApiClient.ExecuteWxaApiNewTemplateGetTemplateAsync(reqTemplate); if (resTemplate.ErrorCode != (int)WechatReturnCodeEnum.请求æˆåŠŸ) throw Oops.Oh(resTemplate.ErrorMessage + " " + resTemplate.ErrorCode); return resTemplate.TemplateList; } /// <summary> /// å‘é€è®¢é˜…æ¶ˆæ¯ ðŸ”– /// </summary> /// <param name="input"></param> /// <returns></returns> [DisplayName("å‘é€è®¢é˜…消æ¯")] public async Task<dynamic> SendSubscribeMessage(SendSubscribeMessageInput input) { var accessToken = await GetCgibinToken(); var reqMessage = new CgibinMessageSubscribeSendRequest() { AccessToken = accessToken, TemplateId = input.TemplateId, ToUserOpenId = input.ToUserOpenId, Data = input.Data, MiniProgramState = input.MiniprogramState, Language = input.Language, MiniProgramPagePath = input.MiniProgramPagePath }; var resMessage = await _wechatApiClient.ExecuteCgibinMessageSubscribeSendAsync(reqMessage); return resMessage; } /// <summary> /// å¢žåŠ è®¢é˜…æ¶ˆæ¯æ¨¡æ¿ 🔖 /// </summary> /// <param name="input"></param> /// <returns></returns> [ApiDescriptionSettings(Name = "AddSubscribeMessageTemplate"), HttpPost] [DisplayName("å¢žåŠ è®¢é˜…æ¶ˆæ¯æ¨¡æ¿")] public async Task<dynamic> AddSubscribeMessageTemplate(AddSubscribeMessageTemplateInput input) { var accessToken = await GetCgibinToken(); var reqMessage = new WxaApiNewTemplateAddTemplateRequest() { AccessToken = accessToken, TemplateTitleId = input.TemplateTitleId, KeyworkIdList = input.KeyworkIdList, SceneDescription = input.SceneDescription }; var resTemplate = await _wechatApiClient.ExecuteWxaApiNewTemplateAddTemplateAsync(reqMessage); return resTemplate; } /// <summary> /// 生æˆäºŒç»´ç /// </summary> /// <param name="input"> 扫ç 进入的å°ç¨‹åºé¡µé¢è·¯å¾„,最大长度 128 个å—符,ä¸èƒ½ä¸ºç©ºï¼› eg: pages / index ? id = AY000001 </param> /// <returns></returns> [DisplayName("生æˆå°ç¨‹åºäºŒç»´ç ")] [ApiDescriptionSettings(Name = "GenerateQRImage")] public async Task<GenerateQRImageOutput> GenerateQRImageAsync(GenerateQRImageInput input) { GenerateQRImageOutput generateQRImageOutInput = new GenerateQRImageOutput(); if (input.PagePath.IsNullOrEmpty()) { generateQRImageOutInput.Success = false; generateQRImageOutInput.ImgPath = ""; generateQRImageOutInput.Message = $"生æˆå¤±è´¥ 页é¢è·¯å¾„ä¸èƒ½ä¸ºç©º"; return generateQRImageOutInput; } if (input.ImageName.IsNullOrEmpty()) { input.ImageName = DateTime.Now.ToString("yyyyMMddHHmmss"); } var accessToken = await GetCgibinToken(); var request = new CgibinWxaappCreateWxaQrcodeRequest { AccessToken = accessToken, Path = input.PagePath, Width = input.Width }; var response = await _wechatApiClient.ExecuteCgibinWxaappCreateWxaQrcodeAsync(request); if (response.IsSuccessful()) { var QRImagePath = App.GetConfig<string>("Wechat:QRImagePath"); //åˆ¤æ–æ–‡ä»¶å˜æ”¾è·¯å¾„是å¦å˜åœ¨ if (!Directory.Exists(QRImagePath)) { Directory.CreateDirectory(QRImagePath); } // 将二维ç 图片数æ®ä¿å˜ä¸ºæ–‡ä»¶ var filePath = QRImagePath + $"\\{input.ImageName.ToUpper()}.png"; if (File.Exists(filePath)) { File.Delete(filePath); } File.WriteAllBytes(filePath, response.GetRawBytes()); generateQRImageOutInput.Success = true; generateQRImageOutInput.ImgPath = filePath; generateQRImageOutInput.Message = "ç”ŸæˆæˆåŠŸ"; } else { // 处ç†é”™è¯¯æƒ…况 generateQRImageOutInput.Success = false; generateQRImageOutInput.ImgPath = ""; generateQRImageOutInput.Message = $"生æˆå¤±è´¥ 错误代ç :{response.ErrorCode} 错误æè¿°ï¼š{response.ErrorMessage}"; } return generateQRImageOutInput; } /// <summary> /// 获å–Access_token /// </summary> private async Task<string> GetCgibinToken() { var reqCgibinToken = new CgibinTokenRequest(); var resCgibinToken = await _wechatApiClient.ExecuteCgibinTokenAsync(reqCgibinToken); if (resCgibinToken.ErrorCode != (int)WechatReturnCodeEnum.请求æˆåŠŸ) throw Oops.Oh(resCgibinToken.ErrorMessage + " " + resCgibinToken.ErrorCode); return resCgibinToken.AccessToken; } }