1. 程式人生 > >[微信開發] - 使用普通掃碼登入獲取使用者資訊,非開放平臺版本

[微信開發] - 使用普通掃碼登入獲取使用者資訊,非開放平臺版本

微信平臺掃碼登入時,因為開放平臺的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為你解圍