using System; using Microsoft.AspNetCore.Mvc; using System.Text; using System.Threading.Tasks; using CoreCms.Net.Configuration; using CoreCms.Net.Caching.AccressToken; using CoreCms.Net.IServices; using CoreCms.Net.Loging; using CoreCms.Net.Model.Entities; using CoreCms.Net.WeChat.Service.HttpClients; using CoreCms.Net.WeChat.Service.Enums; using CoreCms.Net.WeChat.Service.Models; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using SKIT.FlurlHttpClient.Wechat.Api.Models; using SKIT.FlurlHttpClient.Wechat.Api; using LogLevel = NLog.LogLevel; namespace CoreCms.Net.Web.Controllers.WeChat { /// /// 微信公众号用户授权事件 /// public class WeChatOffiaccountOAuth2Controller : ControllerBase { //private readonly string _weChatAppId = AppSettingsConstVars.WeiXinAppId; //private readonly string _weChatSecret = AppSettingsConstVars.WeiXinAppSecret; //private readonly string _weChatOAuth2CallBackUrl = AppSettingsConstVars.AppConfigAppInterFaceUrl + "/WeCharOAuth2/UserInfoCallback"; private readonly IWeChatApiHttpClientFactory _weChatApiHttpClientFactory; private readonly IWeChatUserAccessTokenServices _weChatUserAccessTokenServices; private readonly ICoreCmsUserWeChatInfoServices _weChatUserInfoServices; /// /// 构造函数 /// public WeChatOffiaccountOAuth2Controller(IWeChatApiHttpClientFactory weChatApiHttpClientFactory, IWeChatUserAccessTokenServices weChatUserAccessTokenServices, ICoreCmsUserWeChatInfoServices weChatUserInfoServices) { _weChatApiHttpClientFactory = weChatApiHttpClientFactory; _weChatUserAccessTokenServices = weChatUserAccessTokenServices; _weChatUserInfoServices = weChatUserInfoServices; } /// /// OAuthScope.snsapi_userinfo方式回调 /// /// /// /// /// [HttpGet] public async Task UserInfoCallback(string code, string state, string bkUrl) { if (string.IsNullOrEmpty(code)) { return Content("您拒绝了授权!"); } //if (!state.Contains(",")) //{ // //这里的state其实是会暴露给客户端的,验证能力很弱,这里只是演示一下 // //实际上可以存任何想传递的数据,比如用户ID,并且需要结合例如下面的Session["OAuthAccessToken"]进行验证 // return Content("验证失败!请从正规途径进入!"); //} var client = _weChatApiHttpClientFactory.CreateWeXinClient(); var accessToken = WeChatCacheAccessTokenHelper.GetWeChatAccessToken(); var request = new SnsOAuth2AccessTokenRequest() { AccessToken = accessToken, Code = code }; var response = await client.ExecuteSnsOAuth2AccessTokenAsync(request, HttpContext.RequestAborted); if (response.ErrorCode != (int)WeChatReturnCode.ReturnCode.请求成功) { return Content("错误:" + response.ErrorMessage); } NLogUtil.WriteFileLog(LogLevel.Info, LogType.WeChat, "获取用户accessToken", JsonConvert.SerializeObject(response)); var accessTokenModel = await _weChatUserAccessTokenServices.QueryByClauseAsync(p => p.openid == response.OpenId); if (accessTokenModel == null) { accessTokenModel = new WeChatUserAccessToken(); accessTokenModel.access_token = response.AccessToken; accessTokenModel.expires_in = response.ExpiresIn; accessTokenModel.openid = response.OpenId; accessTokenModel.refresh_token = response.RefreshToken; accessTokenModel.scope = response.Scope; accessTokenModel.unionid = response.UnionId; accessTokenModel.refresh_DateTime = DateTime.Now.AddSeconds(response.ExpiresIn); await _weChatUserAccessTokenServices.InsertAsync(accessTokenModel); } else { accessTokenModel.access_token = response.AccessToken; accessTokenModel.expires_in = response.ExpiresIn; //accessTokenModel.openid = response.OpenId; accessTokenModel.refresh_token = response.RefreshToken; accessTokenModel.scope = response.Scope; accessTokenModel.unionid = response.UnionId; accessTokenModel.refresh_DateTime = DateTime.Now.AddSeconds(response.ExpiresIn); await _weChatUserAccessTokenServices.UpdateAsync(accessTokenModel); } //因为第一步选择的是OAuthScope.snsapi_userinfo,这里可以进一步获取用户详细信息 try { var userInfoRequest = new SnsUserInfoRequest() { AccessToken = response.AccessToken, OpenId = response.OpenId }; var userInfoResponse = await client.ExecuteSnsUserInfoAsync(userInfoRequest, HttpContext.RequestAborted); if (userInfoResponse.ErrorCode == (int)WeChatReturnCode.ReturnCode.请求成功) { var weChatUserInfo = await _weChatUserInfoServices.QueryByClauseAsync(p => p.openid == response.OpenId); if (weChatUserInfo == null) { weChatUserInfo = new CoreCmsUserWeChatInfo() { createTime = DateTime.Now, type = (int)GlobalEnumVars.UserAccountTypes.微信公众号, //city = userInfoResponse.City, //country = userInfoResponse.Country, //province = userInfoResponse.Province, nickName = userInfoResponse.Nickname, //gender = userInfoResponse.Sex, avatar = userInfoResponse.HeadImageUrl, unionId = userInfoResponse.UnionId, openid = userInfoResponse.OpenId, gender = 1, //isSubscribe = userInfoResponse.PrivilegeList, }; var id = await _weChatUserInfoServices.InsertAsync(weChatUserInfo); if (id > 0) { await _weChatUserInfoServices.UpdateAsync( p => new CoreCmsUserWeChatInfo() { userId = id }, p => p.id == id); } } else { if (weChatUserInfo.nickName != userInfoResponse.Nickname || weChatUserInfo.avatar != userInfoResponse.HeadImageUrl || weChatUserInfo.unionId != userInfoResponse.UnionId) { weChatUserInfo.nickName = userInfoResponse.Nickname; weChatUserInfo.avatar = userInfoResponse.HeadImageUrl; weChatUserInfo.unionId = userInfoResponse.UnionId; await _weChatUserInfoServices.UpdateAsync(weChatUserInfo); } } } else { return Content("错误:" + response.ErrorMessage); } var option = new CookieOptions { Expires = DateTime.Now.AddSeconds(1440) }; Response.Cookies.Append(GlobalConstVars.CookieOpenId, userInfoResponse.OpenId, option); if (!string.IsNullOrEmpty(bkUrl)) { var outBase64String = Convert.FromBase64String(bkUrl); var orgStr = Encoding.Default.GetString(outBase64String); return Redirect(orgStr); } else { return Redirect(AppSettingsConstVars.AppConfigAppH5Url); } } catch (Exception ex) { return Content(ex.Message); } } } }