简单三步获取微信公众号用户授权

    之前做过几次微信公众号开发, 一直没有记录下开发过程, 为方便以后不用在去各种搜索找资料, 在此记录开发流程...


    首先, 开通微信公众号, 电梯直达(公众号申请). 


第二步, 绑定开发者权限, 方便使用开发者工具调试


一切准备就绪, 接下来分析微信公众号授权流程, 下图简单介绍授权序列图:



在没有弄清楚该流程之前, 我一直有个疑惑, 到底该何时提示用户授权呢? 也就是说微信服务器与我们的业务服务器在哪里作为切入点.

这里可以有两种方式提示用户授权:

  1. 访问首页授权
  2. 访问指定接口授权
这里以指定接口授权作为演示, 同时通过Spring Interceptor作为校验切入点. 为方便起见, 开发一个 LoginValidation 注解:

在需要的接口上指定 LoginValidation 注解即可, ( 在Class中注解表示该类所有接口都需要登录可以访问,  也可在指定方法中注解)

指定需要拦截的地址, 以及拦截器规则开发:
public class LoginInterceptor extends HandlerInterceptorAdapter {

    private final Logger LOGGER = LoggerFactory.getLogger(getClass());

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String path = request.getServletPath();
        HandlerMethod method = (HandlerMethod) handler;
        Method originO = method.getMethod();
        Class
     
      clazz = originO.getDeclaringClass();

        LoginValidation classAnnotation = clazz.getAnnotation(LoginValidation.class);
        LoginValidation methonAnnotation = method.getMethodAnnotation(LoginValidation.class);
        boolean needLogin = (null != methonAnnotation || null != classAnnotation);
        boolean isGuest = (null == WebUtil.getUser());

        if (needLogin && isGuest) {
            ResponseBody responseBody = ((HandlerMethod) handler).getMethodAnnotation(ResponseBody.class);

            boolean isReqData = (null != responseBody);
            if (isReqData)
                path = "/"; // 如果是数据请求, 授权后返回首页
            redirectAuth(request, response, path);
            return false;
        }

        return true;
    }

    private void redirectAuth(HttpServletRequest request, HttpServletResponse response, String path) throws Exception {
        LOGGER.info("用户未登录, 跳转到授权页面");
        boolean normalReq = !isAjaxRequest(request);
        String redirectPath = "/wx/auth";
        if (normalReq) {
            response.sendRedirect(redirectPath);
        } else {
            Map
     
     
      
       map = Maps.newHashMap();
            map.put("flag", false);
            map.put("redirect", redirectPath);
            WebUtil.writeJSON(map);
        }
        WebUtil.setSessionAttr(Constants.SESSION_WECHAT_AUTH_BEFORE_PATH, path);
    }

    public boolean isAjaxRequest(HttpServletRequest request) {
        String header = request.getHeader("X-Requested-With");
        boolean isAjax = "XMLHttpRequest".equals(header) ? true : false;
        return isAjax;
    }
}
     
     
接下来为微信服务器提供回调接口
@Controller
@RequestMapping("/wx")
public class WeChatController {
    private static final String APP_ID = "wx1xxxxxxxxxxxxxxx";
    private static final String APP_SECURITY = "aa23461daxxxxxxxxxxxxxxxxxxxxxxxxx";

    @Autowired
    private UserService userService;

    /**
     * 构建授权页面
     */
    @RequestMapping("auth")
    public String auth();

    /**
     * 微信服务器回调接口
     * @param code 用于换区access_Token, 用来获取用户数据
     * @param state 自定义数据
     */
    @RequestMapping("callback")
    public String callback(String code, String state) 

}
一切准备接续, 接下来重点关注 WeChatController, 我们先来看看 auth 这个接口的实现
@RequestMapping("auth")
public String auth() {
    // 本地开发 WebUtil.getBaseUrl() 总是为 localhost
    // String callback = URLEncoder.encode(WebUtil.getBaseUrl() + "wx/callback", "UTF-8");
    String callback = StringUtil.encodeUrl("http://df52b8f6.ngrok.io/wx/callback", "UTF-8");
    String url = WeChatUtil.createUrl(WeChatUtil.newAuthorizeParam(APP_ID, callback, WeChatUtil.Scope.SNSAPI_USERINFO, null));
    return "redirect:" + url;
}
通过 WeChatUtil.createUrl() 通过简单封装, 构建一个微信授权的重定向链接, 该链接中包含以下几部分, 

需要重点关注Scope值:
  1. snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)
  2. snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息
接下来看看 callback 的实现:
/**
 * 微信服务器回调接口
 * @param code 用于换区access_Token, 用来获取用户数据
 * @param state 自定义数据
 */
@RequestMapping("callback")
public String callback(String code, String state) {
    AccessData accessData = WeChatUtil.accessToken(WeChatUtil.newAccessParam(code, APP_ID, APP_SECURITY));
    String openId = accessData.getOpenId();
    User user = userService.getByOpenId(openId);
    if (null == user) {
        WeChatUser wxUserInfo = accessData.getUser();
        user = userService.loginByWeChat(wxUserInfo);
    }
    WebUtil.setUser(user);
    String path = WebUtil.getSessionAttr(Constants.SESSION_WECHAT_AUTH_BEFORE_PATH);
    return "redirect:" + path;
}

WeChatUtil.accessToken() 通过回调参数 code 获取 AccessData 对象, 通过该对象可以获取到 openid 和 WeChatUser 数据.

  1. openid 为当前用户对当前公众号关联应用唯一识别码.
  2. WeChatUser 为用户公开信息, 可拿到昵称、性别、所在地等信息. Scope 必须为 WeChatUtil.Scope.SNSAPI_USERINFO (也就是snsapi_userinfo)

根据具体业务使用 WeChatUser 对象即可.


三步获取用户数据总结:

第一步, 构建授权重定向地址  WeChatUtil.createUrl(WeChatUtil.newAuthorizeParam(appId, callback, WeChatUtil.Scope, state))
第二步,获取用户授权 AccessData accessData = WeChatUtil.accessToken(WeChatUtil.newAccessParam(code, appId, security));
第三步,获取用户数据 WeChatUser wxUserInfo = accessData.getUser();

WeChatUtil相关代码: https://gitee.com/osby/third/tree/master/src/main/java/org/yong/third/wx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,在获取微信公众号网页授权用户信息之前,我们需要先了解微信公众号的几个概念: 1. AppID和AppSecret:AppID是每个公众号独有的身份标识,在开发者中心中可查看;而AppSecret则是用于获取access_token的密钥。 2. 授权作用域:微信网页授权分为静默授权和弹出授权,前者只能获取用户基本信息,后者可以获取用户详细信息。 3. 网页授权流程:用户同意授权后,微信后台会将授权code返回给开发者,开发者可以使用该code获取access_token,并通过access_token获取用户信息。 接下来,我们就可以开始使用JSP获取微信公众号网页授权用户信息了。 1. 获取授权链接 首先,我们需要构造出授权链接,以便用户点击授权。 String redirect_uri = URLEncoder.encode("http://your.domain.com/callback.jsp", "UTF-8"); String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; 其中,redirect_uri是授权后重定向的回调链接地址,需要进行URLEncode编码;scope=snsapi_userinfo表示需要用户授权获取详细信息。 2. 获取授权code 当用户点击授权后,需要在回调页面(上面代码中的callback.jsp)中获取授权code。 String code = request.getParameter("code"); 3. 获取access_token 利用上一步获取授权code,构造出获取access_token的链接,并向该链接发送HTTP GET请求,获取access_token。 String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code"; URL url = new URL(tokenUrl); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.connect(); InputStream inputStream = urlConnection.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuffer stringBuffer = new StringBuffer(); while ((line = bufferedReader.readLine()) != null) { stringBuffer.append(line); } JSONObject json = new JSONObject(stringBuffer.toString()); String accessToken = json.getString("access_token"); String openid = json.getString("openid"); 4. 获取用户信息 利用获取到的access_token和openid,可以构造出获取用户信息的链接。 String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN"; URL url = new URL(userInfoUrl); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.connect(); InputStream inputStream = urlConnection.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuffer stringBuffer = new StringBuffer(); while ((line = bufferedReader.readLine()) != null) { stringBuffer.append(line); } JSONObject json = new JSONObject(stringBuffer.toString()); String nickname = json.getString("nickname"); String headimgurl = json.getString("headimgurl"); 以上就是使用JSP获取微信公众号网页授权用户信息的流程。需要注意的是,获取用户信息需要用户同意授权获取详细信息,并且在构造链接时需要进行URL编码。另外,在实际开发过程中,建议将获取access_token和获取用户信息的代码封装为工具类,以便重复使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值