微信公众号智能绑定实现步骤:
微信公众号智能绑定功能所有的步骤都是以模拟实现的。具体实现过程如下:
1.智能绑定核心类:
import java.io.IOException; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; import org.oms.wechat.pojo.WechatAccountInfo; import org.oms.wechat.pojo.WechatDevInfo; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; /** * 智能绑定核心类 * * @author sunlight * */ public class SmartBindUtil { public final static Log log = LogFactory.getLog(SmartBindUtil.class); // 微信URL public final static String HOST_URL = "https://mp.weixin.qq.com"; // 微信登陆地址 public final static String LOGIN_URL = "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN"; // 微信登出地址 public final static String LOGOUT_URL = "http://mp.weixin.qq.com/cgi-bin/logout?t=wxm-logout&lang=zh_CN&token="; // 主页地址 public final static String INDEX_URL = "http://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token="; // 微信账号信息 public final static String ACCOUNT_INFO_URL = "http://mp.weixin.qq.com/cgi-bin/settingpage?t=setting/index&action=index&lang=zh_CN&token="; // 开发者页面地址 public final static String DEV_URL = "https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&lang=zh_CN&token="; // 切换开发模式 public final static String DEV_UPDATE_RUL = "https://mp.weixin.qq.com/misc/skeyform?form=advancedswitchform&lang=zh_CN&flag=1&type=2"; // 服务器配置提交地址 public final static String DEV_SERVICE_URL = "https://mp.weixin.qq.com/advanced/callbackprofile?t=ajax-response&lang=zh_CN&token="; // 获取ACCESS_TOKEN接口 public final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; // 获取粉丝列表 public final static String FANS_URL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s"; // 获取粉丝信息 public final static String FANS_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN"; // 删除自定义菜单 public final static String MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s"; // 创建自定义菜单 public final static String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s"; // 模拟请求所用的参数设置 public final static String COOKIE_H = "Cookie"; public final static String CONNECTION_H = "Connection"; public final static String CONNECTION = "keep-alive"; public final static String HOST_H = "Host"; public final static String HOST = "mp.weixin.qq.com"; public final static String REFERER_H = "Referer"; public final static String REFERER = "https://mp.weixin.qq.com/"; public final static String USER_AGENT_H = "User-Agent"; public final static String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"; public final static String ACCEPT_H = "Accept"; public final static String ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; public final static String ACCEPT_ENCODEING_H = "Accept-Encoding"; public final static String ACCEPT_ENCODEING = "gzip,deflate,sdch"; public final static String ACCEPT_LANGUAGE_H = "Accept-Language"; public final static String ACCEPT_LANGUAGE = "zh-CN,zh;q=0.8"; public final static String CONTENT_TYPE_H = "Content-Type"; public final static String CONTENT_TYPE = "application/x-www-form-urlencoded; charset=UTF-8"; public final static String XMLHTTP_REQUEST_H = "X-Requested-With"; public final static String XMLHTTP_REQUEST = "XMLHttpRequest"; public final static String UTF_8 = "UTF-8"; private HttpClient client = new HttpClient(); private boolean isLogin = false; private String cookiestr; private String loginUser; private String loginPwd; private String token; public SmartBindUtil(String loginUser, String loginPwd) { super(); this.loginUser = loginUser; this.loginPwd = loginPwd; } /** * 得到AppId,AppSecret * * @return */ public WechatDevInfo getWechatDev() { int staus = login(); if (staus == HttpStatus.SC_OK) { isLogin = true; return getWechatDevInfo(); } else { return null; } } public int login() { if (isLogin) { return HttpStatus.SC_OK; } PostMethod post = new PostMethod(LOGIN_URL); setHeader(post); setLoginParams(post); log.info("正在登陆微信公众平台..."); try { System.setProperty("jsse.enableSNIExtension", "false"); int status = client.executeMethod(post); if (status == HttpStatus.SC_OK) { log.info("登陆成功"); String res = post.getResponseBodyAsString(); JSONObject retcode = JSON.parseObject(res); int ret = Integer.parseInt(retcode.getJSONObject("base_resp") .getString("ret")); if (ret == 0) { log.info("微信端验证成功"); Cookie[] cookies = client.getState().getCookies(); StringBuffer cookie = new StringBuffer(); for (Cookie c : cookies) { cookie.append(c.getName()).append("=") .append(c.getValue()).append(";"); } this.cookiestr = cookie.toString(); log.info("正在获取token..."); String redirect_url = retcode.getString("redirect_url"); if (redirect_url != null && redirect_url.trim().length() > 0) { String[] ss = StringUtils.split(redirect_url, "?"); String[] ps = null; if (ss.length == 2) { if (!StringUtils.isBlank(ss[1]) && ss[1].indexOf("&") != -1) ps = StringUtils.split(ss[1], "&"); } else if (ss.length == 1) { if (!StringUtils.isBlank(ss[0]) && ss[0].indexOf("&") != -1) ps = StringUtils.split(ss[0], "&"); } if (ps != null) { for (String p : ps) { if (StringUtils.isBlank(p)) { continue; } String[] tk = StringUtils.split(p, "="); if (tk[0] != null && "token".equals(tk[0].trim() .toLowerCase())) { token = tk[1]; break; } } } log.info("获取token成功..."); } log.info("正在进入微信首页..."); return index(); } else { log.info("微信端验证失败code: " + ret); return ret; } } else { System.err.println("Method failed: " + post.getStatusLine()); log.info("网络连接错误"); return -1; } } catch (Exception e) { log.error(e.getMessage(), e); e.printStackTrace(); return -1; } finally { post.releaseConnection(); } } /** * 切换开发模式/编辑模式 * * @param flag * 开启1关闭0 * @param type * 开发模式2编辑模式1 * @return */ public Result<Integer> enabledDev(int flag, int type) { Result<Integer> result = new Result<Integer>(); int staus = login(); if (staus == HttpStatus.SC_OK) { isLogin = true; PostMethod post = new PostMethod(DEV_UPDATE_RUL); setHeader(post); NameValuePair[] params = new NameValuePair[] { new NameValuePair("flag", "" + flag), new NameValuePair("type", "" + type), new NameValuePair("token", token) }; post.setRequestBody(params); try { log.info("正在切换开发模式/编辑模式..."); staus = client.executeMethod(post); if (staus == HttpStatus.SC_OK) { log.info("服务器连接成功"); String res = post.getResponseBodyAsString(); JSONObject retcode = JSON.parseObject(res); JSONObject base = retcode.getJSONObject("base_resp"); result.setObject(Integer.parseInt(base.getString("ret"))); result.setMsg(base.getString("err_msg")); } else { result.setObject(staus); result.setMsg("网络连接错误,请稍后再试"); } } catch (Exception e) { log.error(e.getMessage(), e); result.setObject(staus); result.setMsg("网络连接错误,请稍后再试"); } finally { post.releaseConnection(); } } else { result.setObject(staus); result.setMsg("服务器登陆失败,请稍后再试"); } return result; } /** * 设置开发模式,服务器回调 * * @param url * @param callback_token * @return */ public Result<Integer> setDevServiceUrl(String url, String callback_token) { Result<Integer> result = new Result<Integer>(); int staus = login(); if (staus == HttpStatus.SC_OK) { isLogin = true; PostMethod post = new PostMethod(DEV_SERVICE_URL + token); setHeader(post); NameValuePair[] params = new NameValuePair[] { new NameValuePair("url", "" + url), new NameValuePair("callback_token", callback_token) }; post.setRequestBody(params); try { log.info("正在设置公众平台回调..."); staus = client.executeMethod(post); if (staus == HttpStatus.SC_OK) { log.info("服务器连接成功"); String res = post.getResponseBodyAsString(); // TODO............ System.out.println("res========" + res); JSONObject retcode = JSON.parseObject(res); staus = Integer.parseInt(retcode.getString("ret")); result.setObject(Integer.parseInt(retcode.getString("ret"))); result.setMsg(retcode.getString("msg")); } else { result.setObject(staus); result.setMsg("网络连接错误,请稍后再试"); } } catch (Exception e) { log.info(e.getMessage(), e); result.setObject(staus); result.setMsg("网络连接错误,请稍后再试"); } finally { post.releaseConnection(); } } else { result.setObject(staus); result.setMsg("服务器登陆失败,请稍后再试"); } return result; } /** * 得到微信公众平台个人信息 * * @return */ public WechatAccountInfo getAccount() { // TODO获取微信账号基本信息 log.info("获取账户信息..."); WechatAccountInfo account = null; GetMethod get = new GetMethod(ACCOUNT_INFO_URL + token); setHeader(get); try { int status = client.executeMethod(get); if (status == HttpStatus.SC_OK) { log.info("已经连接,正在接收数据"); String res = get.getResponseBodyAsString(); Document doc = Jsoup.parseBodyFragment(res); Elements eles = doc.select("#settingArea .meta_content"); if (eles != null && eles.size() > 0) { account = new WechatAccountInfo(); account.setAccountName(eles.get(0).text()); account.setHeadImage(HOST_URL + eles.get(1).select("img").attr("src")); account.setAccountId(eles.get(3).text()); account.setWechatNumber(eles.get(4).text()); account.setType(eles.get(5).text()); account.setAuthenticate(eles.get(6).text()); } } } catch (Exception e) { log.error("网络连接发生错误", e); } finally { get.releaseConnection(); } return account; } /** * 得到AppId,AppSecret * * @return */ public WechatDevInfo getWechatDevInfo() { // TODO 得到AppId,AppSecret log.info("获取appid,appsecret信息..."); WechatDevInfo devInfo = null; GetMethod get = new GetMethod(DEV_URL + token); setHeader(get); try { int status = client.executeMethod(get); if (status == HttpStatus.SC_OK) { log.info("已经连接,正在接收数据"); String res = get.getResponseBodyAsString(); Document doc = Jsoup.parseBodyFragment(res); Elements eles = doc.select(".developer_info_wrp"); if (eles != null && eles.size() > 0) { Elements datas = eles.select(".frm_vertical_pt"); devInfo = new WechatDevInfo(); devInfo.setAppId(datas.get(0).text()); devInfo.setAppSecret(datas.get(1).text() .replaceAll("重置", "").trim()); } } } catch (Exception e) { e.printStackTrace(); } finally { get.releaseConnection(); } return devInfo; } /** * 登出操作 * * @return 异常CODE * @throws HttpException * @throws IOException */ public int logout() throws HttpException, IOException { log.info("退出服务..."); GetMethod get = new GetMethod(LOGOUT_URL + token); setHeader(get); int status = client.executeMethod(get); get.releaseConnection(); return status; } /** * 进入微信首页 * * @return 异常CODE * @throws HttpException * @throws IOException */ private int index() throws HttpException, IOException { GetMethod get = new GetMethod(INDEX_URL + token); setHeader(get); int status = client.executeMethod(get); get.releaseConnection(); return status; } private void setHeader(PostMethod post) { post.setRequestHeader(CONNECTION_H, CONNECTION); post.setRequestHeader(HOST_H, HOST); post.setRequestHeader(REFERER_H, REFERER); post.setRequestHeader(USER_AGENT_H, USER_AGENT); if (this.cookiestr != null && this.cookiestr.length() > 0) { post.setRequestHeader(COOKIE_H, this.cookiestr); } } private void setHeader(GetMethod get) { get.setRequestHeader(CONNECTION_H, CONNECTION); get.setRequestHeader(HOST_H, HOST); get.setRequestHeader(REFERER_H, REFERER); get.setRequestHeader(USER_AGENT_H, USER_AGENT); if (this.cookiestr != null && this.cookiestr.length() > 0) { get.setRequestHeader(COOKIE_H, this.cookiestr); } } private void setLoginParams(PostMethod post) { post.setRequestHeader(CONTENT_TYPE_H, CONTENT_TYPE); post.setRequestHeader(XMLHTTP_REQUEST_H, XMLHTTP_REQUEST); NameValuePair[] params = new NameValuePair[] { new NameValuePair("username", this.loginUser), new NameValuePair("pwd", DigestUtils.md5Hex(this.loginPwd .getBytes())), new NameValuePair("f", "json"), new NameValuePair("imgcode", "") }; post.setQueryString(params); } }
import org.oms.wechat.pojo.WechatAccountInfo; import org.oms.wechat.pojo.WechatDevInfo; /** * 智能绑定执行类 * @author Sunlight * */ public class WechatBind { private static String msg; private static String url="http://omsvip.sinaapp.com/coreServlet"; private static String token="weixinCourse"; public static String SmartBind(String username, String password) { // 开始绑定帐号 // 初始化登录信息 SmartBindUtil smartBind = new SmartBindUtil(username, password); //登录成功后,在开发者中心获取开发者ID(AppId、AppSecret) WechatDevInfo devInfo=smartBind.getWechatDev(); System.out.println("devInfo="+devInfo); //获取微信公众号设置基本信息(名称、头像、类型、认证情况等) WechatAccountInfo account = smartBind.getAccount(); if (account == null) { msg = "{success:false,msg:\"登陆微信服务器失败,请检查用户名/密码是否正确\"}"; } System.out.println("account="+account); // 启动开发模式 if (msg == null) { Result<Integer> result = smartBind.enabledDev(1, 2); if (result.getObject() != 0) { msg = "{success:false,msg:\"" + result.getMsg() + "\"}"; } } // 验证服务器接口回调,此处修改服务器配置中的URL和Token if (msg == null) { Result<Integer> result = smartBind.setDevServiceUrl(url, token); if (result.getObject() != 0) { msg = "{success:false,msg:\"" + result.getMsg() + "\"}"; } } if(msg==null){ msg="智能绑定成功!"; } return msg; } }
需要用到的2个Pojo 公众号信息类,代码如下:
/** * 微信账号基本信息 * * @author sunlight * */ public class WechatAccountInfo { /** * 原始ID */ private String accountId; /** * 名称 */ private String accountName; /** * 微信头像 */ private String headImage; /** * 微信号 */ private String wechatNumber; /** * 账号类型 */ private String type; /** * 认证情况 */ private String authenticate; public String getAccountId() { return accountId; } public void setAccountId(String accountId) { this.accountId = accountId; } public String getAccountName() { return accountName; } public void setAccountName(String accountName) { this.accountName = accountName; } public String getHeadImage() { return headImage; } public void setHeadImage(String headImage) { this.headImage = headImage; } public String getWechatNumber() { return wechatNumber; } public void setWechatNumber(String wechatNumber) { this.wechatNumber = wechatNumber; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getAuthenticate() { return authenticate; } public void setAuthenticate(String authenticate) { this.authenticate = authenticate; } @Override public String toString() { return "WechatAccountInfo [accountId=" + accountId + ", accountName=" + accountName + ", headImage=" + headImage + ", wechatNumber=" + wechatNumber + ", type=" + type + ", authenticate=" + authenticate + "]"; } }
/** * 微信开发者信息 * * @author sunlight * */ public class WechatDevInfo { private String appId; private String appSecret; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getAppSecret() { return appSecret; } public void setAppSecret(String appSecret) { this.appSecret = appSecret; } @Override public String toString() { return "WechatDevInfo [appId=" + appId + ", appSecret=" + appSecret + "]"; } }
注意:因为微信公众号页面等相关调整频繁,因此智能绑定微信公众号只是模拟用户登录,所以微信公众号官网页面等相关信息发生变化会导致智能绑定功能失效!
因此,微信修改一次我们的代码也会变化一次。
本文章因时间问题,编写的的不是很完美,等有时间重新整理一份!
本人微信公众号:PainPoint
扫描二维码关注我.