簡單的實現微信獲取openid
微信公眾平臺獲取openid在公眾號的開發中有很多用途,前段時間為實現使用者使用公眾號在登入一次以後可以免密登陸而使用了openid。開發過程中遇到了一些問題,在這裡向需要且還沒有獲取到openid的米娜桑分享一下簡單的流程及部分程式碼,和一些問題的解決方式,給初次接觸微信openid的朋友們一個參考。目的只在於獲取openid,至於優化及應用上諸君請自由發揮。
首先了解openid是什麼,一個微訊號與一個公眾號對應一個固定不變的openid。所以一個微訊號在一個公眾號下的openid是不變的,如果換了一個對應的公眾號,那就是另一個openid了。且只有在微信自帶瀏覽器中開啟的專案才可獲取到。
準備:
首先你要有一個公眾號,還有一個外網可訪問的域名,我的公眾號型別是企業號,這裡就以企業號為例了。獲取openid需要的公眾號的 appid 和 secret(登陸公眾平臺 開發----->基本配置中的開發者ID(AppID)和 開發者密碼(AppSecret)就是)。其次是設定網頁授權域名(登陸公眾平臺 設定----->公眾號設定------>功能設定----->網頁授權域名 按步驟操作並設定就好),這個域名就是你獲取openid的web專案釋出的域名,這裡注意伺服器請一定跑在80埠。
流程:
1.呼叫https://open.weixin.qq.com/connect/oauth2/authorize介面獲取到code
2.得到code作為一個引數呼叫https://api.weixin.qq.com/sns/oauth2/access_token介面獲取到openid
因為只是簡單的獲取到openid,這裡只放兩個servlet與用到的工具類程式碼:
第一個是獲取code用的WxCodeServlt
public class WxCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
//這裡要將你的授權回撥地址處理一下,否則微信識別不了
String redirect_uri=URLEncoder.encode("/*你的授權回撥地址*/", "UTF-8");
//簡單獲取openid的話引數response_type與scope與state引數固定寫死即可
StringBuffer url=new StringBuffer("https://open.weixin.qq.com/connect/oauth2/authorize?redirect_uri="+redirect_uri+
"&appid="+/*你的appid*/+"&response_type=code&scope=snsapi_base&state=1#wechat_redirect");
response.sendRedirect(url.toString());//這裡請不要使用get請求單純的將頁面跳轉到該url即可
}
當用戶用微信進入我們的網頁並呼叫到WxCodeServlet之後,若引數無誤,設定的網頁授權域名正確,微信就會重定向頁面到我們提交的回撥地址,同時我們想要的code也會被傳過來
而這個回撥地址就是我們的第二個servlet WxOpenIdServlet
public class WxOpenIdServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String code = request.getParameter("code");//獲取code
Map params = new HashMap();
params.put("secret", "/*你的secret*/");
params.put("appid", "/*你的appid*/");
params.put("grant_type", "authorization_code");
params.put("code", code);
String result = HttpGetUtil.httpRequestToString(
"https://api.weixin.qq.com/sns/oauth2/access_token", params);
JSONObject jsonObject = JSONObject.fromObject(result);
String openid = jsonObject.get("openid").toString();
System.out.println("得到的openid為:"+openid);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在這裡我要補充一下了,一位朋友獲取到code後去請求卻被微信反悔了一個錯誤碼"errcode":40125,對應的錯誤是appsecret無效,可是填寫的appsecret與公眾平臺中的appsecret一致。這個問題在開發時我也遇到過,解決方式是重置appsecret,當初也沒在意,現在看來這個問題挺頻繁的,所以在這裡再補充一下。
其中用到了一個工具類HttpGetUtil JSON需要的包這裡就不說了
public class HttpGetUtil {
public static String httpRequestToString(String url,
Map<String,String> params) {
String result = null;
try {
InputStream is = httpRequestToStream(url, params);
BufferedReader in = new BufferedReader(new InputStreamReader(is,
"UTF-8"));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = in.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
} catch (Exception e) {
return null;
}
return result;
}
private static InputStream httpRequestToStream(String url,
Map<String, String> params) {
InputStream is = null;
try {
String parameters = "";
boolean hasParams = false;
for(String key : params.keySet()){
String value = URLEncoder.encode(params.get(key), "UTF-8");
parameters += key +"="+ value +"&";
hasParams = true;
}
if(hasParams){
parameters = parameters.substring(0, parameters.length()-1);
}
url += "?"+ parameters;
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setConnectTimeout(50000);
conn.setReadTimeout(50000);
conn.setDoInput(true);
//設定請求方式,預設為GET
conn.setRequestMethod("GET");
is = conn.getInputStream();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
}
至此如果各個步驟都沒有出錯的話,當我們的WxCodeServlet被呼叫後,控制檯就能打印出來剛才通過微信開啟我們網頁並呼叫到WxCodeServlet的微信使用者對應我們公眾平臺的openid了
注意問題:
1.網頁授權域名設定如果與提交的回撥地址的域名不對應,微信是無法回撥到的。
2.單純的獲取openid使用的授權方式是靜態授權,不需要經過使用者許可的(使用者看不到授權的過程),而想要獲取使用者的頭像暱稱等資訊是另一種授權(使用者端會彈出授權視窗),在此就不介紹了。
3.提交的回撥地址格式為 http://xxxx.xxxx.com/xxxxx/WxOpenIdServlet,使用java.net 包裡的URLEncoder.encode("url","utf-8")處理後提交
4.如遇到問題,請耐心細心的回頭按步驟檢查資料資訊以及程式碼。