原始的代码不记得是哪个作者了,如果原作者看见了,我要说声谢谢
但这个真的做了大改动,我怕原作者也看不出来了~最近比较忙,如果谁愿意,去改改吧,不知道为什么,这个很不稳定,老是405错误,或者最近移动的问题?
给出代码:
package myFetion; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.nio.ByteBuffer; import java.security.MessageDigest; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.codec.binary.Hex; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; public class libFx { // [start] 变量定义 private static final String SIP_M = "M fetion.com.cn SIP-C/2.0"; private static final String SIP_S = "S fetion.com.cn SIP-C/2.0"; private static String URL_SD = "http://221.176.31.42/ht/sd.aspx"; private static String URL_LOGIN = "https://uid.fetion.com.cn/ssiportal/SSIAppSignIn.aspx"; private static String URL_CONFIG = "http://nav.fetion.com.cn/nav/getsystemconfig.aspx"; private int call, seq; private String username, password; private String ssic, sid, guid, domain, uri; private HashMap<String, buddyInfo> allBuddys = new HashMap<String, buddyInfo>(); // [end] private class resResult { int status; Map<String, List<String>> header; String response; } public class buddyInfo { String uri; String mobile; String localname; String nickname; String buddytype; String displayname; } public libFx(String username, String password) { this.username = username; this.password = password; } public void getSystemConfig() { String data = "<config><user mobile-no=\"" + username; data += "\" /><client type=\"PC\" version=\"3.2.0540\" platform=\"W5.1\" />"; data += "<servers version=\"0\" /><service-no version=\"0\" /><parameters version=\"0\" />"; data += "<hints version=\"0\" /><http-applications version=\"0\" /></config>"; resResult res = httpRequest(URL_CONFIG, data, null); try { String[] resSplit = res.response.split("\r\n"); String xmlData = resSplit[0]; Document xml = DocumentHelper.parseText(xmlData); Element httptunnel = (Element) xml.selectObject("/config/servers/http-tunnel"); URL_SD = httptunnel.getStringValue(); Element ssiappsignin = (Element) xml.selectObject("/config/servers/ssi-app-sign-in"); URL_LOGIN = ssiappsignin.getStringValue(); } catch (Exception ex) { System.out.println(ex.getMessage()); } } // [start] 登录,注册到服务器,退出 public String Login() { String debugMsg = ""; try { String data = "mobileno=" + username + "&pwd=" + password + ""; resResult res = httpRequest(URL_LOGIN, data, null); if (res == null) { debugMsg = "login error"; return debugMsg; } String header = res.header.values().toString(); Pattern ssicPattern = Pattern.compile("ssic=(.*?);"); Matcher matcher = ssicPattern.matcher(header); if (matcher.find()) { ssic = matcher.group(1); } Document document = DocumentHelper.parseText(res.response); Element root = document.getRootElement(); Element user = root.element("user"); // 示例:<user uri="sip:[email protected];p=6006" mobile-no="15910510159" user-status="101" user-id="607221518"> uri = user.attribute("uri").getValue(); int a = uri.indexOf("@"); int b = uri.indexOf(";"); sid = uri.substring(4, a); domain = uri.substring(a + 1, b); } catch (Exception ex) { debugMsg += ex.getMessage(); return debugMsg; } return "OK" + debugMsg; } public String Register() { String debugMsg = ""; String arg = "<args><device type=\"PC\" version=\"2009112603\" client-version=\"3.5.2540\" />"; arg += "<caps value=\"simple-im;im-session;temp-group;personal-group;im-relay;xeno-im;direct-sms;sms2fetion\" />"; arg += "<events value=\"contact;permission;system-message;personal-group;compact\" /><user-info attributes=\"all\" />"; arg += "<presence><basic value=\"400\" desc=\"\" /></presence></args>"; String response = null, nonce = null; HashMap<String, String> fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", nextCall()); fields.put("Q", "1 R"); String msg = createSipData("R fetion.com.cn SIP-C/2.0", fields, arg) + "SIPP"; // 发送请求 response = sendRequest(nextUrl("i"), msg).response; response = sendRequest(nextUrl("s"), "SIPP").response; Pattern noncePattern = Pattern.compile("nonce=\"(\\w+)\""); Matcher m = noncePattern.matcher(response); if (m.find()) { nonce = m.group(1); } else { return "not find noce!" + response; } String salt = "777A6D03"; String cnonce = calc_cnonce(); String calcResponse = calc_response(nonce, cnonce); String strA = "Digest algorithm=\"SHA1-sess\",response=\"" + calcResponse + "\","; strA += "cnonce=\"" + cnonce + "\",salt=\"" + salt + "\",ssic=\"" + ssic + "\""; fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", nextCall()); fields.put("Q", "2 R"); fields.put("A", strA); msg = createSipData("R fetion.com.cn SIP-C/2.0", fields, arg) + "SIPP"; // 发送请求 response = sendRequest(nextUrl("s"), msg).response; response = sendRequest(nextUrl("s"), "SIPP").response; if (response == null) { return "not 2R"; } return "OK" + debugMsg; } public boolean logout() { HashMap<String, String> fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", "1"); fields.put("Q", "2 R"); fields.put("X", "0"); String msg = createSipData("R fetion.com.cn SIP-C/2.0", fields, null) + "SIPP"; String response = sendRequest(nextUrl("s"), msg).response; System.out.println("退出:" + response); if (response == null || response.equals("")) { return false; } return true; } // [end] // [start] 相关算法 private String nextCall() { call += 1; return String.valueOf(call); } private String nextUrl(String t) { seq++; System.out.println(URL_SD + "?t=" + t + "&i=" + seq); return new StringBuffer(URL_SD).append("?t=").append(t).append("&i=").append(seq).toString(); } private String calc_cnonce() { MessageDigest md5 = null; String md5Str = null; try { md5 = MessageDigest.getInstance("MD5"); md5.update(UUID.randomUUID().toString().getBytes("UTF-8")); md5Str = new String(Hex.encodeHex(md5.digest())).toUpperCase(); } catch (Exception e) { return null; } return md5Str; } private String calc_response(String nonce, String cnonce) { String temp = ":"; String strTemp = "REGISTER"; char[] saltChars = { 0x77, 0x7A, 0x6D, 0x03 }; String salt = String.valueOf(saltChars); String h3 = null; try { int sidLength = sid.getBytes("UTF-8").length; int domainLength = domain.getBytes("UTF-8").length; int nonceLength = nonce.getBytes("UTF-8").length; int tempLength = temp.getBytes("UTF-8").length; int strTempLength = strTemp.getBytes("UTF-8").length; int cnonceLength = cnonce.getBytes("UTF-8").length; ByteBuffer buf = null; // 晕,这部有点多余可以省略,就是把原来加密过的字符串转成字节 // byte[] decode = Hex.decodeHex(binstr.toUpperCase().toCharArray()); MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); // 密码使用SHA-1加密 sha1 = MessageDigest.getInstance("SHA-1"); sha1.update(password.getBytes("UTF-8")); byte[] src = sha1.digest(); // 加密后把{ 0x77, 0x7A, 0x6D, 0x03 }这四个字符加上用SHA-1加密过的密码 buf = ByteBuffer.allocate(src.length + salt.getBytes("UTF-8").length); buf.put(salt.getBytes("UTF-8")); buf.put(src); buf.flip(); sha1.update(buf); buf.clear(); // 然后再把相加过的`字节数组`用SHA-1加密 byte[] decode = sha1.digest(); // 用SHA-1加密```形式如 sid:domain:decode buf = ByteBuffer.allocate(sidLength + domainLength + decode.length + (tempLength * 2)); buf.put(sid.getBytes("UTF-8")); buf.put(temp.getBytes("UTF-8")); buf.put(domain.getBytes("UTF-8")); buf.put(temp.getBytes("UTF-8")); buf.put(decode); buf.flip(); sha1.update(buf); byte[] keyBytes = sha1.digest(); // 用MD5加密```形式如 key:nonce:cnonce 上面生成的就是key 生成h1 MessageDigest md5 = MessageDigest.getInstance("MD5"); buf = ByteBuffer.allocate(keyBytes.length + nonceLength + cnonceLength + (tempLength * 2)); buf.put(keyBytes); buf.put(temp.getBytes("UTF-8")); buf.put(nonce.getBytes("UTF-8")); buf.put(temp.getBytes("UTF-8")); buf.put(cnonce.getBytes("UTF-8")); buf.flip(); md5.update(buf); buf.clear(); String h1 = new String(Hex.encodeHex(md5.digest())).toUpperCase(); // 用MD5加密```形式如 REGISTER:sid 生成h2 buf = ByteBuffer.allocate(sidLength + strTempLength + tempLength); buf.put(strTemp.getBytes("UTF-8")); buf.put(temp.getBytes("UTF-8")); buf.put(sid.getBytes("UTF-8")); buf.flip(); md5.update(buf); buf.clear(); String h2 = new String(Hex.encodeHex(md5.digest())).toUpperCase(); // 用MD5加密```形式如 h1:nonce:h2 生成h2 buf = ByteBuffer.allocate(h1.getBytes("UTF-8").length + nonceLength + h2.getBytes("UTF-8").length + (tempLength * 2)); buf.put(h1.getBytes("UTF-8")); buf.put(temp.getBytes("UTF-8")); buf.put(nonce.getBytes("UTF-8")); buf.put(temp.getBytes("UTF-8")); buf.put(h2.getBytes("UTF-8")); buf.flip(); md5.update(buf); buf.clear(); h3 = new String(Hex.encodeHex(md5.digest())).toUpperCase(); } catch (Exception e) { e.printStackTrace(); } return h3; } private String createSipData(String invite, HashMap<String, String> fields, String arg) { StringBuffer sip = new StringBuffer(invite).append("\r\n"); for (Map.Entry<String, String> entry : fields.entrySet()) { sip.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n"); } if (arg != null) { try { sip.append("L: ").append(arg.getBytes("UTF-8").length).append("\r\n\r\n").append(arg); } catch (UnsupportedEncodingException e) { return null; } } return sip.toString(); } // [end] // [start] http请求 private resResult httpRequest(String strUrl, String data, Map<String, String> heads) { resResult res = new resResult(); URL url = null; HttpURLConnection conn = null; for (int i = 0; i < 10; i++) {// 如果请求失败,则重试5次 try { url = new URL(strUrl); conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true);// 设置输出 conn.setUseCaches(false);// 不使用缓存 conn.setRequestMethod("POST"); // 循环设置请求头部,比如cookie if (heads != null) { for (Entry<String, String> entry : heads.entrySet()) conn.setRequestProperty(entry.getKey(), entry.getValue()); } OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); out.write(data);// 写入请求(POST)数据 out.flush(); out.close(); InputStream in = conn.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf-8")); String line = "", response = ""; while ((line = br.readLine()) != null) { response += line + "\r\n"; } Map<String, List<String>> resHeads = conn.getHeaderFields(); res.status = conn.getResponseCode(); System.out.println("conn_code:" + res.status); res.response = response; res.header = resHeads; } catch (Exception e) { System.out.println(e.getMessage()); } finally { if (conn != null) conn.disconnect(); } if (res.status == 200) { break;// 重试若干次,当返回200则跳出 } try { Thread.sleep(1000); } catch (InterruptedException e) { } } return res; } private resResult sendRequest(String strUrl, String data) { if (guid == null) { guid = UUID.randomUUID().toString(); } resResult res = new resResult(); try { Map<String, String> cookies = new HashMap<String, String>(); cookies.put("User-Agent", "IIC2.0/PC 3.5.2540"); cookies.put("Cookie", "ssic=" + ssic); cookies.put("Content-Type", "application/oct-stream"); cookies.put("Pragma", "xz4BBcV" + guid); // StringRequestEntity m_data = new StringRequestEntity(data, "text/xml", "utf-8"); res = httpRequest(strUrl, data, cookies); } catch (Exception e) { return null; } return res; } // [end] // /以下是飞信应用API public HashMap<String, buddyInfo> getContactsInfo() { allBuddys = getContactsList(); StringBuffer arg = new StringBuffer("<args><contacts attributes=\"all\">"); for (Entry<String, buddyInfo> buddy : allBuddys.entrySet()) { arg.append("<contact uri=\"").append(buddy.getKey()).append("\" />"); } arg.append("</contacts></args>"); HashMap<String, String> fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", nextCall()); fields.put("Q", "1 S"); fields.put("N", "GetContactsInfo"); String msg = createSipData(SIP_S, fields, arg.toString()) + "SIPP"; try { sendRequest(nextUrl("s"), msg); Thread.sleep(2000); String response = sendRequest(nextUrl("s"), "SIPP").response; String[] resSplit = response.split("\r\n\r\n"); String xmlData = resSplit[1].replace("</results>SIPP", "</results>"); Document xml = DocumentHelper.parseText(xmlData); List contacts = xml.selectNodes("/results/contacts/contact"); Iterator itc = contacts.iterator(); while (itc.hasNext()) { Element elt = (Element) itc.next(); Attribute uri = elt.attribute("uri"); buddyInfo buddy = allBuddys.get(uri.getStringValue()); Element personal = elt.element("personal"); Attribute mobile = personal.attribute("mobile-no"); Attribute nickname = personal.attribute("nickname"); buddy.mobile = mobile.getStringValue(); buddy.nickname = nickname.getStringValue(); buddy.buddytype = "mobile"; String display = buddy.localname; if (display.equals("")) display = buddy.nickname; if (display.equals("")) display = buddy.mobile; if (display.equals("")) display = "猪头啦"; buddy.displayname = display; } } catch (Exception ex) { } return allBuddys; } private HashMap<String, buddyInfo> getContactsList() { String arg = "<args><contacts><buddy-lists /><buddies attributes=\"all\" />"; arg += "<mobile-buddies attributes=\"all\" /><chat-friends /><blacklist /></contacts></args>"; HashMap<String, String> fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", nextCall()); fields.put("Q", "1 S"); fields.put("N", "GetContactList"); String msg = createSipData(SIP_S, fields, arg) + "SIPP"; sendRequest(nextUrl("s"), msg); String response = sendRequest(nextUrl("s"), "SIPP").response; HashMap<String, buddyInfo> lstbuddys = new HashMap<String, buddyInfo>(); try { String[] resSplit = response.split("\r\n\r\n"); String xmlData = resSplit[1].replace("</results>SIPP", "</results>"); Document xml = DocumentHelper.parseText(xmlData); // 获取飞信好友 List buddys = xml.selectNodes("/results/contacts/buddies/buddy"); Iterator itb = buddys.iterator(); while (itb.hasNext()) { Element elt = (Element) itb.next(); Attribute uri = elt.attribute("uri"); Attribute localname = elt.attribute("local-name"); buddyInfo buddy = new buddyInfo(); buddy.uri = uri.getStringValue(); buddy.localname = localname.getStringValue(); buddy.buddytype = "buddy"; lstbuddys.put(buddy.uri, buddy); } // 获取手机好友 List mobiles = xml.selectNodes("/results/contacts/mobile-buddies/mobile-buddy"); Iterator itm = mobiles.iterator(); while (itm.hasNext()) { Element elt = (Element) itm.next(); Attribute uri = elt.attribute("uri"); Attribute localname = elt.attribute("local-name"); buddyInfo buddy = new buddyInfo(); buddy.uri = uri.getStringValue(); buddy.localname = localname.getStringValue(); buddy.buddytype = "mobile"; lstbuddys.put(buddy.uri, buddy); } } catch (Exception ex) { } return lstbuddys; } private String getUri(String mobile) { if (allBuddys.entrySet().size() == 0) getContactsInfo(); for (Entry<String, buddyInfo> entry : allBuddys.entrySet()) { if (entry.getValue().mobile.equals(mobile)) return entry.getKey(); } return null; } public boolean sendCatSms(String content) { return sendCatSms(null, content); } public boolean sendCatSms(String to, String content) { // T试了好像只能是标准的sip地址,不知道有没有什么办法能换成手机号,sip:[email protected];p=4009中4009的计算公式: // 13开头的手机号 // p=手机号码前6位 - 134099 // 15开头的手机号 // p=手机号码前6位 - 153099 // String toMobile = buddys.get(to); // if (toMobile == null || "".equals(toMobile)) // return false; String sendto = to; if (!to.startsWith("sip")) sendto = getUri(to); if (sendto == null) return false; HashMap<String, String> fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", nextCall()); fields.put("Q", "1 M"); fields.put("T", to == null ? uri : sendto); fields.put("N", "SendCatSMS"); String msg = createSipData(SIP_M, fields, content) + "SIPP"; sendRequest(nextUrl("s"), msg); String response = sendRequest(nextUrl("s"), "SIPP").response; if (response.indexOf("Send SMS OK") > 0) return true; else return false; } public boolean sendSms(String to, String content) { int len = content.length(); HashMap<String, String> fields = new HashMap<String, String>(); fields.put("F", sid); fields.put("I", nextCall()); fields.put("Q", "0 M"); fields.put("T", uri); fields.put("C", "text/html-fragment"); fields.put("K", "SaveHistory"); fields.put("L", String.valueOf(len)); String msg = createSipData(SIP_M, fields, content) + "SIPP"; String response = sendRequest(nextUrl("s"), msg).response; response = sendRequest(nextUrl("s"), "SIPP").response; if (response.indexOf("Send SMS OK") > 0) return true; else return false; } }