微信开发
微信开发现在用的比较多,大致讲一下微信公众号开发的流程,官方资料可查看微信公众号开发
一:java后台获取微信接口访问权限
1、获取开发公众号的openId(这里需要说明一下,一个用户对应不同的公众号有不同的openId,但是都可以唯一标识)
public String getOpenId(HttpServletRequest httprequest, HttpServletResponse response) { logger.info("开始获取用户openId"); String code = httprequest.getParameter("code"); String openId=""; if(StringUtils.checkStringEmpty(code)){ String url = "https://api.weixin.qq.com/sns/oauth2/access_token"; HttpRequestUtility httpRequestUtility = new HttpRequestUtility(); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("appid", SysConstantsConfig.WECHAT_APPID)); params.add(new BasicNameValuePair("secret", SysConstantsConfig.WECHAT_APPSECRET)); params.add(new BasicNameValuePair("code", code)); params.add(new BasicNameValuePair("grant_type", "authorization_code")); String result = httpRequestUtility.getResponsebyGet(url, params); if (StringUtils.checkStringEmpty(result)) { String errorCode = JsonUtility.getVauleFromJson("errcode", result); String errorMessage = JsonUtility.getVauleFromJson("errmsg", result); if (StringUtils.checkStringEmpty(errorCode) && !StringUtils.checkStringEmpty(errorMessage)) { logger.info("开始获取用户openId失败,返回错误码为 :" + errorCode + " 错误消息为 :" + errorMessage); } else { openId = JsonUtility.getVauleFromJson("openid", result); logger.info("开始获取用户openId成功,openId :" + openId); } } } return openId; }
Http请求发送:
public class HttpRequestUtility { private static final Logger logger = Logger .getLogger(HttpRequestUtility.class); public static String getResponsebyGet(String url, List<NameValuePair> params) { logger.info("开始执行HttpClient get 请求,请求URL为: "+url); String result = ""; HttpClient httpClient = new DefaultHttpClient(); // 连接时间 httpClient.getParams().setParameter( CoreConnectionPNames.CONNECTION_TIMEOUT, 3000); // 数据传输时间 httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 2000); // Get请求 HttpGet httpget = new HttpGet(url); try { // 设置参数 String str = EntityUtils.toString(new UrlEncodedFormEntity(params, "UTF-8")); httpget.setURI(new URI(httpget.getURI().toString() + "?" + str)); // 发送请求 HttpResponse httpResponse = httpClient.execute(httpget); int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { logger.error("执行HttpClient get 请求报错,statusCode为 : "+statusCode); } // 获取返回数据 HttpEntity entity = httpResponse.getEntity(); String body = EntityUtils.toString(entity, "utf-8"); result = body; if (entity != null) { EntityUtils.consume(entity); } } catch (Exception e) { } finally { httpClient.getConnectionManager().shutdown(); } logger.info("结束执行HttpClient get 请求,返回结果为: "+result); return result; } }
2、获取access_token
/** * 动态生成微信API access_token 调用微信提供的接口必须要这个属性 */ public String getaccessToken() { logger.info("开始动态生成access_token"); String accessToken = ""; String errorCode = ""; String errorMessage = ""; String url = "https://api.weixin.qq.com/cgi-bin/token"; HttpRequestUtility httpRequestUtility = new HttpRequestUtility(); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("grant_type", "client_credential")); params.add(new BasicNameValuePair("appid", SysConstantsConfig.WECHAT_APPID)); params.add(new BasicNameValuePair("secret", SysConstantsConfig.WECHAT_APPSECRET)); String response = httpRequestUtility.getResponsebyGet(url, params); if (StringUtils.checkStringEmpty(response)) { errorCode = JsonUtility.getVauleFromJson("errcode", response); errorMessage = JsonUtility.getVauleFromJson("errmsg", response); if (StringUtils.checkStringEmpty(errorCode) && !StringUtils.checkStringEmpty(errorMessage)) { logger.info("开始动态生成access_token失败,返回错误码为 :" + errorCode + " 错误消息为 :" + errorMessage); } else { accessToken = JsonUtility.getVauleFromJson("access_token", response); logger.info("开始动态生成access_token成功,accessToken :" + accessToken); } } return accessToken; }
3、获取jsapi_ticket(jsapi_ticket是公众号用于调用微信JS接口的临时票据)
/** * 动态生成微信API jsapi_ticket 调用微信JS提供的接口必须要这个属性 */ public String getjsapi_ticket(String accessToken) { logger.info("开始动态生成jsapi_ticket"); String ticket = ""; String errorCode = ""; String errorMessage = ""; String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; HttpRequestUtility httpRequestUtility = new HttpRequestUtility(); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("access_token", accessToken)); params.add(new BasicNameValuePair("type","jsapi")); String response = httpRequestUtility.getResponsebyGet(url, params); if (StringUtils.checkStringEmpty(response)) { errorCode = JsonUtility.getVauleFromJson("errcode", response); errorMessage = JsonUtility.getVauleFromJson("errmsg", response); if (StringUtils.checkStringEmpty(errorCode) &&!"0".equalsIgnoreCase(errorCode)) { logger.info("开始动态生成jsapi_ticket失败,返回错误码为 :" + errorCode + " 错误消息为 :" + errorMessage); } else { ticket = JsonUtility.getVauleFromJson("ticket",response); logger.info("开始动态生成jsapi_ticket成功,jsapi_ticket :" + ticket); } } return ticket; }
4、JS-SDK权限签名算法(获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了)
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
注意事项:
1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
2.签名用的url必须是调用JS接口页面的完整URL。
3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
/** * 获取签名 * @param ticket * @return */ public WechatConfig getSingnature(String ticket,String url){ SHA1 sha1=new SHA1(); WechatConfig wechatConfig=new WechatConfig(); String signature=""; String timestamp = System.currentTimeMillis()/1000+""; //获取时间戳 String noncestr = getRandomString(16); //获取随机字符串 signature = "jsapi_ticket="+ticket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url; signature = sha1.getDigestOfString(signature.getBytes()); //进行sha1加密 wechatConfig.setAppid(SysConstantsConfig.WECHAT_APPID); wechatConfig.setNonceStr(noncestr); wechatConfig.setSignature(signature); wechatConfig.setTimestamp(timestamp); return wechatConfig; } /** * 生成随机字符串 * @param length * @return */ public static String getRandomString(int length) { //length表示生成字符串的长度 String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); }
二:使用微信接口
1、前台JS调用
var iswechatBrowser; $(document).ready(function(){ var ua = window.navigator.userAgent.toLowerCase(); //识别微信浏览器 if(ua.match(/MicroMessenger/i) == 'micromessenger'){ iswechatBrowser=true; }else{ iswechatBrowser=false; } if(iswechatBrowser){ //如果是微信浏览器就去配置微信JS接口 var currenturl = location.href.split('#')[0]; var sharedTitle = "慧英保险"; var imageUrl; $.ajax({ type: "POST", url: getPath()+"/WechatLogin/getWechatJSAccess.do", data:currenturl ,//将对象序列化成JSON字符串 dataType:"json", contentType:'application/json;charset=utf-8', //设置请求头信息 success: function(data){ var sharedLink = data.sharedLink; wx.config({ debug: false, appId: data.appid, // 必填,公众号的唯一标识 timestamp:data.timestamp , // 必填,生成签名的时间戳 nonceStr: data.nonceStr, // 必填,生成签名的随机串 signature: data.signature.toLowerCase(), // 必填,签名,见附录1 jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填,需要使用的JS接口列表 }); wx.ready(function(){ //实现JS分享功能 wx.onMenuShareTimeline({//1.获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 title: sharedTitle, // 分享标题 link: sharedLink, // 分享链接 imgUrl: imageUrl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareAppMessage({//2.获取“分享给朋友”按钮点击状态及自定义分享内容接口 title: sharedTitle, // 分享标题 desc: "http://m.quicksure.com/ludiquickSureMobileServer", // 分享描述 link: sharedLink, // 分享链接 imgUrl: imageUrl, // 分享图标 type: '', // 分享类型,music、video或link,不填默认为link dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); }); }, error: function(res){ $("#pop").hide(); $("#Message").html("微信登录失败"); $('.errorhei').show(); $('.beijing').hide(); } }); } });
注意:wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
2、后台生成权限签名
@RequestMapping("/getWechatJSAccess.do")
public @ResponseBody WechatConfig getWechatJSAccess(@RequestBody String url,
HttpServletRequest httprequest,HttpServletResponse response,ModelMap modelMap){
logger.info("get URL is:"+url);
HttpSession session = httprequest.getSession();
WechatConfig wechatConfig = null;
String ticket="";
String token="";
if(session!=null&&session.getAttribute("token")!=null){
token=(String) session.getAttribute("token");
session.setAttribute("token", token);
}else{
token=wechatLoginServiceImpl.getaccessToken();
}
if(session!=null&&session.getAttribute("ticket")!=null){
ticket=(String)session.getAttribute("ticket");
}else{
if(StringUtils.checkStringEmpty(token)){
ticket=wechatLoginServiceImpl.getjsapi_ticket(token);
session.setAttribute("ticket", ticket);
}
}
if(StringUtils.checkStringEmpty(ticket)){
wechatConfig = wechatLoginServiceImpl.getSingnature(ticket,url);
}
return wechatConfig;
}
微信链接分享开发可以参考:http://blog.csdn.net/zhengyangzkr/article/details/70187486

浙公网安备 33010602011771号