没事分析了下网页版本微信的通训协议,并且用java实现了登录,发送和接收消息,以后可以用来集成到后台,作为一个业务通知系统,就是每次登录需要扫码比较费事。
登录步骤:
1.打开首页,分配一个随机用户id,
2.根据该id获取二维码图片。
3.微信客户端扫描该图片,在客户端确认登录。
4.浏览器不停的调用一个接口,如果返回登录成功,则调用登录接口
5.此时可以获取联系人列表,可以发送消息。然后不断调用同步接口。
6.如果同步接口有返回,则可以获取新消息,然后继续调用同步接口。
贴上源码,仅供参考:(需要下载apache httpclient以及json)
package wwx; import java.util.LinkedList; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; public class WebWeixin { String url_getuuid="https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_={t}"; String url_login2weima="https://login.weixin.qq.com/qrcode/{}?t=webwx"; String url_check_login="https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid={}&tip=1&_={t}"; String url_init = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r={t}"; String url_contactlist = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r={t}"; String url_synccheck = "https://webpush.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?callback=jQuery18309326978388708085_1377482079946&r={t}&sid={0}&uin={1}&deviceid={2}&synckey={3}&_={t}"; String url_msglist = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid={}&r={t}"; String url_sendMsg = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid={}&r={t}"; public static void main(String[] args) throws Exception{ new WebWeixin().init(); // new Test().getCookies("http://www.baidu.com"); // System.out.println(System.currentTimeMillis();); } class UInfo{ String wxuin; String wxsid; String webwxuvid; String deviceid; String syncKey; JSONObject SyncKey; String SKey; JSONObject ujson; String name; //帐号 String nickName;//昵称 boolean connect = false; } UInfo u = new UInfo(); Object wait = new Object(); LinkedList<WxMsgListener> listeners = new LinkedList<WxMsgListener>(); public void addListener(WxMsgListener lis){ this.listeners.add(lis); } //开始登录微信 public void start(){ //1.取得uuid String getUUIDUrl = url_getuuid.replace("{t}", ""+System.currentTimeMillis()); String res = Utils.getUrl(getUUIDUrl); String uuid = ""; Pattern pat = Pattern.compile("window.QRLogin.code = ([0-9]+); window.QRLogin.uuid = \"([0-9a-z]+)\";"); Matcher mat = pat.matcher(res); if(mat.find()){ System.out.println(mat.group(1)); System.out.println(mat.group(2)); uuid = mat.group(2); } //2.取得登录二维码 String url_login = url_login2weima.replace("{}", uuid); System.out.println("login_url=>"+url_login); String img_path = Utils.dowmImg(url_login); System.out.println("img_path=>"+img_path); //3.轮询手机端是否已经扫描二维码并确认在Web端登录 String login_url = check_login(uuid); Map<String, String> cookies = Utils.getCookies(login_url); System.out.println("cookies = "+cookies); u.wxuin = cookies.get("wxuin"); u.wxsid = cookies.get("wxsid"); u.webwxuvid = cookies.get("webwxuvid"); u.deviceid = "e960817075982756"; //4.调用初始化url JSONObject post = new JSONObject(); JSONObject BaseRequest = new JSONObject(); post.put("BaseRequest", BaseRequest); BaseRequest.put("Uin", u.wxuin); BaseRequest.put("Sid", u.wxsid); BaseRequest.put("Skey", ""); BaseRequest.put("DeviceID", u.deviceid); String intUrl = url_init.replace("{t}", ""+System.currentTimeMillis()); res = Utils.postUrl(intUrl, post.toString()); JSONObject init = JSONObject.parseObject(res); JSONObject user = init.getJSONObject("User"); System.out.println("欢迎您:"+user); u.ujson = user; u.name = user.getString("UserName"); u.nickName = user.getString("NickName"); JSONObject SyncKey = init.getJSONObject("SyncKey"); u.syncKey = getSyncKey(init); u.SyncKey = SyncKey; u.SKey = init.getString("SKey"); u.connect = true; startSyncCheck(); u.connect = false; // System.out.println(res); } public void init() throws Exception{ while(true){ Thread t = new Thread(){ public void run(){ try { WebWeixin.this.start(); } catch (Exception e) { e.printStackTrace(); u.connect = false; } synchronized (wait) { wait.notify(); } } }; t.start(); Thread.sleep(300 * 1000); if(!u.connect){ t.interrupt(); }else{ synchronized (wait) { wait.wait(); } } } } //取得synckey public String getSyncKey(JSONObject json){ JSONObject SyncKey = json.getJSONObject("SyncKey"); JSONArray Listarr = SyncKey.getJSONArray("List"); String synckey = ""; for(int i = 0;i<Listarr.size(); i++){ JSONObject jj = Listarr.getJSONObject(i); synckey = synckey + jj.get("Key")+"_"+jj.get("Val")+"|" ; } synckey = synckey.substring(0, synckey.length() - 2); return synckey; } //check_login public String check_login(String uuid){ String url_check = url_check_login.replace("{}", uuid); url_check = url_check.replace("{t}", ""+System.currentTimeMillis()); int c = 0; String login_url = null; while(login_url == null){ String res = Utils.getUrl(url_check); Pattern pat = Pattern.compile("window.redirect_uri=\"(.+)\";"); Matcher mat = pat.matcher(res); if(mat.find()){ System.out.println(mat.group(1)); login_url = mat.group(1); } c++; } System.out.println("经历了"+c+"次轮询"); return login_url; } //循环检查新消息 public void startSyncCheck(){ while(true){ String url = url_synccheck.replace("{0}", u.wxsid); url = url.replace("{1}", u.wxuin); url = url.replace("{2}", u.deviceid); url = url.replace("{3}", u.syncKey); url = url.replaceAll("[|]", "%7C"); long t = System.currentTimeMillis(); url = url.replace("{t}", ""+t); url = url.replace("{t}", ""+t); String res = Utils.getUrl(url); System.out.println("sync back="+res); Pattern pat = Pattern.compile("window.synccheck=\\{retcode:\"([0-9]+)\",selector:\"([0-9]+)\"}"); Matcher mat = pat.matcher(res); if(mat.find()){ int retcode = Integer.valueOf(mat.group(1)); if(retcode != 0){ System.out.println(url); System.out.println("退出登录"+res); break; } int count = Integer.valueOf(mat.group(2)); // System.out.println(mat.group(2)); if(count > 0){ // System.out.println("有"+count+"条新消息"); String msgurl = url_msglist.replace("{}", u.wxsid); msgurl = msgurl.replace("{t}", ""+t); JSONObject post = new JSONObject(); JSONObject BaseRequest = new JSONObject(); BaseRequest.put("Uin", u.wxuin); BaseRequest.put("Sid", u.wxsid); post.put("BaseRequest", BaseRequest); post.put("SyncKey", u.SyncKey); post.put("rr", System.currentTimeMillis()); res = Utils.postUrl(msgurl, post.toString()); // System.out.println(res); JSONObject rj = JSONObject.parseObject(res); u.SKey = rj.getString("SKey"); if(u.SKey.equals("")){ break; } JSONObject SyncKey = rj.getJSONObject("SyncKey"); u.syncKey = getSyncKey(rj); u.SyncKey = SyncKey; JSONArray AddMsgList = rj.getJSONArray("AddMsgList"); for(int i = 0;i<AddMsgList.size(); i ++ ){ JSONObject msg = AddMsgList.getJSONObject(i); long msgid = msg.getLong("MsgId"); String fname = msg.getString("FromUserName"); String tname = msg.getString("ToUserName"); String cont = msg.getString("Content"); if(tname.equals(u.name)){ System.out.println("新消息:"+fname+":"+cont); // sendMsg(fname, "1"); //遍历 for(WxMsgListener l : this.listeners){ if(l.isEqualToMsg(fname, cont)){ l.exec(fname, cont); } } } } // System.out.println(res); } } } } //发送消息 public boolean sendMsg(String toname, String cont){ String url = url_sendMsg.replace("{}", u.wxsid); url = url.replace("{t}", ""+ System.currentTimeMillis()); JSONObject post = new JSONObject(); JSONObject BaseRequest = new JSONObject(); BaseRequest.put("Uin", u.wxuin); BaseRequest.put("Sid", u.wxsid); BaseRequest.put("DeviceID", u.deviceid); BaseRequest.put("Skey", u.SKey); post.put("BaseRequest", BaseRequest); JSONObject Msg = new JSONObject(); Msg.put("ClientMsgId", System.currentTimeMillis()); Msg.put("Content", cont); Msg.put("FromUserName", u.name); Msg.put("LocalID", System.currentTimeMillis()); Msg.put("ToUserName", toname); Msg.put("Type", 1); post.put("Msg", Msg); String res = Utils.postUrl(url, post.toString()); if(res != null){ JSONObject r = JSONObject.parseObject(res); if(r.getJSONObject("BaseResponse").getInteger("Ret") == 0){ System.out.println("发送成功"); return true; }else{ System.out.println("发送失败"); } }else{ //多次测试此时是发送成功的 } System.out.println(res); return false; } /************************* **************************************/ // static HttpClientContext context = HttpClientContext.create(); // //http get // public static String get(String url){ // try { // RequestConfig defaultRequestConfig = RequestConfig.custom() // .setSocketTimeout(60000) // .setConnectTimeout(60000) // .setConnectionRequestTimeout(60000) // .setStaleConnectionCheckEnabled(false) // .setExpectContinueEnabled(false) // .build(); // CloseableHttpClient httpclient = HttpClients.custom() // .setDefaultRequestConfig(defaultRequestConfig) // .build(); // // HttpGet httpget = new HttpGet(url); // CloseableHttpResponse response = httpclient.execute(httpget, context); // try { //// System.out.println(response); // // return EntityUtils.toString(response.getEntity()); // } finally { // response.close(); // } // } catch (ClientProtocolException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // return null; // } // //http getcookies // public static Map<String, String> getCookies(String url){ // try { // CloseableHttpClient httpclient = HttpClients.createDefault(); // HttpGet httpget = new HttpGet(url); // CloseableHttpResponse response = httpclient.execute(httpget, context); // try { // System.out.println(response); //// System.out.println(context.getCookieStore()); // CookieStore cs = context.getCookieStore(); // Map<String, String> map = new HashMap<String, String>(); // for(Cookie c : cs.getCookies()){ // map.put(c.getName(), c.getValue()); // } // return map; // } finally { // response.close(); // } // } catch (ClientProtocolException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // return null; // } // // //down img // public static String dowmImg(String url){ // try { // CloseableHttpClient httpclient = HttpClients.createDefault(); // HttpGet httpget = new HttpGet(url); // CloseableHttpResponse response = httpclient.execute(httpget, context); // try { //// System.out.println(response); // byte [] bs = EntityUtils.toByteArray(response.getEntity()); // File f =new File("img.png"); // OutputStream os = new FileOutputStream(f); // os.write(bs); // os.close(); //// return EntityUtils.toString(response.getEntity()); // return f.getAbsolutePath(); // } finally { // response.close(); // } // } catch (ClientProtocolException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // return null; // } // //http post // public static String post(String url, Object ... kvs){ // try { // List<NameValuePair> formparams = new ArrayList<NameValuePair>(); // for(int i = 0;i < kvs.length/2; i++){ // formparams.add(new BasicNameValuePair(""+kvs[2*i], ""+kvs[2*i + 1])); // } // UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8); // HttpPost post = new HttpPost(url); // post.setEntity(entity); // // CloseableHttpClient httpclient = HttpClients.createDefault(); // CloseableHttpResponse response = httpclient.execute(post, context); // try { //// System.out.println(response); // return EntityUtils.toString(response.getEntity()); // } finally { // response.close(); // } // } catch (ClientProtocolException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // return null; // } // // //http post // public static String postString(String url, String str){ // try { // StringEntity sentity = new StringEntity(str, Consts.UTF_8); // HttpPost post = new HttpPost(url); // post.setEntity(sentity); // // CloseableHttpClient httpclient = HttpClients.createDefault(); // CloseableHttpResponse response = httpclient.execute(post, context); // try { //// System.out.println(response); // HttpEntity ent = response.getEntity(); // String res = ""; // try { // res = EntityUtils.toString(ent, Charset.forName("UTF-8")); // } catch (ParseException e) { // e.printStackTrace(); // res = null; // } // return res; // } finally { // response.close(); // } // } catch (ClientProtocolException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // return null; // } }
扫描二维码关注公众号,回复:
575717 查看本文章