Java微信公众号开发之网页授权获取用户基本信息

时间:2024-03-19 14:33:30

 前言

微信公众号开发,需要用到网页授权获取用户信息,通过OAuth2.0网页授权机制,来获取用户基本信息,进而实现自己的业务逻辑。 (前提条件:公众号为服务号,且通过认证),我的项目开发就是已认证的服务号,写这篇文章的目的是因为刚接触微信开发的小白对微信授权的文档很模糊,你只要按照我下面提供的授权接口完整走一遍你就明白了授权的4个步骤

微信网页授权api接口说明:https://mp.weixin.qq.com/wiki/4/9ac2e7b1f1d22e9e57260f6553822520.html

一、网页授权前基本配置

    1、内网穿透

       做微信开发的应该都知道,微信开发调试需要把本地127.0.0.1通过内网穿透,映射到外网中去,这样才可以正常的通过外网与腾讯的微信服务器进行通讯,开发调试;关于内网穿透的工具有很多,详细可以查看:可以实现内网穿透的几款工具,我个人比较推荐Natapp,我使用的是Natapp,Natapp官网地址:https://natapp.cn/  ,Natapp内网穿透开启成功后如下图:

   Java微信公众号开发之网页授权获取用户基本信息

     2、设置授权网页回调域名

      在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发—— 接口权限——网页服务——网页授权——点击修改——功能设置——网页授权域名——点击设置按钮”,填写授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头; 

   Java微信公众号开发之网页授权获取用户基本信息
 

     3、注意填写域名规范

        授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权

Java微信公众号开发之网页授权获取用户基本信息
 

    4. 设置授权文件

  在上一步填写完域名后,注意很重要的一步:将以下文件上传至填写域名或路径指向的web服务器(或虚拟主机)的目录(若填写域名,将文件放置在域名根目录下,例如wx.qq.com/MP_verify_x6qyHYovfWrZHcfo.txt;若填写路径,将文件放置在路径目录下,例如wx.qq.com/mp/MP_verify_x6qyHYovfWrZHcfo.txt),并确保可以访问。这里我放置所部属项目的Tomcat服务器的webapp下面的Root目录下面,如果放置位置不正确或者跳过此不,点击保存按钮会无法通过,切记;

Java微信公众号开发之网页授权获取用户基本信息

二、关于网页授权的两种scope的区别说明 

   1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页  的。用户感知的就是直接进入了回调页(往往是业务页面) 
   2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权会产生一个授权页面,需要用户手动同意,在用户同意后,就可以通过获取用户基本信息的接口获取该用户的基本信息。 如用户的openid,昵称,性别,头像,所在地等。

我们需要获取用户信息,这里选择以snsapi_userinfo为scope发起的网页授权

三、网页授权流程分为四步

   1、引导用户进入授权页面或打开授权链接同意授权,获取code 
   2、通过code换取网页授权access_token(与基础支持中的access_token不同) 
   3、如果需要,开发者可以刷新网页授权access_token,避免过期 
   4、通过网页授权access_token和openid获取用户基本信息
    以上4步,请详细阅读:微信网页授权官方文档,这里你不在累赘

四、开发网页授权接口

  1. 引入微信SDK依赖 

<!-- 微信框架 参考:https://github.com/Wechat-Group/weixin-java-tools -->
      <dependency>
         <groupId>com.github.binarywang</groupId>
         <artifactId>weixin-java-mp</artifactId>
         <version>3.0.0</version>
      </dependency>

 2. 新建WxMpOAuthController

   网页授权接口代码

/**
 * @ClassName: WxMpOAuthController
 * @Description: 微信网页授权
 * @author cao_wencao
 * @date 2018年7月4日 下午1:27:58
 */
@RestController
@RequestMapping("/wechat/oauth")
public class WxMpOAuthController extends BaseController {

    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private FollowService followService;

    @GetMapping("/oauthInfo")
    public void authorize(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String backUrl = request.getParameter("backUrl");
        backUrl = URLEncoder.encode(backUrl, "UTF-8");
        String host = request.getRequestURL().toString();

        host = host.replaceAll("/oauthInfo", "/getInfo") + "?backUrl=" + backUrl;
        // String redirect_uri = URLEncoder.encode(host, "UTF-8");
        // 构建授权URL,方法内会自动encode
        String redirectUri = wxMpService.oauth2buildAuthorizationUrl(host, WxConsts.OAuth2Scope.SNSAPI_USERINFO, "1");
        logger.info("redirectUri地址={}", redirectUri);// 日志
        response.sendRedirect(redirectUri);
    }

    @GetMapping("/getInfo")
    public void getInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String backUrl = "";
        String code = request.getParameter("code");
        backUrl = request.getParameter("backUrl");
        backUrl = URLDecoder.decode(backUrl, "UTF-8");

        // 通过code换取access token
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
        String openId = null;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
            // 获取openId
            openId = wxMpOAuth2AccessToken.getOpenId();
            logger.info("openId={}", openId);
            // 通过access_token和openid拉取用户
            String lang = "zh_CN";
            WxMpUser wxMpUser = this.wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, lang);
            // TODO 操作保存用户信息到数据库
            Follow follow = followService.findFollowByOpenId(openId);
            if (null == follow && null != wxMpUser) {
                // 保存授权拿到的用户信息
                followService.saveOauthFollowInfo(wxMpUser);
            }

            logger.info("网页授权获取用户信息 :" + wxMpUser.toString());

            Map<String, Object> params = HttpTools.getUrlParamMap(HttpTools.getUrlParam(backUrl));
            params.put("curoauth", openId); // 重新组装参数
            String baseUrl = HttpTools.getUrlBase(backUrl);
            backUrl = baseUrl + "?" + HttpTools.getUrlParamsByMap(params);
            logger.info("链接微信授权成功 结束======" + backUrl);
        }
        catch (WxErrorException e) {
            logger.error("【微信网页授权】{}", e.getMessage());
            throw new RuntimeException("网页授权失败!");
        }
        response.sendRedirect(backUrl);
    }
}

 3. 新建TestController,来测试网页授权

(1)、网页授权TestController代码

import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.google.common.collect.Maps;

@Controller("mobile/TestController")
@RequestMapping(value = "/mobile/test")
public class TestController extends BaseController {

    @Autowired
    private WxMpService wxMpService;
	

	
    @RequestMapping(value = {"/testOauth"})
    public String testOauth(HttpServletRequest request, HttpServletResponse response, Model model) {
	    String openid = (String) request.getSession().getAttribute("openid");
	    model.addAttribute("openid", openid);
        return "mobile/modules/app/testOauth";
    }
	

	
}

(2)、新建一个测试的jsp, testOauth.jsp,供后端testOauth方法跳转

<%@ page contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>测试授权</title>
<script>
    		function aa(){	
    			var openid =  GetUrlParam('curoauth');
    			if(openid != ""){
    				alert(openid);
    				return ;
    			}
    				   				    				
    				alert('我要授权');
    			
				var backUrl = window.location.href;
				   alert(backUrl);
				//跳转至授权页面
				window.location.href ="http://mywx.tunnel.qydev.com/greenwx/wechat/oauth/oauthInfo"+"?backUrl="+backUrl;
				alert('授权完啦' + ${openid});
			}
    		
    		
    		
    		function GetUrlParam(paraName) {
    		    var url = document.location.toString();
    		    var arrObj = url.split("?");

    		    if (arrObj.length > 1) {
    		      var arrPara = arrObj[1].split("&");
    		      var arr;

    		      for (var i = 0; i < arrPara.length; i++) {
    		        arr = arrPara[i].split("=");

    		        if (arr != null && arr[0] == paraName) {
    		          return arr[1];
    		        }
    		      }
    		      return "";
    		    }
    		    else {
    		      return "";
    		    }
    		  }
 		
    		
    		//aa();
		
    		
    </script>

</head>
<body>
	<div class="wrap">
		<div class="header">
			<a>
				<i class="icon-chevron-left"></i>
			</a>
			<h3>标题</h3>
			<a></a>
		</div>
		<div class="box bg-grey">
			<div class="content">
<%-- 			<h5>粉丝 openid :${openid}</h5> <br> --%>
			openid :  <input  type="text" name="openid"   value="${openid}" />
			</div>
			
			
		</div>
	</div>
</body>
</html>

(3)、测试网页授权

        我的项目名叫greenwx,内网穿透域名是thinkingcao.natapp1.cc,所以,这里访问地址是:http://thinkingcao.natapp1.cc/greenwx//mobile/test/testOauth,启动项目,在你的公众号中访问controller的这个地址(http://thinkingcao.natapp1.cc/greenwx//mobile/test/testOauth)当你在公众号中点击这个地址时,jsp中的js代码就会触发网页授权操作,就会弹出网页授权界面,这时候结合公众号就可以看到网页授权获取的用户信息了,这时网页授权获取用户信息就成功了;