第一步

  先去微信公众平台申请公众号,网址:https://mp.weixin.qq.com/,然后有了公众号申请测试号,拿到appID和appsecret

第二步

申请url和域名

微信网页授权登录(公众号)-风君雪科技博客

(1) 测试号二维码添加自己的微信号(后期使用微信web开发者工具)可以用自己微信测试,注 往下拉 :网页服务 –> 网页帐号 –> 网页授权获取用户基本信息 –> 修改   这边也需要把域名填写,和上面的域名一致。

因为微信的授权接口必须是域名不能ip,所有这边没有域名的小伙伴可以使用NATAPP

公网配置前的准备:
在我们本地测试的时候,需要将我们的本地地址映射到公网,我们使用一个免费且非常方便的工具:natapp。下面的地址是natapp的官网和natapp的使用教程:
natapp官网 :https://natapp.cn/
NATAPP 1分钟快速新手图文教程 :https://natapp.cn/article/natapp_newbie

免费隧道配置

微信网页授权登录(公众号)-风君雪科技博客
先注册,注册成功后登录。
微信网页授权登录(公众号)-风君雪科技博客

注意上图:本地端口必须是要填8080的(这个购买后也是可以再修改的),因为微信公众平台接口的调用仅支持80。开发之间建议阅读微信公众平台技术文档
隧道购买成功后,在我的隧道中就可以看到已拥有的隧道:

微信网页授权登录(公众号)-风君雪科技博客
客户端下载
我们访问到natapp的客户端下载,下载natapp客户端:
微信网页授权登录(公众号)-风君雪科技博客
下载后,解压,会有一个natapp.exe的文件。

运行natapp
在运行natapp之前需要先配置,详细教程参考:使用本地配置文件config.ini。config.ini内容:
微信网页授权登录(公众号)-风君雪科技博客
注意:config.ini配置文件需要与natapp.exe在同一个目录下。
 微信网页授权登录(公众号)-风君雪科技博客
在这两个文件的目录下,打开cmd命令窗口,输入:

natapp -authtoken=你的authtoken

回车,运行成功后是如下界面:
 微信网页授权登录(公众号)-风君雪科技博客
– Tunnel Status Online 代表链接成功
– Version 当前客户端版本,如果有新版本,会有提示
– Forwarding 当前穿透 网址 或者端口
– Web Interface 是本地Web管理界面,可在隧道配置打- 开或关闭,仅用于web开发测试
– Total Connections 总连接数
– Avg Conn Time 0.00ms 这里不代表,不代表,不代表 延时,需要注意!
 微信网页授权登录(公众号)-风君雪科技博客
这两个都是可以访问的,区别就是使用natapp是将本地映射到公网上了,别人也可以访问,但是别人就不能访问你的127.0.0.1:8080。注意:用http://xxx.natappfree.cc 访问的时候运行natapp的cmd窗口要开着,也就是得运行着natapp,不然是找不到公网映射的

(2) 申请url,有了域名以后自己写个api直接返回就可以成功了

 1     @ApiOperation(value = "微信申请URL")
 2     @GetMapping("")
 3     public void getUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
 4         log.info("WeiXinController getUrl start");
 5 
 6         Enumeration pNames = request.getParameterNames();
 7         String logName = null;
 8         while (pNames.hasMoreElements()) {
 9             String name = (String) pNames.nextElement();
10             String value = request.getParameter(name);
11             logName = "name =" + name + "     value =" + value;
12         }
13         log.info("logName: " + logName);
14 
15         // 微信加密签名
16         String signature = request.getParameter("signature");
17         // 时间戳
18         String timestamp = request.getParameter("timestamp");
19         // 随机数
20         String nonce = request.getParameter("nonce");
21         // 随机字符串
22         String echostr = request.getParameter("echostr");
23         PrintWriter out = response.getWriter();
24         out.print(echostr);
25         out.close();
26         String info = "signature = " + signature + ", timestamp = " + timestamp + ", nonce = " + nonce + ", echostr = "+ echostr;
27         log.info(info);
28 
29         log.info("WeiXinController getUrl end");
30     }

第三步

后台接口测试

第一个servlet:

@Slf4j
@WebServlet(name = "weChatLoginServlet", urlPatterns = "/wechat/login")
public class WeiXinLoginServlet extends HttpServlet {

    public WeiXinLoginServlet() {
        super();
    }

    /**
     * 微信公众号唯一标识(在微信小程序管理后台获取)
     */
    @Value("${wechat.appId}")
    private String appId;

    /**
     * 回调地址
     */
    @Value("${wechat.backUrl}")
    private String backUrl;

    /**
     * 第一步:引导用户进入授权页面同意授权,获取code
     */
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.debug("WeiXinLoginServlet doGet start");

        // 授权页面地址
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"
                + "appid=" + appId
                + "&redirect_uri=" + urlEncodeUTF8(backUrl)
                + "&response_type=code"
                + "&scope=snsapi_base"
                + "&state=STATE#wechat_redirect";

        // 重定向到授权页面
        response.sendRedirect(url);

        log.debug("WeiXinLoginServlet doGet end");
    }


    /**
     * 用 urlEncode 对链接进行处理
     *
     * @author
     * @date 2019-03-19
     */
    private String urlEncodeUTF8(String source) {
        log.debug("WeiXinLoginServlet urlEncodeUTF8 start, source = [{}]", source);

        String result = source;
        try {
            result = java.net.URLEncoder.encode(source,"utf-8");
        } catch (UnsupportedEncodingException e) {
            log.info("WeiXinController urlEncodeUTF8 BaseException: " + e.getMessage());
        }

        log.debug("WeiXinLoginServlet urlEncodeUTF8 end");
        return result;
    }
}

第二个servlet:

@Slf4j
@WebServlet(name = "weChatCallbackServlet", urlPatterns = "/wechat/callback")
public class WeiXinCallBackServlet extends HttpServlet {

    public WeiXinCallBackServlet() {
        super();
    }

    /**
     * 微信公众号唯一标识(在微信小程序管理后台获取)
     */
    @Value("${wechat.appId}")
    private String appId;

    /**
     * 回调地址
     */
    @Value("${wechat.secret}")
    private String secret;

    /**
     * 第二步:通过code换取网页授权openid
     */
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        log.debug("WeiXinCallBackServlet callback start");

        // 从request里面获取code参数(当微信服务器访问回调地址的时候,会把code参数传递过来)
        String code = request.getParameter("code");

        // 获取code后,请求以下链接获取access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
                + "appid=" + appId
                + "&secret=" + secret
                + "&code=" + code
                + "&grant_type=authorization_code";

        // 通过网络请求方法来请求上面这个接口
        JSONObject jsonObject = doGetJson(url);

        // 从返回的JSON数据中取出access_token和openid,拉取用户信息时用
//        String token =  jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");

        // 第四步:拉取用户信息(需scope为 snsapi_userinfo)
//        String infoUrl ="https://api.weixin.qq.com/sns/userinfo?"
//                + "access_token=" + token
//                + "&openid=" + openid
//                + "&lang=zh_CN";
        // 通过网络请求方法来请求上面这个接口
//        JSONObject userInfo = doGetJson(infoUrl);
        request.setAttribute("openid", openid);
//        request.getRequestDispatcher("/login?channel=1&source=1&openid=" + openid).forward(request, response);

        log.debug("WeiXinCallBackServlet callback end");
    }


    /**
     * 工具类
     * @param url String
     * @return JSONObject
     */
    private JSONObject doGetJson(String url) throws IOException {
        log.debug("WeiXinCallBackServlet doGetJson start, url = [{}]", url);

        JSONObject jsonObject = null;
        // 首先初始化HttpClient对象
        HttpClient client = HttpClientBuilder.create().build();
        // 通过get方式进行提交
        HttpGet httpGet = new HttpGet(url);
        // 通过HTTPclient的execute方法进行发送请求
        HttpResponse response = client.execute(httpGet);
        // 从response里面拿自己想要的结果
        HttpEntity entity = response.getEntity();
        if(entity != null){
            String result = EntityUtils.toString(entity,"UTF-8");
            jsonObject = JSONObject.parseObject(result);
        }
        // 把链接释放掉
        httpGet.releaseConnection();

        log.debug("WeiXinCallBackServlet doGetJson end");
        return jsonObject;
    }

访问第一个servlet以后会得到一个跳转地址,然后直接在微信web开发者工具上使用就可以测试获取openId了

微信网页授权登录(公众号)-风君雪科技博客