SysWechatService.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // 大名科技(天津)有限公司 版权所有
  2. //
  3. // 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
  4. //
  5. // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动
  6. //
  7. // 任何基于本项目二次开发而产生的一切法律纠纷和责任,均与作者无关
  8. namespace Admin.NET.Core.Service;
  9. /// <summary>
  10. /// 微信公众号服务 💥
  11. /// </summary>
  12. [ApiDescriptionSettings(Order = 230)]
  13. public class SysWechatService : IDynamicApiController, ITransient
  14. {
  15. private readonly SqlSugarRepository<SysWechatUser> _sysWechatUserRep;
  16. private readonly SysConfigService _sysConfigService;
  17. private readonly WechatApiClientFactory _wechatApiClientFactory;
  18. private readonly WechatApiClient _wechatApiClient;
  19. public SysWechatService(SqlSugarRepository<SysWechatUser> sysWechatUserRep,
  20. SysConfigService sysConfigService,
  21. WechatApiClientFactory wechatApiClientFactory)
  22. {
  23. _sysWechatUserRep = sysWechatUserRep;
  24. _sysConfigService = sysConfigService;
  25. _wechatApiClientFactory = wechatApiClientFactory;
  26. _wechatApiClient = wechatApiClientFactory.CreateWechatClient();
  27. }
  28. /// <summary>
  29. /// 生成网页授权Url 🔖
  30. /// </summary>
  31. /// <param name="input"></param>
  32. /// <returns></returns>
  33. [AllowAnonymous]
  34. [DisplayName("生成网页授权Url")]
  35. public string GenAuthUrl(GenAuthUrlInput input)
  36. {
  37. return _wechatApiClient.GenerateParameterizedUrlForConnectOAuth2Authorize(input.RedirectUrl, input.Scope, input.State);
  38. }
  39. /// <summary>
  40. /// 获取微信用户OpenId 🔖
  41. /// </summary>
  42. /// <param name="input"></param>
  43. [AllowAnonymous]
  44. [DisplayName("获取微信用户OpenId")]
  45. public async Task<string> SnsOAuth2([FromQuery] WechatOAuth2Input input)
  46. {
  47. var reqOAuth2 = new SnsOAuth2AccessTokenRequest()
  48. {
  49. Code = input.Code,
  50. };
  51. var resOAuth2 = await _wechatApiClient.ExecuteSnsOAuth2AccessTokenAsync(reqOAuth2);
  52. if (resOAuth2.ErrorCode != (int)WechatReturnCodeEnum.请求成功)
  53. throw Oops.Oh(resOAuth2.ErrorMessage + " " + resOAuth2.ErrorCode);
  54. var wxUser = await _sysWechatUserRep.GetFirstAsync(p => p.OpenId == resOAuth2.OpenId);
  55. if (wxUser == null)
  56. {
  57. var reqUserInfo = new SnsUserInfoRequest()
  58. {
  59. OpenId = resOAuth2.OpenId,
  60. AccessToken = resOAuth2.AccessToken,
  61. };
  62. var resUserInfo = await _wechatApiClient.ExecuteSnsUserInfoAsync(reqUserInfo);
  63. wxUser = resUserInfo.Adapt<SysWechatUser>();
  64. wxUser.Avatar = resUserInfo.HeadImageUrl;
  65. wxUser.NickName = resUserInfo.Nickname;
  66. wxUser = await _sysWechatUserRep.AsInsertable(wxUser).ExecuteReturnEntityAsync();
  67. }
  68. else
  69. {
  70. wxUser.AccessToken = resOAuth2.AccessToken;
  71. wxUser.RefreshToken = resOAuth2.RefreshToken;
  72. await _sysWechatUserRep.AsUpdateable(wxUser).IgnoreColumns(true).ExecuteCommandAsync();
  73. }
  74. return resOAuth2.OpenId;
  75. }
  76. /// <summary>
  77. /// 微信用户登录OpenId 🔖
  78. /// </summary>
  79. /// <param name="input"></param>
  80. /// <returns></returns>
  81. [AllowAnonymous]
  82. [DisplayName("微信用户登录OpenId")]
  83. public async Task<dynamic> OpenIdLogin(WechatUserLogin input)
  84. {
  85. var wxUser = await _sysWechatUserRep.GetFirstAsync(p => p.OpenId == input.OpenId);
  86. if (wxUser == null)
  87. throw Oops.Oh("微信用户登录OpenId错误");
  88. var tokenExpire = await _sysConfigService.GetTokenExpire();
  89. return new
  90. {
  91. wxUser.Avatar,
  92. accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
  93. {
  94. { ClaimConst.UserId, wxUser.Id },
  95. { ClaimConst.NickName, wxUser.NickName },
  96. { ClaimConst.LoginMode, LoginModeEnum.APP },
  97. }, tokenExpire)
  98. };
  99. }
  100. /// <summary>
  101. /// 获取配置签名参数(wx.config) 🔖
  102. /// </summary>
  103. /// <returns></returns>
  104. [DisplayName("获取配置签名参数(wx.config)")]
  105. public async Task<dynamic> GenConfigPara(SignatureInput input)
  106. {
  107. var resCgibinToken = await _wechatApiClient.ExecuteCgibinTokenAsync(new CgibinTokenRequest());
  108. var request = new CgibinTicketGetTicketRequest()
  109. {
  110. AccessToken = resCgibinToken.AccessToken
  111. };
  112. var response = await _wechatApiClient.ExecuteCgibinTicketGetTicketAsync(request);
  113. if (!response.IsSuccessful())
  114. throw Oops.Oh(response.ErrorMessage);
  115. return _wechatApiClient.GenerateParametersForJSSDKConfig(response.Ticket, input.Url);
  116. }
  117. /// <summary>
  118. /// 获取模板列表 🔖
  119. /// </summary>
  120. [DisplayName("获取模板列表")]
  121. public async Task<dynamic> GetMessageTemplateList()
  122. {
  123. var accessToken = await GetCgibinToken();
  124. var reqTemplate = new CgibinTemplateGetAllPrivateTemplateRequest()
  125. {
  126. AccessToken = accessToken
  127. };
  128. var resTemplate = await _wechatApiClient.ExecuteCgibinTemplateGetAllPrivateTemplateAsync(reqTemplate);
  129. if (resTemplate.ErrorCode != (int)WechatReturnCodeEnum.请求成功)
  130. throw Oops.Oh(resTemplate.ErrorMessage + " " + resTemplate.ErrorCode);
  131. return resTemplate.TemplateList;
  132. }
  133. /// <summary>
  134. /// 发送模板消息 🔖
  135. /// </summary>
  136. /// <param name="input"></param>
  137. /// <returns></returns>
  138. [DisplayName("发送模板消息")]
  139. public async Task<dynamic> SendTemplateMessage(MessageTemplateSendInput input)
  140. {
  141. var dataInfo = input.Data.ToDictionary(k => k.Key, k => k.Value);
  142. var messageData = new Dictionary<string, CgibinMessageTemplateSendRequest.Types.DataItem>();
  143. foreach (var item in dataInfo)
  144. {
  145. messageData.Add(item.Key, new CgibinMessageTemplateSendRequest.Types.DataItem() { Value = "" + item.Value.Value.ToString() + "" });
  146. }
  147. var accessToken = await GetCgibinToken();
  148. var reqMessage = new CgibinMessageTemplateSendRequest()
  149. {
  150. AccessToken = accessToken,
  151. TemplateId = input.TemplateId,
  152. ToUserOpenId = input.ToUserOpenId,
  153. Url = input.Url,
  154. MiniProgram = new CgibinMessageTemplateSendRequest.Types.MiniProgram
  155. {
  156. AppId = _wechatApiClientFactory._wechatOptions.WechatAppId,
  157. PagePath = input.MiniProgramPagePath,
  158. },
  159. Data = messageData
  160. };
  161. var resMessage = await _wechatApiClient.ExecuteCgibinMessageTemplateSendAsync(reqMessage);
  162. return resMessage;
  163. }
  164. /// <summary>
  165. /// 删除模板 🔖
  166. /// </summary>
  167. /// <param name="input"></param>
  168. /// <returns></returns>
  169. [ApiDescriptionSettings(Name = "DeleteMessageTemplate"), HttpPost]
  170. [DisplayName("删除模板")]
  171. public async Task<dynamic> DeleteMessageTemplate(DeleteMessageTemplateInput input)
  172. {
  173. var accessToken = await GetCgibinToken();
  174. var reqMessage = new CgibinTemplateDeletePrivateTemplateRequest()
  175. {
  176. AccessToken = accessToken,
  177. TemplateId = input.TemplateId
  178. };
  179. var resTemplate = await _wechatApiClient.ExecuteCgibinTemplateDeletePrivateTemplateAsync(reqMessage);
  180. return resTemplate;
  181. }
  182. /// <summary>
  183. /// 获取Access_token
  184. /// </summary>
  185. private async Task<string> GetCgibinToken()
  186. {
  187. var reqCgibinToken = new CgibinTokenRequest();
  188. var resCgibinToken = await _wechatApiClient.ExecuteCgibinTokenAsync(reqCgibinToken);
  189. if (resCgibinToken.ErrorCode != (int)WechatReturnCodeEnum.请求成功)
  190. throw Oops.Oh(resCgibinToken.ErrorMessage + " " + resCgibinToken.ErrorCode);
  191. return resCgibinToken.AccessToken;
  192. }
  193. }