[微信开发] - 使用普通扫码登录获取用户信息,非开放平台版本

微信平台扫码登录时,因为开放平台的openid与原系统不一致,所以使用了原公众平台二维码扫码后获取用户openid,继而转链接形式.

油腻腻的大猪蹄进行测试 
oysIt005E1TDKTKIdc8TmR6VTViA < 使用开放平台的登录二维码扫码获取的openid 

o4mIl1jXCq4b2MkQ0tTZTzKzl2XY < 微信平台获取的openid

o4mIl1jXCq4b2MkQ0tTZTzKzl2XY < 扫码临时二维码获取的openid

 

大致流程:

用户点击微信登录->跳转到该请求 wechat/wechatLogin

请求到该控制层

package com.baigehuidi.demo.controller;

import com.baigehuidi.demo.loader.WeixinInsLoader;
import com.baigehuidi.demo.weixin4j.WeixinException;
import com.baigehuidi.demo.weixin4j.model.qrcode.Qrcode;
import com.baigehuidi.demo.weixin4j.model.qrcode.QrcodeType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

/**
 * 生成带参二维码
 */
@Controller
public class WeixinQrcodeController {

    //该方法为用户点击微信登录后请求的地址(第一步)
    @RequestMapping("/wechat/wechatLogin")
    public String wechatLogin(Model model) throws WeixinException {
        //场景字符串使用baige+时间
        String scene_str = "baige"+new Date().getTime();
        //字符串场景临时二维码
        Qrcode qrcode = WeixinInsLoader.getWeixinInstance().qrcode().create(QrcodeType.QR_STR_SCENE,scene_str,600);

        String ticket = qrcode.getTicket();
        String qrcodeUrl = null;
        if(ticket!=null){
            qrcodeUrl = WeixinInsLoader.getWeixinInstance().qrcode().showQrcode(ticket);//方法中已经进行了encode
        }
        model.addAttribute("qrcodeUrl",qrcodeUrl);
        model.addAttribute("scene_str",scene_str);
        //return ModelAndView(qrcode展示页面路径,modelMap);

        //跳转到二维码展示页面 (参数为字母+时间戳)
        return "/wechat/qrcode";
    }


}

其中上面方法中执行了创建临时二维码的官方的api接口请求链接 create() 方法创建了二维码

获取ticket之后展示二维码,获取二维码展示url showQrcode就是干这个的.

之后将展示二维码的路径放到model里,返回页面到wechat/qrcode

wechat/qrcode

截取展示jsp的控制器中展示qrcode的:

/**
     * 扫码登录 临时带参二维码版 qrcode二维码展示页面
     * @return
     */
    @RequestMapping("/wechat/qrcode")
    public String wqrcode(){ return "/wechat/qrcode"; }

展示的就是qrcode.jsp

<%--
微信扫码登录 openid版本
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>微信扫码,关注并登录</title>
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/>
    <style>a {
        outline: 0
    }

    h1, h2, h3, h4, h5, h6, p {
        margin: 0;
        font-weight: 400
    }

    a img, fieldset {
        border: 0
    }

    body {
        font-family: "Microsoft Yahei";
        color: #fff;
        background: 0 0
    }

    .impowerBox {
        display: inline-block;
        vertical-align: middle;
        line-height: 1.6;
        position: relative;
        width: 100%;
        z-index: 1;
        text-align: center
    }

    .impowerBox .title {
        text-align: center;
        font-size: 20px
    }

    .impowerBox .qrcode {
        width: 280px;
        height: 280px;
        margin-top: 15px;
        border: 1px solid #E2E2E2
    }

    .impowerBox .info {
        width: 280px;
        margin: 0 auto
    }

    .impowerBox .status {
        padding: 7px 14px;
        text-align: left
    }

    .impowerBox .status.normal {
        margin-top: 15px;
        background-color: #232323;
        border-radius: 100px;
        -moz-border-radius: 100px;
        -webkit-border-radius: 100px;
        box-shadow: inset 0 5px 10px -5px #191919, 0 1px 0 0 #444;
        -moz-box-shadow: inset 0 5px 10px -5px #191919, 0 1px 0 0 #444;
        -webkit-box-shadow: inset 0 5px 10px -5px #191919, 0 1px 0 0 #444
    }

    .impowerBox .status.status_browser {
        text-align: center
    }

    .impowerBox .status p {
        font-size: 13px
    }</style>
    <script src="http://www.jq22.com/jquery/jquery-3.3.1.js"></script>
</head>
<body style="background-color: rgb(51, 51, 51); padding: 50px;">
<div class="main impowerBox">
    <div class="loginPanel normalPanel">
        <div class="title">微信登录</div>
        <div class="waiting panelContent">
            <div class="wrp_code">
                <img class="qrcode lightBorder" src="${qrcodeUrl}"/>
            </div>
            <div class="info">
                <div class="status status_browser js_status normal" id="wx_default_tip">
                    <p>请使用微信扫描二维码登录</p>
                    <p>白鸽惠递</p>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        setInterval("wechatCheckLogin()", 2000);
    });

    function wechatCheckLogin() {
        $.post("/wechat/checkLogin", {scene_str: "${scene_str}"}, function (data) {
            console.log("请求/wechat/checkLogin方法中...");
            //数据1, 成功获取用户信息
            if (data.code===1) {
                window.location.href="http://baige.free.idcfengye.com/wechat/callback";
            } else if(data.code===0) {
                //虽然有用户openid,但是无法获取用户信息,可能是用户取消了关注
                //需要跳转到重新扫码生成界面
                window.location.href="http://baige.free.idcfengye.com/wechat/wechatLogin";
            }else if(data.code===-1){
                //如果场景字符串为空 -1 检查场景字符串时间戳生成是否正确
                window.location.href="http://baige.free.idcfengye.com/error";
            }else if(data.code===-2){
                //检查openid为什么没正确传入
                window.location.href="http://baige.free.idcfengye.com/error";
            }else if(data.code===-3){
                //-3
                //两者都为空,系统挂了吗
                window.location.href="http://baige.free.idcfengye.com/error";
            }
        }, "JSON");
    }
</script>
</body>
</html>

上面jsp中对请求进行轮询: wechat/checkLogin

下面是WeixinConnectionController中的请求到的方法:

 

    /**
     * TODO 如果数据库要进行更改,可以根据当时生成的scene_str查询用户openid或具体信息
     * 该方法为
     * @param scene_str
     * @return
     */
    @ResponseBody
    @RequestMapping("/wechat/checkLogin")
    public Map wechatCheckLogin(String scene_str,HttpSession session) throws WeixinException {
        System.err.println("scene_str : " + scene_str);

        String toUserName = null;//用户openid
        if (xmlObj != null) {
            toUserName = xmlObj.getToUserName();
            System.out.println("toUserName:" + toUserName);

        }
        //其中scene_str为场景字符串,使用了baige+时间戳 而toUserName则是扫码用户的openid
        if (scene_str != null && scene_str != "" && toUserName != null && toUserName != "") {
            System.err.println("wechatCheckLogin(String scene_str)->WeixinInsLoader.getWeixinInstance().getToken().getAccess_token()::::::"+WeixinInsLoader.getWeixinInstance().getToken().getAccess_token());
            User user = WeixinInsLoader.getWeixinInstance().user().info(toUserName);
            System.out.println("user:"+user);
            Map map = new HashMap();
            if(user!=null){
                //成功获取用户状态码
//                model.addAttribute(user);
                session.setAttribute("nickname",user.getNickname());
                map.put("code",1);
//                map.put("user",user);
                return map;
            }else if(user==null && toUserName!=null && toUserName !=""){
                //虽然有用户openid,但是无法获取用户信息,可能是用户取消了关注
                //需要跳转到重新扫码生成界面
                map.put("code",0);
                return map;
            } else if(scene_str == null && scene_str == ""){
                //如果场景字符串为空 -1 检查场景字符串时间戳生成是否正确
                map.put("code",-1);
                return map;
            }else if(toUserName == null && toUserName == ""){
                //检查openid为什么没正确传入
                map.put("code",-2);
                return map;
            }else{
                //两者都为空,系统挂了吗
                map.put("code",-3);
                return map;
            }

        }
        return null;

    }

该方法写在上面的Controller中虽有不太合适之嫌,但为了赶着完工,现在先放到这里,后期改善.

上面方法return map后,前端的qrcode.jsp页面接收返回值,如果用户已经扫码,则可以进行跳转回调页面.

这里到回调wechat/callback页面是因为如果仅仅获取微信用户信息,其实已经可以获取了:

通过上面的

User user = WeixinInsLoader.getWeixinInstance().user().info(toUserName);

该信息就是用户的微信资料信息.

但是除了这个信息,网站只是通过微信进行登录,其它的网站上的信息,账户,订单等是对应该用户的openid 或是openid同时的自增主键.

所以进入回调页面是要获取用户的更详尽的其它信息.

wechat/callback.jsp :

<%--
 缺少样式 (正在跳转)
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>正在跳转...</title>
    <script src="http://www.jq22.com/jquery/jquery-3.3.1.js"></script>
</head>
<body>
<p>该页面为回调页面,文本内容可为空.</p>
欢迎您,<%=session.getAttribute("nickname")%>.
正在跳转...

<script>
    $.ajax({
        // url: "/user/getOpenSnsUserInfoByCode",
        url: "/wechat/callbackAndGetUserInfo",
        // data: "${user.openid}",
        contentType: "application/json",
        dataType: "json",
        method: "POST",
        success: function (data) {

            if(data===1){
                //right code -> to index
                window.location.href="http://baige.free.idcfengye.com";
            }else{
                //wrong code -> show error page
                window.location.href="http://baige.free.idcfengye.com/error";
            }

        }
    });
</script>
</body>
</html>

wechat/callbackAndGetUserInfo:

 /**
     * 将用户信息放入session
     *
     * @param
     * @return
     * @throws WeixinException
     */
    @ResponseBody
    @RequestMapping(value = "/wechat/callbackAndGetUserInfo", method = RequestMethod.POST)
    public Integer callBackAndGetUserInfo(HttpSession session) throws WeixinException {
        System.out.println("callBackAndGetUserInfo method");

        String access_token = WeixinInsLoader.getWeixinInstance().getToken().getAccess_token();
        System.err.println("Connection:Access_token:" + access_token);
        SnsUser snsUser = null;

        String openid = xmlObj.getToUserName();
        System.out.println("openid:" + openid);


        User user = null;
        if (openid != null && openid != "") {
            //查询该openid下的其它表数据,如账户表等,放入一个实体传回到首页
            //这里先只展示用户信息

            user = WeixinInsLoader.getWeixinInstance().user().info(openid);
            session.setAttribute("user",user);

        }

        //存数据库



        if (user != null) {
            return 1;
        } else {
            return 0;
        }
    }

 

这里还有一些逻辑没做,比如用户之前关注过微信平台,再返回来关注时,虽然用户的openid还是相同的,但是给出提示

应该是: 欢迎回来.

而第一次关注的则是 : 欢迎关注...并给出新手提示.

 

这里还有一篇文章:

微信公众号与微信开放平台的openid不一致怎么破解?unionID为你解围

 

简单记录下整个流程

 

最后补一个index.jsp

<%@ page import="com.baigehuidi.demo.weixin4j.model.user.User" %>
<%@ page import="com.baigehuidi.demo.weixin4j.model.sns.SnsUser" %><%--
测试首页 将登录做为单独的页面 (也可以在该页面中进行弹出[或iframe形式或遮罩窗体形式])
TODO 每页(包括子页面)都应有登录或者展示用户昵称的头部bar

该页面为PC端.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>微信扫码登录</title>
    <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"></script>
    <style>
        .link{display: none;}
        .show{display: block;}
    </style>
</head>
<body>
TODO :
index.jsp  该页面也为最终用户登录后的页面,登录后,不再展示登录集,而展示用户名 <br>
<p id="nickname"></p>

用户登录后设定session时间 <br>
<a href="login">登录集</a> <br>
<a href="/menuCreate">自定义菜单</a> <br>
<a href="/wxpay/notify">支付测试</a> <br>

测试号二维码<br>
<img src="img/0.jpg" style="height:300px;width:300px">

${snsUser.nickname}
<%if(session.getAttribute("user")!=null){%>
<%User user = (User)session.getAttribute("user");%>
<%=user.getNickname()%>
<%}%>


<%--<%if(session.getAttribute("SnsUser")!=null){%>--%>
<%--<%SnsUser snsUser = (SnsUser)session.getAttribute("SnsUser");%>--%>
<%--<%=snsUser.getNickname()%>--%>
<%--<%}%>--%>

<a href="" class="link a2 show">不是微信端</a>
<a href="" class="link a1">微信端</a>


<p>该页面通过判定是否是微信内置浏览器,执行/非执行网页授权获取用户信息.</p>



<script>
    function isWeiXin() {
        var ua = window.navigator.userAgent.toLowerCase();
        console.log(ua);//mozilla/5.0 (iphone; cpu iphone os 9_1 like mac os x) applewebkit/601.1.46 (khtml, like gecko)version/9.0 mobile/13b143 safari/601.1
        if (ua.match(/MicroMessenger/i) == 'micromessenger') {
            return true;
        }
        else {
            return false;
        }
    }
    if(isWeiXin()){
        console.log(" 是来自微信内置浏览器");
        $(".a1").addClass("show");
        $(".a2").removeClass("show");
        //是微信内置浏览器执行通过code获取用户信息
        getSnsUserInfoByCode();
        function getSnsUserInfoByCode(){

            alert("getSnsUserInfoByCode in method");
            //下面页面为手机端页面获取
            $.ajax({
                url: "/user/getSnsUserInfoByCode",
                // url: "/callBackLogin",
                data: "<%=request.getParameter("code")%>",
                contentType: "application/json",
                dataType: "json",
                method: "POST",
                success: function (data) {
                    alert(JSON.stringify(data));
                    var nickname = data.SnsUser.nickname;
                    $("#nickname").html(nickname+"同学");
                    alert("你好啊,"+data.SnsUser.nickname+"同学,好久不见你瘦了一大圈.");
                    //将数据反填到html或jsp页面上
                }
            });
        }
    }
    else{
        console.log("不是来自微信内置浏览器");
        $(".a2").addClass("show");
        $(".a1").removeClass("show");
    }
</script>

</body>

</html>

 

posted @ 2018-12-16 12:43  ukyo--BlackJesus  阅读(4574)  评论(0编辑  收藏  举报