在开发微信应用的时候, 我们往往需要确认用户的身份, 一般公众号唯一区别用户的身份是 openid 信息, 但是这个信息并不是可以直接获取到, 需要通过 code 进行获取, 而 code 的获取则需要用户进行一个授权的处理才能获得, 本篇随笔通过结合 Session 的方式, 自动判断用户状态, 如果用户首次访问页面, 则以重定向的方式实现用户身份信息的获取并转回原来页面.
1, 常规的页面身份获取处理
之前为了在某个页面里面获取用户身份信息, 需要把 URL 进行一个授权的处理 URL, 如下所示.
通过这样的方式处理, 我们可以在页面处理里面, 获得 code 参数, 然后根据 code 参数获取 openid.
- string code = Request.QueryString["code"];
- var result = baseApi.GetAuthToken(accountInfo.AppID, accountInfo.AppSecret, code);
- if (result != null && !string.IsNullOrEmpty(result.openid))
- {
- Session["openid"] = result.openid;// 存储在 Session
- }
其中 GetAuthToken 是我们根据微信 API 进行封装的一个通过 code 换取网页授权 access_token 的接口方法.
- /// <summary>
- /// 通过 code 换取网页授权 access_token
- /// 首先请注意, 这里通过 code 换取的是一个特殊的网页授权 access_token, 与基础支持中的 access_token(该 access_token 用于调用其他接口) 不同.
- /// 公众号可通过下述接口来获取网页授权 access_token.
- /// 如果网页授权的作用域为 snsapi_base, 则本步骤中获取到网页授权 access_token 的同时, 也获取到了 openid,snsapi_base 式的网页授权流程即到此为止.
- /// </summary>
- /// <param name="appId"> 公众号的唯一标识 </param>
- /// <param name="appSecret"> 公众号的 appsecret</param>
- /// <param name="code">code 作为换取 access_token 的票据, 每次用户授权带上的 code 将不一样, code 只能使用一次, 5 分钟未被使用自动过期.</param>
- /// <param name="grantType"> 填写为 authorization_code</param>
- /// <returns></returns>
- public AccessTokenResult GetAuthToken(string appId, string appSecret, string code, string grantType = "authorization_code")
- {
- var key = code + "_AuthToken";
- AccessTokenResult itemResult = MemoryCacheHelper.GetItem<AccessTokenResult>(key);
- if (itemResult == null)
- {
- var url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type={3}",
- appId, appSecret, code, grantType);
- var authToken = WeJsonHelper<AccessTokenResult>.ConvertJson(url);
- MemoryCacheHelper.AddItem(key, authToken);// 先加入一个获取的值
- }
- // 然后每次从其中取, 如果超过时间则启用刷新机制
- var access_token = MemoryCacheHelper.GetCacheItem<AccessTokenResult>(key, delegate()
- {
- return RefreshAuthToken(appId, itemResult.access_token);
- },
- new TimeSpan(0, 0, 7000)//7000 秒过期
- );
- return access_token;
- }
这种方式能够正常获取 openid, 不过每个菜单这样进行 URL 处理, 并且每次重复这样的逻辑获取 openid, 肯定不是什么好的办法.
因此考虑一种通用的方式来处理, 以减少这些曲折处理过程.
2, 通用函数处理, 以重定向的方式实现用户身份信息
上面提出了, 采用常规处理方式, 菜单 URL 需要先转移, 后台重复处理 code 的转换, 非常不方便我们开发业务功能.
其实我们可以把以上获取用户身份的处理放置在一个通用函数里面, 这样每次确保获得 Openid 即可, 如果第一次访问页面, 那么记录当前页面地址, 并重定向到获取 code 的页面, 并解析 code 为 openid 即可, 然后放在 Session 里面存储起来, 下次直接读取 Session 获取即可.
我们首先在入口页面里面记录当前页面地址, 然后转去判断并获取 openid 即可.
如果在 session 里面没有获取到 Openid, 那么认为是第一访问页面, 重新判断是否有 code 进来, 如果没有, 先获取 code, 然后转回到当前的 AuthOpenId 地址入口来.
- /// <summary>
- /// 通过重新转向, 获取用户 code 并转换为 openid.
- /// 用于自动获取当前用户的身份.
- /// </summary>
- /// <returns></returns>
- protected ActionResult AuthOpenId()
- {
- // 先判断 Session 是否存在
- var open_id = Session["openid"];
- if (open_id == null)
- {
- // 如果第一次 (没有 code), 则再次转到授权页面重新获取 code
- string code = Request.QueryString["code"];
- if (string.IsNullOrEmpty(code))
- {
- var authUrl = baseApi.GetAuthorizeUrl(accountInfo.AppID, Request.Url.AbsoluteUri, "", OAuthScope.snsapi_base);
- Response.Redirect(authUrl);
- return null;
- }
如果是已经获取到了 code, 则根据 code 进行解析获取 openid, 如下代码所示.
- else
- {
- // 如果成功获取 code, 那么根据 code 获取 openid
- var result = baseApi.GetAuthToken(accountInfo.AppID, accountInfo.AppSecret, code);
- if (result != null && !string.IsNullOrEmpty(result.openid))
- {
- //LogHelper.Info("openid:" + result.openid);
- Session["openid"] = result.openid;// 存储在 Session
- }
- }
最后如果顺利获得 openid, 那么返回到最初入口的页面地址 (已经存放地址在 Session 里面了)
- // 获取返回的连接
- var backUrl = Session["back_url"];
- if (backUrl != null)
- {
- return Redirect(backUrl.ToString());
- }
- else
- {
- return View("PersonalInfo");// 返回个人页面
- }
整个函数的完整的代码如下所示.
- /// <summary>
- /// 通过重新转向, 获取用户 code 并转换为 openid.
- /// 用于自动获取当前用户的身份.
- /// </summary>
- /// <returns></returns>
- protected ActionResult AuthOpenId()
- {
- // 先判断 Session 是否存在
- var open_id = Session["openid"];
- if (open_id == null)
- {
- // 如果第一次 (没有 code), 则再次转到授权页面重新获取 code
- string code = Request.QueryString["code"];
- if (string.IsNullOrEmpty(code))
- {
- var authUrl = baseApi.GetAuthorizeUrl(accountInfo.AppID, Request.Url.AbsoluteUri, "", OAuthScope.snsapi_base);
- Response.Redirect(authUrl);
- return null;
- }
- else
- {
- // 如果成功获取 code, 那么根据 code 获取 openid
- var result = baseApi.GetAuthToken(accountInfo.AppID, accountInfo.AppSecret, code);
- if (result != null && !string.IsNullOrEmpty(result.openid))
- {
- Session["openid"] = result.openid;// 存储在 Session
- }
- }
- }
- // 获取返回的连接
- var backUrl = Session["back_url"];
- if (backUrl != null)
- {
- return Redirect(backUrl.ToString());
- }
- else
- {
- return View("PersonalInfo");// 返回个人页面
- }
- }
这样我们在菜单里面, 就不需要前面所说的转义函数处理了, 所有的身份获取都通过标准操作确保获取用户的 openid 了.
页面的处理也变得相对容易一些, 根据用户身份显示不同的视图页面.
- /// <summary>
- /// 患者问诊
- /// </summary>
- /// <returns></returns>
- public ActionResult DrugInquiry()
- {
- Session["back_url"] = Request.Url.AbsoluteUri;
- AuthOpenId();// 自动获取当前用户的身份.
- string openid = (string)Session["openid"];
- if (!string.IsNullOrEmpty(openid))
- {
- // 刷新配置 JS 的参数
- RefreshTicket();
- ViewBag.openid = openid;
- var userInfo = BLLFactory<User>.Instance.FindByOpenId(openid);
- if (userInfo != null)
- {
- // 识别用户身份后的处理逻辑
- ...............
- }
- return View("DrugInquiry");
- }
- else
- {
- ViewBag.Title = "无法获取用户身份信息";
- ViewBag.Message = "无法获取用户身份信息";
- ViewBag.Type = "error";
- return View("info");
- }
- }
以上就是微信开发中使用通用函数处理, 以重定向的方式实现用户身份信息的获取并转回原来页面的做法, 这个函数给我们减轻了很多繁琐的问题, 并且减少了重复来获取用户身份的弊端, 是我们在 H5 页面里面处理用户身份信息的利器, 希望对大家在开发微信公众号或者企业微信, 获取用户身份的时候, 提供好的参考思路和代码.
来源: https://www.cnblogs.com/wuhuacong/p/11693007.html