您的位置:首页 > 移动开发 > 微信开发

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

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

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



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



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



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

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

访问首页授权
访问指定接口授权
这里以指定接口授权作为演示, 同时通过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值:

snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)
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 数据.

openid 为当前用户对当前公众号关联应用唯一识别码.
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐