這篇文章主要介紹微信開發(fā)之如何獲取OAuth2.0網(wǎng)頁授權(quán)認證和獲取用戶信息進行關(guān)聯(lián),文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
成都創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的解放網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
最近有做了關(guān)于微信公眾號和自己網(wǎng)站用戶進行用戶關(guān)聯(lián)授權(quán)登錄的一個功能,主要是用戶關(guān)注該公眾號,點擊會員中心,則會彈出需要關(guān)聯(lián)授權(quán)的網(wǎng)頁授權(quán):OAuth3.0網(wǎng)頁授權(quán),然后用戶同意獲取用戶信息,進行用戶和網(wǎng)站的關(guān)聯(lián),然后用戶則可以使用微信進行登錄。
本次做的是一個在Java的Action層處理各個返回參數(shù)獲取數(shù)據(jù)。
一、 使用到的工具:
1、ngrok,將你自己的本機映射到公網(wǎng),這樣保證可以隨時測試開發(fā);
1、下載ngrok,網(wǎng)址:www.tunnel.mobi/
2、將文件放到Tomcat目錄下,在cmd中運行ngrok -config ngrok.cfg -subdomain xinzhi 8080
3、ngrok工具為在慕課網(wǎng)@LAOBI 看到的
2、微信公眾號測試賬號,隨時測試,首先保證在測試賬號下沒有問題后在進行公眾號的移植。
二、使用到在Java中發(fā)送一個Http請求,然后返回JSON參數(shù),獲得JSON參數(shù),然后進行處理。
首先,獲取將公眾號測試號放到properties文件中,以便我們進行調(diào)用或者更換,如:url請用https
Properties代碼
AppID = wxf00**c3dd2ebfa0 AppSecret = 3cb220755f****506dc35391aa5c03ec url = https://xinzhi.tunnel.mobi
這里url為我們映射到外網(wǎng)的地址,一會需要用到。然后需要兩個工具類,該工具類作用是在Java的Action中發(fā)送http請求后獲取到去返回值
這里使用的是@柳峰,關(guān)于服務(wù)器請求的代碼http://blog.csdn.net/lyq8479/article/details/9841371,啟用自己有相應(yīng)的改動,以適應(yīng)本項目的需求:
WeixinUtil.java 和 MyX509TrustManager.java
Java代碼
package com.zhtx.common.util; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 公眾平臺通用接口工具類 * * @author xinz * @date 2015-10-14 */ public class WeixinUtil { private static Logger log = LoggerFactory.getLogger(WeixinUtil.class); /** * 發(fā)起https請求并獲取結(jié)果 * * @param requestUrl 請求地址 * @param requestMethod 請求方式(GET、POST) * @param outputStr 提交的數(shù)據(jù) * @return JSONObject(通過JSONObject.get(key)的方式獲取json對象的屬性值) */ public static String httpRequest(String requestUrl, String requestMethod, String outputStr) { StringBuffer buffer = new StringBuffer(); try { // 創(chuàng)建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 httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 設(shè)置請求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 當有數(shù)據(jù)需要提交時 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意編碼格式,防止中文亂碼 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 將返回的輸入流轉(zhuǎn)換成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 釋放資源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); } catch (ConnectException ce) { log.error("Weixin server connection timed out."); } catch (Exception e) { log.error("https request error:{}", e); } return buffer.toString(); } }
對于https請求,我們需要一個證書信任管理器,這個管理器類需要自己定義,但需要實現(xiàn)X509TrustManager接口,代碼如下:
Java代碼
package com.zhtx.common.util; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /** * 證書信任管理器(用于https請求) * * @author xinz * @date 2015-10-14 */ public class MyX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }
微信返回參數(shù)的一個POJO類:
Java代碼
private String openid; //用戶的唯一標識 private String nickname;//用戶昵稱 private Integer sex;// 用戶的性別,值為1時是男性,值為2時是女性,值為0時是未知 private String province;//用戶個人資料填寫的省份 private String city;//普通用戶個人資料填寫的城市 private String country;// 國家,如中國為CN private String headimgurl; // 用戶頭像,最后一個數(shù)值代表正方形頭像大小(有0、46、64、96、132數(shù)值可選,0代表640*640正方形頭像),用戶沒有頭像時該項為空。若用戶更換頭像,原有頭像URL將失效。 private String privilege;// 用戶特權(quán)信息,json 數(shù)組,如微信沃卡用戶為(chinaunicom) private String unionid;// 只有在用戶將公眾號綁定到微信開放平臺帳號后,才會出現(xiàn)該字段。詳見:獲取用戶個人信息(UnionID機制) private String access_token;
授權(quán)憑證驗證的類:
Java代碼
private String errcode; private String errmsg;
通過code換取網(wǎng)頁授權(quán)access_token
Java代碼
private String access_token; private String expires_in; private String refresh_token; private String openid; private String scope; private String unionid;
關(guān)于微信頭像的,獲取的是一個http的url,則需要將圖片下載到服務(wù)器存儲,然后獲得相對路徑:
Java代碼
/** * 使用url或者http存入文件 * @Title: fileUpload * @param @param fileUrl 文件url,可以是http * @param @param path 文件存儲路徑 * @return void * @throws xinz */ public static void fileUpload (String fileUrl,String path){ //讀取文件 String s1 = fileUrl; java.io.InputStream is = null; //定義一個輸入流。 BufferedInputStream bis = null;//定義一個帶緩沖的輸入流 。 //寫到本地 BufferedOutputStream bos = null; //定義一個帶緩沖的輸出流。 try{ java.net.URL url = new java.net.URL(s1);//創(chuàng)建一個URL對象。 is = url.openStream();//打開到此 URL 的連接并返回一個用于從該連接讀入的 InputStream。 bis = new java.io.BufferedInputStream(is); File file = new File(path); if(!file.exists()){ //測試此抽象路徑名表示的文件或目錄是否存在。 file.createNewFile(); //創(chuàng)建此抽象路徑名表示的文件或目錄。 } bos = new BufferedOutputStream(new FileOutputStream(file));; byte[] b = new byte[1024]; //創(chuàng)建字節(jié)數(shù)組。 while(bis.read(b)!=-1){//輸入流中的數(shù)據(jù)如果還有下一行(!=-1)將繼續(xù)循環(huán) bos.write(b);//將字節(jié)數(shù)組寫入輸出流。 } }catch(Exception e){ System.out.println(e.toString()); }finally{ try{ bos.flush();//刷新此緩沖的輸出流。 bis.close(); //關(guān)閉此輸入流 。 }catch(Exception e){ System.out.println(e.toString()); } } }
現(xiàn)在是基礎(chǔ)工作都做完了,現(xiàn)在開發(fā)代碼的開發(fā),在微信開發(fā)文檔中 http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html 有提到每一個步驟,然后我們按照這個步驟開發(fā):
1第一步:用戶同意授權(quán),獲取code
2第二步:通過code換取網(wǎng)頁授權(quán)access_token
3第三步:刷新access_token(如果需要)
4第四步:拉取用戶信息(需scope為 snsapi_userinfo)
5附:檢驗授權(quán)憑證(access_token)是否有效
第一步:用戶同意授權(quán),獲取code
這里的url就是前面所準備在properties中的url了。
Java代碼
/** * 微信用戶授權(quán) * @Title: wechatOauth * @param @param request * @param @param response * @param @param model * @param @return * @return String * @throws xinz */ @RequestMapping("wechatOauth") public String wechatOauth(HttpServletRequest request,HttpServletResponse response,Model model) { /** * 1 第一步:用戶同意授權(quán),獲取code */ //首先拿到微信公眾號的AppID、AppSecret等參數(shù) String AppID = ZhtxHelper.getApplicationResourcesProp("sendSms","AppID"); String urlOpen = ZhtxHelper.getApplicationResourcesProp("sendSms","url"); //如果用戶授權(quán)成功則跳轉(zhuǎn)到此url String loginUrl = ""+urlOpen+"/zhtx-wap/weixin/getAccessToken"; //用戶授權(quán),獲取code String url = "https://open.weixin.qq.com/connect/oauth3/authorize?" + "appid="+AppID+"" + "&redirect_uri="+loginUrl+"" + "&response_type=code" + "&scope=snsapi_userinfo" + "&state=123#wechat_redirect"; //forward redirect return "redirect:"+url+""; }
Java代碼
/** * 通過code換取網(wǎng)頁授權(quán)access_token * @Title: getAccessToken * @param @param request * @param @param response * @param @param model * @param @return * @return String * @throws xinz */ @RequestMapping("getAccessToken") public String getAccessToken(HttpServletRequest request,HttpServletResponse response,Model model) { //獲取到返回的參數(shù) try { //首先拿到微信公眾號的AppID、AppSecret等參數(shù) String AppID = ZhtxHelper.getApplicationResourcesProp("sendSms","AppID"); String AppSecret = ZhtxHelper.getApplicationResourcesProp("sendSms","AppSecret"); String code = request.getParameter("code"); String url = null; if(code!=null){ /** * 2 第二步:通過code換取網(wǎng)頁授權(quán)access_token */ //用戶授權(quán),獲取code url = "https://api.weixin.qq.com/sns/oauth3/access_token?" + "appid="+AppID+"" + "&secret="+AppSecret+"" + "&code="+code+"" + "&grant_type=authorization_code"; String requestMethod = "GET"; String outputStr = ""; String httpRequest = WeixinUtil.httpRequest(url, requestMethod, outputStr); System.out.println("通過code換取網(wǎng)頁授權(quán)access_token="+httpRequest); AccessTokenModel accTok = JSON.parseObject(httpRequest, AccessTokenModel.class); /** * 4 第四步:拉取用戶信息(需scope為 snsapi_userinfo) */ //用戶授權(quán),獲取code String urlUser = "https://api.weixin.qq.com/sns/userinfo?" + "access_token="+accTok.getAccess_token()+"" + "&openid="+accTok.getOpenid()+"" + "&lang=zh_CN"; String httpUser = WeixinUtil.httpRequest(urlUser, requestMethod, outputStr); System.out.println("拉取用戶信息=="+httpUser); WechatUser wechatUser = JSON.parseObject(httpUser, WechatUser.class); wechatUser.setAccess_token(accTok.getAccess_token()); /** * 5 附:檢驗授權(quán)憑證(access_token)是否有效 */ WechatMsg checkAccessToken = checkAccessToken(wechatUser.getAccess_token(), wechatUser.getOpenid()); if(checkAccessToken.getErrcode().equals("0")){ CurrentSession.setAttribute("wechatUser", wechatUser); WechatUser wechatU = new WechatUser(); wechatU.setOpenid(wechatUser.getOpenid()); ListfindWechatUser = wechatUserService.findWechatUser(wechatU); if(findWechatUser.size()>0){ UserRegister userRegister = userService.findUserByOpenid(wechatUser.getOpenid()); CurrentSession.setAttribute("user", userRegister); return "redirect:/user/userCenter"; }else{ return "/jsp/wechat/wechatregister"; } }else{ //如果access_token失效,則再次進行調(diào)用,并存儲access_token值,access_token有效期為2個小時 this.wechatOauth(request, response, model); } } } catch (Exception e) { System.out.println("===拉取用戶出錯==="); e.printStackTrace(); } //forward redirect return "/jsp/wechat/wechatregister"; }
Java代碼
/** * 微信關(guān)聯(lián)用戶 * @Title: saveWechatUser * @param @param mobilePhone * @param @param password * @param @param validataCode * @param @return * @return String * @throws xinz */ @RequestMapping("saveWechatUser") public String saveWechatUser(HttpServletResponse response,String mobilePhone,String password,String validataCode){ //使用手機號來判斷該手機是否在注冊 UserRegister userRegister = userService.findUserByPhone(mobilePhone); WechatUser wechatUser = (WechatUser)CurrentSession.getAttribute("wechatUser"); WechatUser wechatU = new WechatUser(); wechatU.setOpenid(wechatUser.getOpenid()); ListfindWechatUser = wechatUserService.findWechatUser(wechatU); if(findWechatUser.size()>0 && userRegister.getOpenid()!=null){ CurrentSession.setAttribute("user", userRegister); return "redirect:/user/userCenter"; }else{ //如果沒有注冊,開始注冊 if(userRegister==null){ Result saveUserInfoApp = userRegisterService.saveUserInfoApp(mobilePhone, password, validataCode,wechatUser); if(saveUserInfoApp.getState()==1){ //進行微信和用戶的關(guān)聯(lián) wechatUserService.saveWechatUser(wechatUser); CurrentSession.setAttribute("user", userRegister); return "redirect:/user/userCenter"; } }else if(userRegister.getOpenid()==null || userRegister.getOpenid().equals("")){ //否則,查詢出用戶信息,放入session中,關(guān)聯(lián)微信,跳轉(zhuǎn)到用戶中心 UserRegister userReg = new UserRegister(); userReg.setId(userRegister.getId()); //存入微信openid userReg.setOpenid(wechatUser.getOpenid()); userService.upUser(userReg); UserInfo user = new UserInfo(); //存入微信頭像 //圖片類型 String dateStr =DateUtil.format(DateUtil.getCurrentDate(), "yyyyMMdd") + "/"; //圖片類型 String imgType = "JPG"; //微信頭像名稱 String app2DBarNameAndType = UuidUtil.getUUID()+"."+imgType; //微信頭像路徑 String path = ZhtxHelper.getApplicationResourcesProp("application","app.img.projectpath")+ SysConstant.GOODS2DBARPATH + dateStr; File file1 = new File(path); file1.mkdirs(); //圖片全路徑 String imgUrl = SysConstant.GOODS2DBARPATH + dateStr+app2DBarNameAndType; FileUtil.fileUpload(wechatUser.getHeadimgurl(), path); user.setRegisterId(userRegister.getId()); user.setImageUrl(imgUrl); userInfoService.updateUserInfo(user); //存入微信用戶 wechatUserService.saveWechatUser(wechatUser); UserRegister userW = userService.findUserByPhone(mobilePhone); CurrentSession.setAttribute("user", userW); return "redirect:/user/userCenter"; }else{ CurrentSession.setAttribute("user", userRegister); return "redirect:/user/userCenter"; } } return "redirect:/user/userCenter"; }
Java代碼
/** * 檢驗授權(quán)憑證(access_token)是否有效 * @Title: checkAccessToken * @param @param access_token 網(wǎng)頁授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同 * @param @param openid 用戶的唯一標識 * @return WechatMsg 返回消息實體 * @throws xinz */ public static WechatMsg checkAccessToken(String access_token,String openid){ String requestMethod = "GET"; String outputStr = ""; String url = "https://api.weixin.qq.com/sns/auth?" + "access_token="+access_token+"" + "&openid="+openid+""; String httpmsg = WeixinUtil.httpRequest(url, requestMethod, outputStr); System.out.println("拉取用戶信息返回消息=="+httpmsg); WechatMsg msg = JSON.parseObject(httpmsg, WechatMsg.class); return msg; }
然后在網(wǎng)頁端,則是需要編寫H5頁面,進行自己網(wǎng)站和微信用戶的關(guān)聯(lián),我這里是使用手機號,用戶輸入手機號,進行判斷,如果注冊過就直接關(guān)聯(lián),如果用戶沒有注冊則進行注冊后關(guān)聯(lián),完成后跳轉(zhuǎn)到會員中心。
以上是“微信開發(fā)之如何獲取OAuth2.0網(wǎng)頁授權(quán)認證和獲取用戶信息進行關(guān)聯(lián)”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!