微信授权登录

551 阅读2分钟

官方文档

准备工作

公众号配置

  • 生产环境配置:
  • 网页授权域名 登录微信公众平台进入“公众号设置”的功能设置里填写“网页授权域名” -测试环境配置
  • 登录微信公众平台进入“开发”——“开发者工具”的“公众平台测试账号” 扫码登录进入如下页面 -此处的URL是必填,需要验证并获取token的,示例代码:
  • 控制层
@GetMapping(value = "/checkWxToken")
    @AnonymousAccess
    public ResponseEntity checkToken(HttpServletRequest request,HttpServletResponse response) throws IOException{
        return new ResponseEntity(WxPayUtil.checkWx(request,response),HttpStatus.OK);
    }
  • 业务层
/**
 * 检测微信测试账号接口配置信息
 * @param request
 * @param response
 * @return
 */
public static String checkWx(HttpServletRequest request, HttpServletResponse response){
    String signature = request.getParameter("signature");
    String timestamp = request.getParameter("timestamp");
    String nonce = request.getParameter("nonce");
    String echostr = request.getParameter("echostr");
    //放入数组,进行字典排序后组成一个字符串。
    String[] arr = new String[]{TOKEN, timestamp, nonce};
    Arrays.sort(arr);
    String str = arr[0] + arr[1] + arr[2];
    String resultMsg = DigestUtils.sha1Hex(str);
    if (!resultMsg.equals(signature)) {
        return "";
    }
    return echostr;
}

DigestUtils的使用需要引入pom依赖:

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>

开发步骤

微信授权步骤

-

  • 第一步:用户访问引导页面后会以GET方式请求到“REDIRECT_URI”对应的后端接口,此时会传递参数名为“code”的参数
  • 第二步:后台接收到“code”后根据开放文档给定的链接换区access_token,链接地址:api.weixin.qq.com/sns/oauth2/…
  • 第三步:刷新access_token(如果需要)

由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。

请求方法

获取第二步的refresh_token后,请求以下链接获取access_token:api.weixin.qq.com/sns/oauth2/…

  • 第四步:拉取用户信息(需scope为 snsapi_userinfo)

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

请求方法

http:GET(请使用https协议) api.weixin.qq.com/sns/userinf… 实际开发:

  • 在实际开发中,如果不需要第三部刷新access_token,开发步骤为:第一步用户访问引导链接后,请求后台接口,业务层将第二步第四步依次处理,即可获取微信返回的用户信息

demo示例:

  • 前端:
$(document).ready(function() {
	wxLogin()
})


function wxLogin() {
	var appId = 'APPID'
	var encodeURI = encodeURIComponent('http://xxx.xx.xxx/api/wxlogin/login')
	window.location = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodeURI + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
}
  • 后端: pom.xml中引入hutool工具类
<!-- hutool -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.3.10</version>
</dependency>

<!-- fastjson -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.54</version>
</dependency>
  • 控制层:
@Log("微信授权登录")
    @ApiOperation("微信授权登录")
    @GetMapping(value = "/login")
    @AnonymousAccess
    public void weAppLogin(String code,HttpServletResponse response) throws Exception {
        String redirectUrl = wxLoginService.saveWxUserInfoFromWx(code);
        response.sendRedirect(redirectUrl);
    }

其中的response.sendRedirect(redirectUrl);此处是后台跳转到其他页面

  • 业务层:
WxUserInfo wxUserInfo = WxPayUtil.getWxInfoByCodeAndToken(WxPayUtil.getOpenIdByCode(code));
        log.info("微信返回的用户信息:"+wxUserInfo.toString());

WxPayUtil:

/**
 * 通过code换取网页授权access_token
 * @param code
 * @return
 */
public static AccessToken getOpenIdByCode(String code) {
        log.info(code);
        AccessToken accessToken = new AccessToken();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid", APP_ID);
        paramMap.put("secret", APP_SECRET);
        paramMap.put("code", code);
        paramMap.put("grant_type", "authorization_code");
        String response = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token", paramMap);
        JSONObject jsonObject = JSON.parseObject(response);
        log.info(response);
        accessToken.setAccessToken(jsonObject.getString("access_token"));
        accessToken.setOpenid(jsonObject.getString("openid"));
        return accessToken;
    }
    
 /**
 * 拉取用户信息(需scope为 snsapi_userinfo)
 * @param accessToken
 * @return
 * @throws Exception
 */    
public static WxUserInfo getWxInfoByCodeAndToken(AccessToken accessToken) throws Exception{
        WxUserInfo userInfo = new WxUserInfo();
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("access_token",accessToken.getAccessToken());
        paramMap.put("openid",accessToken.getOpenid());
        paramMap.put("lang","zh_CN");
        String response = HttpUtil.get(" https://api.weixin.qq.com/sns/userinfo",paramMap);
        JSONObject jsonObject = JSON.parseObject(response);
        userInfo.setOpenid(jsonObject.getString("openid"));
        userInfo.setNickname(jsonObject.getString("nickname"));
        userInfo.setSex(jsonObject.getString("sex"));
        userInfo.setProvince(jsonObject.getString("province"));
        userInfo.setCity(jsonObject.getString("city"));
        userInfo.setCountry(jsonObject.getString("country"));
        userInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
        return userInfo;
    }

以上即可完成基本的微信授权登录