/// <summary> /// 第三方平台运营时,授权完成时的回调页面 /// 授权流程完成后,会进入回调URI,并在URL参数中返回授权码和过期时间(redirect_url?auth_code=xxx&expires_in=600) /// 一个公众号不能同时授权给两个帐户,因为微信在推送数据时只带一个APPID,我无法判断其属于哪个Domain /// 但是允许其在解除授权后得新授权给另一个帐户 /// </summary> /// <returns></returns> public ActionResult AuthorizationCallback(string auth_code) { //防止由于用户长时间停留在微信页面,回来时超时 DomainContext 为空 //会直接返回到登录页面 //引处得到授权码,根据授权码获取授权公众号的令牌 //然后获取其详细信息 //开始运行此公众号 ApiResult <CreateAuthorizerResult> result = ThirdPartyAccessTokenGetter.CreateAuthorizer(DomainContext.Domain.Id, auth_code); if (result.Success == false) { _logService.Write("授权回调时创建公众号授权信息失败", result.Message, TraceEventType.Error); //TODO:创建公众号授权信息失败 return(new HttpStatusCodeResult(500)); } //更新公众号帐户详细信息 _thirdPartyManager.UpdateAuthorizerAccountInfo(DomainContext.Domain.Id, result.Data.AppId); //立即获取帐户信息和配置信息 DomainContext.Refresh(); return(RedirectToAction("Docking")); }
public ActionResult GetPreAuthCode() { RequestApiResult <WeixinThirdPartyGetPreAuthCodeResult> result = ThirdPartyApi.GetPreAuthCode(ThirdPartyAccessTokenGetter.Get(), _configuration.ThirdParty.AppId); if (result.Success) { return(RespondDataResult(new { AppId = _configuration.ThirdParty.AppId, PreAuthCode = result.ApiResult.PreAuthCode })); } else { ApiResult apiResult = new ApiResult(); apiResult.Message = result.Message; return(RespondResult(apiResult)); } }
/// <summary> ///微信网页授权回调 ///如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。 ///若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE ///http://mp.weixin.qq.com/wiki/9/01f711493b5a02f24b04365ac5d8fd95.html /// </summary> /// <returns></returns> public ActionResult OAuthCallback() { _log.Write("微信网页授权接口发起回调", HttpContext.Request.Url.ToString(), TraceEventType.Verbose); string code = HttpContext.Request.QueryString["code"]; string state = HttpContext.Request.QueryString["state"]; //第为第三方平台运营时,会返回 appId string appId = HttpContext.Request.QueryString["appid"]; //完成网页鉴权后要转回的页面地址 string redirectUrl = null; if (String.IsNullOrEmpty(state) == false) { redirectUrl = _cachingService.Get(state); } else { _log.Write("微信网页授权接口发起回调", "没有指定完成网页鉴权后要转回的页面地址: state" + HttpContext.Request.Url.ToString(), TraceEventType.Warning); return(new HttpStatusCodeResult(404)); } string domainId = HttpContext.Request.QueryString["domainId"]; if (String.IsNullOrEmpty(domainId)) { _log.Write("微信网页授权接口发起回调", "没有指定 domainId ", TraceEventType.Warning); return(new HttpStatusCodeResult(404)); } DomainContext domainContext = _domainPool.GetDomainContext(Guid.Parse(domainId)); if (domainContext == null) { _log.Write("微信网页授权接口发起回调", "指定的 domainId 不存在", TraceEventType.Warning); return(new HttpStatusCodeResult(404)); } if (domainContext.Authorizer == null) { //重定向到错误页面 return(new RedirectResult(String.Format( "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td5"))); } //只有微信认证服务号具备此权限 //用户管理-网页授权获取用户openid/用户基本信息 if (domainContext.Authorizer.AuthorizationType != EnumAuthorizationType.AuthorizedService) { //重定向到错误页面 return(new RedirectResult(String.Format( "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td4"))); } if (String.IsNullOrEmpty(code)) { //重定向到错误页面 return(new RedirectResult(String.Format( "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td1"))); } /* * 此处偶发 40029 错误,不合法的oauth_code * 40029-invalid code, hints: [ req_id: Ft6quA0644ns67 ] * https://segmentfault.com/q/1010000002739502?foxhandler=RssReadRenderProcessHandler * http://mp.weixin.qq.com/qa/11/3c20059cc944d6edf4a1124c2fd09253.html * redirect_uri后面加个随机数没用 * 通过尝试发起两次请求的方式解决 */ //通过code换取网页access_token RequestApiResult <WeixinWebAccessTokenResult> getWebAccessToken = TokenApi.GetThirdPartyWebAccessToken(domainContext.AppId, code, _configuration.ThirdParty.AppId, ThirdPartyAccessTokenGetter.Get()); if (getWebAccessToken.Success == false) { //再来一次,防止死循环,只重试一次,在URL后面加个参数以标记 if (redirectUrl.Contains("RetryGetWebAccessToken")) { _log.Write("请求网页AccessToken失败。", getWebAccessToken.Message, TraceEventType.Warning); //重定向到错误页面 return(new RedirectResult(String.Format( "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td2"))); } else { if (redirectUrl.IndexOf('?') >= 0) { redirectUrl += "&RetryGetWebAccessToken=1"; } else { redirectUrl += "?RetryGetWebAccessToken=1"; } return(new RedirectResult(redirectUrl)); } } //将OpenId保存到Session SessionContainer.SetOpenId(HttpContext, getWebAccessToken.ApiResult.OpenId); //先判断本地数据库中是否已经有了此用户信息 MemberContext memberContext = null; MemberEntity member = _memberManager.GetMemberByOpenId(domainContext.Domain.Id, domainContext.AppId, getWebAccessToken.ApiResult.OpenId); if (member != null) { if (member.Attention) { //为提高鉴权性能,此处不更新用户信息,只作标记,用windows服务后台更新 _memberManager.NeedUpdate(member.Id, true); memberContext = new MemberContext(member); SessionContainer.SetMemberContext(HttpContext, memberContext); //转回初始业务页面 return(new RedirectResult(redirectUrl)); } else { //如果用户已经取消关注,此处就不需要再调用微信的 GetUserInfo 接口了 //直接判断能不能匿名浏览即可 return(RedirectUrlOnlyOpenId(redirectUrl, domainId)); } } //在本地没有用户信息的情况下,调用weixinApi去取 //此处拿到OpenId了,接下来判断该用户是否是已关注用户 RequestApiResult <WeixinUser> getUserInfoResult = UserApiWrapper.GetUserInfo(domainContext, getWebAccessToken.ApiResult.OpenId); if (getUserInfoResult.Success == false) { //重定向到错误页面 return(new RedirectResult(String.Format( "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td3"))); } //值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 //跳转到引导关注页面 if (getUserInfoResult.ApiResult.Subscribe == 0) { //用户取消关注有消息推送 //在那时设置member中是否在关注为false return(RedirectUrlOnlyOpenId(redirectUrl, domainId)); } else { //根据OpenId获取用户信息 //添加新用户 AddMemberArgs args = new AddMemberArgs(); args.WeixinUser = getUserInfoResult.ApiResult; member = _memberManager.AddMember(domainContext, args); memberContext = new MemberContext(member); SessionContainer.SetMemberContext(HttpContext, memberContext); //转回初始业务页面 return(new RedirectResult(redirectUrl)); } }