第八篇 :微信公眾平臺開發實戰Java版之如何網頁授權獲取用戶基本信息

来源:http://www.cnblogs.com/liuhongfeng/archive/2016/01/04/5099149.html
-Advertisement-
Play Games

我們首先來看看官方的文檔怎麼說:如果用戶在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取用戶基本信息,進而實現業務邏輯。關於網頁授權回調功能變數名稱的說明1、在微信公眾號請求用戶網頁授權之前,開發者需要先到公眾平臺官網中的開發者中心頁配置授權回調功能變數名稱。請註意,這裡填寫的是功能變數名稱(是一個字元...


我們首先來看看官方的文檔怎麼說:

如果用戶在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取用戶基本信息,進而實現業務邏輯。

關於網頁授權回調功能變數名稱的說明

1、在微信公眾號請求用戶網頁授權之前,開發者需要先到公眾平臺官網中的開發者中心頁配置授權回調功能變數名稱。請註意,這裡填寫的是功能變數名稱(是一個字元串),而不是URL,因此請勿加http://等協議頭;
2、授權回調功能變數名稱配置規範為全功能變數名稱,比如需要網頁授權的功能變數名稱為:www.qq.com,配置以後此功能變數名稱下麵的頁面http://www.qq.com/music.htmlhttp://www.qq.com/login.html 都可以進行OAuth2.0鑒權。但http://pay.qq.comhttp://music.qq.comhttp://qq.com無法進行OAuth2.0鑒權
3、如果公眾號登錄授權給了第三方開發者來進行管理,則不必做任何設置,由第三方代替公眾號實現網頁授權即可

關於網頁授權的兩種scope的區別說明

1、以snsapi_base為scope發起的網頁授權,是用來獲取進入頁面的用戶的openid的,並且是靜默授權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(往往是業務頁面)
2、以snsapi_userinfo為scope發起的網頁授權,是用來獲取用戶的基本信息的。但這種授權需要用戶手動同意,並且由於用戶同意過,所以無須關註,就可在授權後獲取該用戶的基本信息。
3、用戶管理類介面中的“獲取用戶基本信息介面”,是在用戶和公眾號產生消息交互或關註後事件推送後,才能根據用戶OpenID來獲取用戶基本信息。這個介面,包括其他微信介面,都是需要該用戶(即openid)關註了公眾號後,才能調用成功的。

關於網頁授權access_token和普通access_token的區別

1、微信網頁授權是通過OAuth2.0機制實現的,在用戶授權給公眾號後,公眾號可以獲取到一個網頁授權特有的介面調用憑證(網頁授權access_token),通過網頁授權access_token可以進行授權後介面調用,如獲取用戶基本信息;
2、其他微信介面,需要通過基礎支持中的“獲取access_token”介面來獲取到的普通access_token調用。

關於UnionID機制

1、請註意,網頁授權獲取用戶基本信息也遵循UnionID機制。即如果開發者有在多個公眾號,或在公眾號、移動應用之間統一用戶帳號的需求,需要前往微信開放平臺(open.weixin.qq.com)綁定公眾號後,才可利用UnionID機制來滿足上述需求。
2、UnionID機制的作用說明:如果開發者擁有多個移動應用、網站應用和公眾帳號,可通過獲取用戶基本信息中的unionid來區分用戶的唯一性,因為同一用戶,對同一個微信開放平臺下的不同應用(移動應用、網站應用和公眾帳號),unionid是相同的。

關於特殊場景下的靜默授權

1、上面已經提到,對於以snsapi_base為scope的網頁授權,就靜默授權的,用戶無感知;
2、對於已關註公眾號的用戶,如果用戶從公眾號的會話或者自定義菜單進入本公眾號的網頁授權頁,即使是scope為snsapi_userinfo,也是靜默授權,用戶無感知。

 

具體而言,網頁授權流程分為四步:

1、引導用戶進入授權頁面同意授權,獲取code
2、通過code換取網頁授權access_token(與基礎支持中的access_token不同)
3、如果需要,開發者可以刷新網頁授權access_token,避免過期
4、通過網頁授權access_token和openid獲取用戶基本信息(支持UnionID機制)

 

 

下麵,我們來按照這個步驟來實現這個功能:

 

第一步:用戶同意授權,獲取code

 

 

在確保微信公眾賬號擁有授權作用域(scope參數)的許可權的前提下(服務號獲得高級介面後,預設擁有scope參數中的snsapi_base和snsapi_userinfo),引導關註者打開如下頁面

 

參考鏈接(請在微信客戶端中打開此鏈接體驗)

Scope為snsapi_base
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

Scope為snsapi_userinfo

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

 

 

 

參數說明

 

參數是否必須說明
appid 公眾號的唯一標識
redirect_uri 授權後重定向的回調鏈接地址,請使用urlencode對鏈接進行處理
response_type 返回類型,請填寫code
scope 應用授權作用域,snsapi_base (不彈出授權頁面,直接跳轉,只能獲取用戶openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到昵稱、性別、所在地。並且,即使在未關註的情況下,只要用戶授權,也能獲取其信息
state 重定向後會帶上state參數,開發者可以填寫a-zA-Z0-9的參數值,最多128位元組
#wechat_redirect 無論直接打開還是做頁面302重定向時候,必須帶此參數

下圖為scope等於snsapi_userinfo時的授權頁面:

 

 

用戶同意授權後

如果用戶同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。若用戶禁止授權,則重定向後不會帶上code參數,僅會帶上state參數redirect_uri?state=STATE

 

code說明 :
code作為換取access_token的票據,每次用戶授權帶上的code將不一樣,code只能使用一次,5分鐘未被使用自動過期。

 

 

溫馨提醒:以下的省略了搭建環境和導入jar的過程,以下的方法提供參考。如果需要的話,需要看下前面的系列文章。

 

 

我們首先創建一些需要用到的pojo :

 

1. 通過網頁授權獲取的用戶信息

 

package com.souvc.weixin.pojo;

import java.util.List;

/**
* 類名: SNSUserInfo </br>
* 描述: 通過網頁授權獲取的用戶信息 </br>
* 開發人員: souvc </br>
* 創建時間:  2015-11-27 </br>
* 發佈版本:V1.0  </br>
 */
public class SNSUserInfo {
    // 用戶標識
    private String openId;
    // 用戶昵稱
    private String nickname;
    // 性別(1是男性,2是女性,0是未知)
    private int sex;
    // 國家
    private String country;
    // 省份
    private String province;
    // 城市
    private String city;
    // 用戶頭像鏈接
    private String headImgUrl;
    // 用戶特權信息
    private List<String> privilegeList;

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getHeadImgUrl() {
        return headImgUrl;
    }

    public void setHeadImgUrl(String headImgUrl) {
        this.headImgUrl = headImgUrl;
    }

    public List<String> getPrivilegeList() {
        return privilegeList;
    }

    public void setPrivilegeList(List<String> privilegeList) {
        this.privilegeList = privilegeList;
    }
}

 

2.  憑證實體類

package com.souvc.weixin.pojo;

/**
* 類名: Token </br>
* 描述:  憑證  </br>
* 開發人員: souvc </br>
* 創建時間:  2015-11-27 </br>
* 發佈版本:V1.0  </br>
 */
public class Token {
    // 介面訪問憑證
    private String accessToken;
    // 憑證有效期,單位:秒
    private int expiresIn;

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(int expiresIn) {
        this.expiresIn = expiresIn;
    }
}

 

3. 網頁授權信息 類

 

package com.souvc.weixin.pojo;

/**
* 類名: WeixinOauth2Token </br>
* 描述:  網頁授權信息  </br>
* 開發人員: souvc </br>
* 創建時間:  2015-11-27 </br>
* 發佈版本:V1.0  </br>
 */
public class WeixinOauth2Token {
    // 網頁授權介面調用憑證
    private String accessToken;
    // 憑證有效時長
    private int expiresIn;
    // 用於刷新憑證
    private String refreshToken;
    // 用戶標識
    private String openId;
    // 用戶授權作用域
    private String scope;

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(int expiresIn) {
        this.expiresIn = expiresIn;
    }

    public String getRefreshToken() {
        return refreshToken;
    }

    public void setRefreshToken(String refreshToken) {
        this.refreshToken = refreshToken;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }
}

 

 

4.  微信用戶的基本信息

 

package com.souvc.weixin.pojo;

/**
* 類名: WeixinUserInfo </br>
* 描述: 微信用戶的基本信息  </br>
* 開發人員: souvc </br>
* 創建時間:  2015-11-27 </br>
* 發佈版本:V1.0  </br>
 */
public class WeixinUserInfo {
    // 用戶的標識
    private String openId;
    // 關註狀態(1是關註,0是未關註),未關註時獲取不到其餘信息
    private int subscribe;
    // 用戶關註時間,為時間戳。如果用戶曾多次關註,則取最後關註時間
    private String subscribeTime;
    // 昵稱
    private String nickname;
    // 用戶的性別(1是男性,2是女性,0是未知)
    private int sex;
    // 用戶所在國家
    private String country;
    // 用戶所在省份
    private String province;
    // 用戶所在城市
    private String city;
    // 用戶的語言,簡體中文為zh_CN
    private String language;
    // 用戶頭像
    private String headImgUrl;

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public int getSubscribe() {
        return subscribe;
    }

    public void setSubscribe(int subscribe) {
        this.subscribe = subscribe;
    }

    public String getSubscribeTime() {
        return subscribeTime;
    }

    public void setSubscribeTime(String subscribeTime) {
        this.subscribeTime = subscribeTime;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getHeadImgUrl() {
        return headImgUrl;
    }

    public void setHeadImgUrl(String headImgUrl) {
        this.headImgUrl = headImgUrl;
    }
}

 

 

但是如何獲取到token值呢?

 

/**
     * 獲取網頁授權憑證
     * 
     * @param appId 公眾賬號的唯一標識
     * @param appSecret 公眾賬號的密鑰
     * @param code
     * @return WeixinAouth2Token
     */
    public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
        WeixinOauth2Token wat = null;
        // 拼接請求地址
        String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        requestUrl = requestUrl.replace("APPID", appId);
        requestUrl = requestUrl.replace("SECRET", appSecret);
        requestUrl = requestUrl.replace("CODE", code);
        // 獲取網頁授權憑證
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
        if (null != jsonObject) {
            try {
                wat = new WeixinOauth2Token();
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setExpiresIn(jsonObject.getInt("expires_in"));
                wat.setRefreshToken(jsonObject.getString("refresh_token"));
                wat.setOpenId(jsonObject.getString("openid"));
                wat.setScope(jsonObject.getString("scope"));
            } catch (Exception e) {
                wat = null;
                int errorCode = jsonObject.getInt("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                log.error("獲取網頁授權憑證失敗 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return wat;
    }

 

 獲取用戶信息:

 

/**
     * 通過網頁授權獲取用戶信息
     * 
     * @param accessToken 網頁授權介面調用憑證
     * @param openId 用戶標識
     * @return SNSUserInfo
     */
    @SuppressWarnings( { "deprecation", "unchecked" })
    public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {
        SNSUserInfo snsUserInfo = null;
        // 拼接請求地址
        String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
        // 通過網頁授權獲取用戶信息
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);

        if (null != jsonObject) {
            try {
                snsUserInfo = new SNSUserInfo();
                // 用戶的標識
                snsUserInfo.setOpenId(jsonObject.getString("openid"));
                // 昵稱
                snsUserInfo.setNickname(jsonObject.getString("nickname"));
                // 性別(1是男性,2是女性,0是未知)
                snsUserInfo.setSex(jsonObject.getInt("sex"));
                // 用戶所在國家
                snsUserInfo.setCountry(jsonObject.getString("country"));
                // 用戶所在省份
                snsUserInfo.setProvince(jsonObject.getString("province"));
                // 用戶所在城市
                snsUserInfo.setCity(jsonObject.getString("city"));
                // 用戶頭像
                snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                // 用戶特權信息
                snsUserInfo.setPrivilegeList(JSONArray.toList(jsonObject.getJSONArray("privilege"), List.class));
            } catch (Exception e) {
                snsUserInfo = null;
                int errorCode = jsonObject.getInt("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                log.error("獲取用戶信息失敗 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return snsUserInfo;
    }

 

 

 

上面我們用到了一個支持發送https請求的工具:

 

package com.souvc.weixin.util;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;

/**
* 類名: MyX509TrustManager </br>
* 描述:信任管理器 </br>
* 開發人員: souvc </br>
* 創建時間:  2015-11-27 </br>
* 發佈版本:V1.0  </br>
 */
public class MyX509TrustManager implements X509TrustManager {

    // 檢查客戶端證書
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // 檢查伺服器端證書
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // 返回受信任的X509證書數組
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

 

 

/**
     * 發送https請求
     * 
     * @param requestUrl 請求地址
     * @param requestMethod 請求方式(GET、POST)
     * @param outputStr 提交的數據
     * @return JSONObject(通過JSONObject.get(key)的方式獲取json對象的屬性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 創建SSLContext對象,並使用我們指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 從上述SSLContext對象中得到SSLSocketFactory對象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);
            
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 設置請求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 當outputStr不為null時向輸出流寫數據
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 註意編碼格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 從輸入流讀取返回內容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 釋放資源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("連接超時:{}", ce);
        } catch (Exception e) {
            log.error("https請求異常:{}", e);
        }
        return jsonObject;
    }

 

 

二、寫授權類:

註意替換成自己的appid 和 密鑰

 

 

package com.souvc.weixin.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.souvc.weixin.pojo.SNSUserInfo;
import com.souvc.weixin.pojo.WeixinOauth2Token;
import com.souvc.weixin.util.AdvancedUtil;

/**
* 類名: OAuthServlet </br>
* 描述: 授權後的回調請求處理 </br>
* 開發人員: souvc </br>
* 創建時間:  2015-11-27 </br>
* 發佈版本:V1.0  </br>
 */
public class OAuthServlet extends HttpServlet {
    private static final long serialVersionUID = -1847238807216447030L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");

        // 用戶同意授權後,能獲取到code
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        
        // 用戶同意授權
        if (!"authdeny".equals(code)) {
            // 獲取網頁授權access_token
            WeixinOauth2Token weixinOauth2Token = AdvancedUtil.getOauth2AccessToken("wxe34a90ac7bxxcab85c", "1207d566090a8344xxxd6224c02c", code);
            // 網頁授權介面訪問憑證
            String accessToken = weixinOauth2Token.getAccessToken();
            // 用戶標識
            String openId = weixinOauth2Token.getOpenId();
            // 獲取用戶信息
            SNSUserInfo snsUserInfo = AdvancedUtil.getSNSUserInfo(accessToken, openId);

            // 設置要傳遞的參數
            request.setAttribute("snsUserInfo", snsUserInfo);
            request.setAttribute("state", state);
        }
        // 跳轉到index.jsp
        request.getRequestDispatcher("index.jsp").forward(request, response);
    }
}

 

 

三、授權後,顯示信息的頁面

 

<%@ page language="java" pageEncoding="utf-8"%>
<%@ page import="com.souvc.weixin.pojo.SNSUserInfo,java.lang.*"%>
<html>
<head>
    <title>OAuth2.0網頁授權</title>
    <meta name="viewport" content="width=device-width,user-scalable=0">
    <style type="text/css">
        *{margin:0; padding:0}
        table{border:1px dashed #B9B9DD;font-size:12pt}
        td{border:1px dashed #B9B9DD;word-break:break-all; word-wrap:break-word;}
    </style>
</head>
<body>
    <% 
        // 獲取由OAuthServlet中傳入的參數
        SNSUserInfo user = (SNSUserInfo)request.getAttribute("snsUserInfo"); 
        String state=request.getAttribute("state").toString();
        if(null != user) {
    %>
    <table width="100%" cellspacing="0" cellpadding="0">
        <tr><td width="20%">屬性</td><td width="80%">值</td></tr>
        <tr><td>OpenID</td><td><%=user.getOpenId()%></td></tr>
        <tr><td>昵稱</td><td><%=user.getNickname()%></td></tr>
        <tr><td>性別</td><td><%=user.getSex()%></td></tr>
        <tr><td>國家</td><td><%=user.getCountry()%></td></tr>
        <tr><td>省份</td><td><%=user.getProvince()%></td></tr>
        <tr><td>城市</td><td><%=user.getCity()%></td></tr>
        <tr><td>頭像</td><td><%=user.getHeadImgUrl()%></td></tr>
        <tr><td>特權</td><td><%=user.getPrivilegeList()%></td></tr>
        <tr><td>state:</td><td><%=state%></td></tr>
    </table>
    <%
        }
        else 
            out.print("用戶不同意授權,未獲取到用戶信息!");
    %>
</body>
</html>

 

 

四、寫請求的路徑

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <!-- <servlet> <servlet-name>coreServlet</servlet-name> <servlet-class>com.souvc.weixin.servlet.CoreServlet</servlet-class> </servlet>
  -->
<!-- /coreServlet用於指定該Servlet的訪問路徑 <servlet-mapping> <servlet-name>coreServlet</servlet-name> <url-pattern>/coreServlet</url-pattern> </servlet-mapping>
  -->

<servlet> <servlet-name>oauthServlet</servlet-name> <servlet-class>com.souvc.weixin.servlet.OAuthServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>oauthServlet</servlet-name> <url-pattern>/oauthServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

 

 

 

五、替換官方的鏈接成我們的方法路徑:

 

Scope為snsapi_userinfo

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

 

   我這裡是:把

http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php 換成自己的請求鏈接。

 

註意這個鏈接需要經過utf-8的編碼:

 

方法是:

 

/**
     * URL編碼(utf-8)
     * 
     * @param source
     * @return
     */
    public static String urlEncodeUTF8(String source) {
        String result = source;
        try {
            result = java.net.URLEncoder.encode(source, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

 

 

 

package com.souvc.weixin.util;

public class TestURL {

    /**     
     * 方法名:main</br>
     * 詳述:生成URL編碼 </br>
     * 開發人員:souvc </br>
     * 創建時間:2016-1-4  </br>
     * @param args 說明返回值含義
     * @throws 說明發生此異常的條件
     */
    public static void main(String[] args) {
        String source="http://chiyan.duapp.com/oauthServlet";
        System.out.println(CommonUtil.urlEncodeUTF8(source));
    }

}

 

也可以直接線上url編碼: http://tool.chinaz.com/Tools/URLEncode.aspx

 

 

六、複製上面替換好的鏈接,然後丟進瀏覽器,然後用微信來掃一掃。會出現以下的效果:

 

 

 

 

 

說明,恭喜你,我們獲取到了用戶的基本信息。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [新年新氣象,2016/01/04] 俺們在開發IOS程式過程中,經常需要用到NSLog輸出一些信息,甚至有的開發過程,必須在控制台查看輸出,有經驗的程式員通過控制台輸出就能知道整個數據交互的一個流程。但是一個發佈的程式,裡面帶有太多的NSLog輸出,肯定對於App性能有所影響,這時候我們可以...
  • 版權聲明:本文為博主原創文章,未經博主允許不得轉載。描述:烏龜和兔子(各自是一個Java線程)在我們的電腦上賽跑,我們為它們指定一個跑道(本地文件系統上的一個目錄,該目錄包含子目錄)。跑的規則是讀“跑道”上的所有文件。兔子很聰明,只讀文件的元信息(路徑名、大小、最後修改時間),但每讀完一個文件就要睡...
  • 主要使用了java.lang.reflect中的Proxy類,方法如下:static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)下麵是利用JDBC做的測試,類似於重寫了Con...
  • php -v 是linux系統的php版本,而phpinfo里顯示的是WEB Server中配置的版本。說簡單點,你的系統中有兩個php版本。
  • 線程的一些主要狀態以及狀態之間的裝換 (如下圖)主要狀態為:1.新建 2.就緒3.運行 4阻塞 5.死亡 其中:join()可以用來邀請其他線程先執行 yield()告訴系統"把自己的CPU時間讓掉,讓其他線程或者自己運行"引入線程的好處:1 創建一個線程花費的時間少。2 兩個線...
  • python列表排序 python字典排序 sortedList的元素可以是各種東西,字元串,字典,自己定義的類等。sorted函數用法如下:sorted(data, cmp=None, key=None, reverse=False) 其中,data是待排序數據,可以使List或者iter...
  • 在開發中遇到將form中的name值一樣的多個input元素傳遞到後臺,我用的是springmvc。剛開始的時候老是報400的請求錯誤。後來查了下資料,其實解決方案挺簡單的。我的後臺controller的代碼如下: 1 @RequestMapping(value = { "/examine" }, ...
  • 早上老大扔了個設備來說要做個搖一搖紅包 就上網找了下 強大的度娘都找不到大神們分享出來的源碼 只能自己埋頭去寫寫了微信官方說明如下搖一搖紅包說明功能說明搖一搖周邊紅包介面是為線下商戶提供的發紅包功能。用戶可以在商家門店等線下場所通過搖一搖周邊領取商家發放的紅包,線上上轉發分享無效。開發者可通過介面開...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...