首先,openid是什么?
openid是一個微信號與一個公眾號對應(yīng)一個固定不變的openid。所以一個微信號在一個公眾號下的openid是不變的,如果換了一個對應(yīng)的公眾號,那就是另一個openid了。openid只有在微信自帶瀏覽器中打開的項目才可獲取到。
準(zhǔn)備:
1、首先你要有一個公眾號,還有一個外網(wǎng)可訪問的域名。因為只有企業(yè)號才有獲取用戶信息的接口權(quán)限,所以這里就以企業(yè)號為例。
2、獲取openid需要的公眾號的 appid 和 secret:登陸公眾平臺查看開發(fā)----->基本配置中的開發(fā)者ID(AppID)和 開發(fā)者密碼(AppSecret)就是。

3、設(shè)置網(wǎng)頁授權(quán)域名:登陸公眾平臺 開發(fā)----->接口權(quán)限------>網(wǎng)頁服務(wù)----->網(wǎng)頁授權(quán)域名),這里需要注意,設(shè)置授權(quán)域名的時候需要先下載一個認(rèn)證文件,你把這個認(rèn)證文件放到你部署的服務(wù)器web項目的根目錄底下,比如springboot項目通常放到static目錄下,而且你的項目能夠被外網(wǎng)訪問到才行,然后點擊保存,如果微信服務(wù)器能訪問到這個文件,就會提示保存成功。你添加的這個域名就是你獲取openid的web項目發(fā)布的域名,這里注意服務(wù)器請一定跑在80端口。

操作流程:
上面的準(zhǔn)備工作完畢之后,接下來就可以開始正式進入獲取用戶openid的流程之中了。
獲取工作大致分為兩步:
1.通過調(diào)用https://open.weixin.qq.com/connect/oauth2/authorize接口獲取到code
請求方法:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
參數(shù)說明:

:在線urlencode地址:http://www.jsons.cn/urlencode/
2.得到code作為一個參數(shù)調(diào)用https://api.weixin.qq.com/sns/oauth2/access_token接口獲取到openid。
請求方法:
獲取code后,請求以下鏈接獲取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
參數(shù)說明:

下面我們逐步的進行說明:
1、其實第一步可以用兩種方式實現(xiàn):
一種是在公眾號中配置鏈接,比如在自動回復(fù)中設(shè)置a標(biāo)簽鏈接,或者新建菜單鏈接等,然后在用戶點擊你的鏈接時,你就能在你的controller中通過HttpServletRequest 獲得對應(yīng)的code值,然后你就可以根據(jù)code值進行第二步操作。

controller中的代碼如下:
@RequestMapping("/login")
public String loginDemo(HttpServletRequest request, HttpServletResponse response) {
System.out.println("+++++++微信+++++++"+request.getParameter("code"));
}
另一種方式是用戶通過鏈接登錄都你的項目時你主動發(fā)送請求獲取對應(yīng)的code,其代碼如下:
1. public class WxCodeServlet extends HttpServlet {
3. public void doGet(HttpServletRequest request, HttpServletResponse response)
4. throws ServletException, IOException {
6. doPost(request, response);
7. }
9. public void doPost(HttpServletRequest request, HttpServletResponse response)
10. throws ServletException, IOException {
12. response.setContentType("text/html");
13. response.setCharacterEncoding("UTF-8");
14. request.setCharacterEncoding("UTF-8");
15. //這里要將你的授權(quán)回調(diào)地址處理一下,否則微信識別不了
16. String redirect_uri=URLEncoder.encode("/*你的授權(quán)回調(diào)地址*/", "UTF-8");
17. //簡單獲取openid的話參數(shù)response_type與scope與state參數(shù)固定寫死即可
18. StringBuffer url=new StringBuffer("https://open.weixin.qq.com/connect/oauth2/authorize?redirect_uri="+redirect_uri+
19. "&appid="+/*你的appid*/+"&response_type=code&scope=snsapi_base&state=1#wechat_redirect");
20. response.sendRedirect(url.toString());//這里請不要使用get請求單純的將頁面跳轉(zhuǎn)到該url即可
23. }
接下來第二步就好處理了,你可以直接在同一個方法里進行第二步操作,獲取用戶的openid等信息,也可以在單獨寫一個方法進行獲取。
我的操作是這樣的:
@RequestMapping("/login")
public String loginDemo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, JSONException {
System.out.println("+++++++微信+++++++"+request.getParameter("code"));
response.setContentType("text/html");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String code = request.getParameter("code");//獲取code
Map params = new HashMap(16);
//公眾號的secret
params.put("secret", "/*你的secret*/");
//公眾號的appid
params.put("appid", "/*你的appid*/");
params.put("grant_type", "authorization_code");
params.put("code", request.getParameter("code"));
String result = HttpGetUtil.httpRequestToString(
"https://api.weixin.qq.com/sns/oauth2/access_token", params);
JSONObject jsonObject = new JSONObject(result);
//JSONObject jsonObject = JSONObject.fromObject(result);
String openid = jsonObject.get("openid").toString();
System.out.println("得到的openid為:"+openid);
......
return ...;
}
另外一種使用servlet的實現(xiàn)方式:
當(dāng)用戶用微信進入我們的網(wǎng)頁并調(diào)用到上面的WxCodeServlet之后,若參數(shù)無誤,設(shè)置的網(wǎng)頁授權(quán)域名正確,微信就會重定向頁面到我們提交的回調(diào)地址,同時我們想要的code也會被傳過來,這樣我們就能從下面這段代碼中獲取到你想要的openid了。
1. public class WxOpenIdServlet extends HttpServlet {
3. private static final long serialVersionUID = 1L;
5. public void doGet(HttpServletRequest request, HttpServletResponse response)
6. throws ServletException, IOException {
8. response.setContentType("text/html");
10. request.setCharacterEncoding("UTF-8");
11. response.setCharacterEncoding("UTF-8");
12. String code = request.getParameter("code");//獲取code
13. Map params = new HashMap();
14. params.put("secret", "/*你的secret*/");
15. params.put("appid", "/*你的appid*/");
16. params.put("grant_type", "authorization_code");
17. params.put("code", code);
18. String result = HttpGetUtil.httpRequestToString(
19. "https://api.weixin.qq.com/sns/oauth2/access_token", params);
20. JSONObject jsonObject = JSONObject.fromObject(result);
22. String openid = jsonObject.get("openid").toString();
23. System.out.println("得到的openid為:"+openid);
24. }
27. public void doPost(HttpServletRequest request, HttpServletResponse response)
28. throws ServletException, IOException {
29. doGet(request, response);
30. }
31. }
在這里補充一下:
有人獲取到code后去請求openid卻被微信反回了一個錯誤碼"errcode":40125,對應(yīng)的錯誤是appsecret無效,可是填寫的appsecret與公眾平臺中的appsecret一致。這個問題在開發(fā)時我也遇到過,解決方式是重置appsecret,當(dāng)初也沒在意,現(xiàn)在看來這個問題挺頻繁的,所以在這里再補充一下。
至此,如果各個步驟都沒有出錯的話,控制臺就能打印出來剛才通過微信打開我們網(wǎng)頁的微信用戶對應(yīng)我們公眾號平臺的openid了,其實這里獲取到的不止用戶的openid,還包含了用戶的其他信息。
附:上面的方法中用到了一個工具類HttpGetUtil,這里也貼出來,方便大家借鑒。(使用JSONObject需要先導(dǎo)入josn包,這里我也貼出來了吧)
<!--json-->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
工具類HttpGetUtil:
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);
//設(shè)置請求方式,默認(rèn)為GET
conn.setRequestMethod("GET");
is = conn.getInputStream();
} catch (UnsupportedEncodingException | MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
}