没事分析了下网页版本微信的通训协议,并且用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(); LinkedListlisteners = new LinkedList (); 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 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 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 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 map = new HashMap (); // 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 formparams = new ArrayList (); // 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; // } }