1. 程式人生 > >第八篇 :微信公眾平臺開發實戰Java版之如何網頁授權獲取使用者基本資訊

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

第一部分:微信授權獲取基本資訊的介紹

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

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

關於網頁授權回撥域名的說明

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),引導關注者開啟如下頁面

引數說明

引數 是否必須 說明
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. 通過網頁授權獲取的使用者資訊

使用者資訊類:SNSUserInfo類

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;
    }
}
View Code

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;
    }
}
View Code

3. 網頁授權資訊 WeixinOauth2Token類

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;
    }
}
View Code

4.  微信使用者的基本資訊WeixinUserInfo類

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;
    }
}
View Code

5. 封裝AdvancedUtil來實現以下方法 。

但是如何獲取到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;
    }
View Code

 獲取使用者資訊:

/**
     * 通過網頁授權獲取使用者資訊
     * 
     * @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;
    }
View Code

 6. 封裝https請求類 CommonUtil 類。

上面我們用到了一個支援傳送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;
    }
}
View Code
/**
     * 傳送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;
    }
View Code

二、寫授權類:

注意替換成自己的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);
    }
}
View Code

三、授權後,顯示資訊的頁面

<%@ 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>
View Code

四、寫請求的路徑

<?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>
View Code

五、替換官方的連結成我們的方法路徑:

官方的請求連結:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

需要修改的地方:

(1)替換自己的AppID

(2)將redirect_url換成自己的授權請求連結URL。注意這個連線需要經過UTF-8編碼。

(3)需要修改scope。需要彈出頁面則要修改為snsapi_userinfo 。

scope引數的解釋:

1、以snsapi_base為scope發起的網頁授權,是用來獲取進入頁面的使用者的openid的,並且是靜默授權並自動跳轉到回撥頁的。使用者感知的就是直接進入了回撥頁(往往是業務頁面)

2、以snsapi_userinfo為scope發起的網頁授權,是用來獲取使用者的基本資訊的。但這種授權需要使用者手動同意,並且由於使用者同意過,所以無須關注,就可在授權後獲取該使用者的基本資訊。 

/**
     * 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;
    }
View Code
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));
    }

}
View Code

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

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

說明,恭喜你,我們獲取到了使用者的基本資訊。

其他文章關聯:

相關推薦

公眾平臺開發實戰Java如何網頁授權獲取使用者基本資訊

第一部分:微信授權獲取基本資訊的介紹 我們首先來看看官方的文件怎麼說: 如果使用者在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取使用者基本資訊,進而實現業務邏輯。 關於網頁授權回撥域名的說明 1、在微信公眾號請求使用者網頁授權之前,開發者需要先到公眾平臺官網中的開發者中心頁配置授權

公眾平臺開發實戰Java如何實現自定義分享內容

第一部分:微信JS-SDK介紹 微信JS-SDK是微信公眾平臺面向網頁開發者提供的基於微信內的網頁開發工具包。 通過使用微信JS-SDK,網頁開發者可藉助微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信使用者提供更優質的網頁

公眾平臺開發實戰Java如何自定義公眾號選單

我們來了解一下 自定義選單建立介面: 自定義選單查詢介面: 自定義選單刪除介面: 自定義選單介面可實現多種型別按鈕,如下: 1、click:點選推事件 使用者點選click型別按鈕後,微信伺服器會通過訊息介面推送訊息型別為event 的結構給開發者(參考訊息介面指

公眾平臺開發實戰Java如何獲取公眾號的access_token以及快取access_token

一、access_token簡介 為了使第三方開發者能夠為使用者提供更多更有價值的個性化服務,微信公眾平臺 開放了許多介面,包括自定義選單介面、客服介面、獲取使用者資訊介面、使用者分組介面、群發介面等, 開發者在呼叫這些介面時,都需要傳入一個相同的引數 access_token,它是公眾賬號的全域性唯一票

公眾平臺開發實戰Java請求訊息,響應訊息以及事件訊息類的封裝

微信伺服器和第三方伺服器之間究竟是通過什麼方式進行對話的? 下面,我們先看下圖: 其實我們可以簡單的理解: (1)首先,使用者向微信伺服器傳送訊息; (2)微信伺服器接收到使用者的訊息處理之後,通過開發者配置的URL和Token 來找到第三方伺服器,並以XML形式向第三方伺服器傳送訊息

公眾平臺開發實戰Java完成訊息接受與相應以及訊息的處理

溫馨提示:      這篇文章是依賴前幾篇的文章的。 首先,我們看看原來寫的dopost方法: /** * 處理微信伺服器發來的訊息 */ public void doPost(HttpServletRequest request, Http

公眾平臺開發實戰Java如何獲取信使用者基本資訊

在關注者與公眾號產生訊息互動後,公眾號可獲得關注者的OpenID(加密後的微訊號,每個使用者對每個公眾號的OpenID是唯一的。對於不同公眾號,同一使用者的openid不同)。 公眾號可通過本介面來根據OpenID獲取使用者基本資訊,包括暱稱、頭像、性別、所在城市、語言和關注時間。 開發者可通過Ope

第一公眾平臺開發實戰Java瞭解公眾平臺基礎知識以及資料準備

相信很多人或多或少聽說了微信公眾平臺的火熱。但是開發還是有一點門檻,鑑於挺多朋友問我怎麼開發,問多了,自己平時也進行以下總結。 所以下面給大家分享一下我的經驗: 第一部分   介紹微信公眾號的一些簡單介紹以及微信扮演的一些角色,微信公眾號的重要性。 1. 微信公眾號是什麼?    官網

第二 公眾平臺開發實戰Java開啟開發者模式,接入微公眾平臺開發

第一部分:微信公眾號對接的基本介紹 一、填寫伺服器配置資訊的介紹 登入微信公眾平臺官網後,進入到公眾平臺後臺管理頁面。 選擇 公眾號基本設定-》基本配置 ,點選“修改配置”按鈕,填寫伺服器地址(URL)、Token和EncodingAESKey。 微信公眾號配置介面:  以上

公眾平臺開發實戰Java獲取使用者基本資訊

在關注者與公眾號產生訊息互動後,公眾號可獲得關注者的OpenID(加密後的微訊號,每個使用者對每個公眾號的OpenID是唯一的。對於不同公眾號,同一使用者的openid不同)。 公眾號可通過本介面來根據OpenID獲取使用者基本資訊,包括暱稱、頭像、性別、所在城市、語言和

公眾平臺開發實戰Java如何獲取公眾號的access_token以及快取access_token

一、access_token簡介 為了使第三方開發者能夠為使用者提供更多更有價值的個性化服務,微信公眾平臺 開放了許多介面,包括自定義選單介面、客服介面、獲取使用者資訊介面、使用者分組介面、群發介面等, 開發者在呼叫這些介面時,都需要傳入一個相同的引數 access_token,它是公眾賬號的全域性唯一票據,

公眾平臺開發教程Java(六) 事件處理(選單點選/關注/取消關注)

前言: 事件處理是非常重要的,這一章講講常見的事件處理 1、關注/取消關注 2、選單點選 事件型別介紹: 在微信中有事件請求是訊息請求中的一種。請求型別為:event 而event事件型別又分多種事件型別,具體分關注:subscribe取消關注:unsubscribe自定義選單點選:CLICK    根

公眾平臺開發——為何不能在網頁調用jsapi?

什麽 ket 平臺 使用 scrip ken 進行 兩個 pro 說到這問題,相信大部分程序員老手都會輕蔑一笑,當然是跨域導致的啊!但是為了一些小白,我覺得還是很有必要再說一次的。 首先介紹什麽是跨域,由於瀏覽器的同源策略,出於防範跨站腳本的攻擊,禁止客戶端腳本( 主要是J

[043] 公眾平臺開發教程19-應用例項人臉檢測

CSDN2013年度部落格之星評選活動開始,本人有幸入圍參加評選,如果部落格中的文章對你有所幫助,請為柳峰投上寶貴一票,非常感謝!        在筆者的公眾賬號小q機器人(微訊號:xiaoqrobot)中有一個非常好玩的功能"人臉檢測",它能夠檢測出使用者傳送的圖片中有多少

公眾平臺開發進入(Web App開發入門)

WebApp與Native App有何區別呢? Native App: 1、開發成本非常大。一般使用的開發語言為Java、C++、Objective-C。 2、更新體驗較差、同時也比較麻煩。每一次釋出新的版本,都需要做版本打包,且需要使用者手動更新(有些應用程式即使不需要使用者手動更新,但是也需要有一個噁心

[053] 公眾平臺開發教程23-SAE不支援XStream框架的解決方案

問題描述最近幾天(2014年8月20日之後),突然有不少網友反應,柳峰部落格中的微信公眾平臺開發程式碼在SAE上執行會報錯,或者是能正常部署,但向公眾號發訊息沒反應。以前也有一些初學者質疑過我部落格中的程式碼是否能正常執行,最後都被我一一證明是由於他們的不理解和粗心導致,但這

[044] 公眾平臺開發教程20-新手解惑40則

        筆者在CSDN部落格頻道推出微信公眾平臺開發教程之後,接觸了許多公眾平臺開發愛好者,也幫助他們解決了許多實際的問題,當然這其中有很多問題都是重複的,因此,筆者將這些問題及解答整理出來,以幫助更多初學者少走彎路。1、訂閱號與服務號的主要區別是什麼?訂閱號每天能群

公眾平臺開發教程()Session處理

class 如果 obj returns name ref car opera 信用 在微信窗口,輸入的信息有限,我們需要將一些信息分多次請求。 比如:在進行用戶綁定時,我們需要輸入用戶的相關信息,比如:用戶名、密碼,或者姓名、電話號碼,服務端驗證通過,即可將系統用戶與微信

粉絲一鍵同步工具類

1、前言   在公眾號開發的過程中,一般都需要獲取粉絲資料,針對單個粉絲,我們可以通過openid獲取其粉絲資訊; 但不排除這種業務,比如目前開發的公眾號已經在使用中,,當前的框架或者功能已經不能夠滿足使用者的需求、需要重新開發,那麼這個時候你開發的新的微信專案將要接入到之前老的微