关于微信的分享功能
微信分享相关的可以查看相关的微信文档,这里给出我的代码,可以参考。
首先微信有默认的分享,他分享的是当前页面。
但是有很多微信web,无论哪个页面分享的都是同一个链接,这个,就需要代码实现
首先,需要ticket,ticket是分享必须的一个参数,但是获取他,就必须先要获取tocken,这里给出代码。
//获取tocken
public void getAccessToken() { String urlNameString = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + WalletUtils.GRANT_TYPE + "&appid=" + WalletUtils.APPID + "&secret=" + WalletUtils.SECRET; //微信的url String str = sendGet(urlNameString); // get请求 JSONObject json = JSONObject.parseObject(str);// 返回值封装 String access_token = String.valueOf(json.get("access_token")); if (access_token != null) { try { memcachedClient.set("ACCESS_TOKEN", 0, access_token); //我这里吧tockne放到了memcached里了,你们可以自行存储 log.info("memcached存储的数据为:" + access_token); String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi"; getTicket(url); } catch (Exception e) { log.info("memcachedClient获取数据异常" + e); throw new BusinessException("memcachedClient获取数据异常"); } }else{ String errcode = String.valueOf(json.get("errcode")); if(errcode!=null){ log.info("获取access_token错误,错误码为:"+errcode); throw new BusinessException("获取access_token错误"); }else{ log.info("访问微信接口无响应"); throw new BusinessException("访问微信接口无响应"); } } } //同上,只不过,这个需要tocken来获取ticket,这里同样放到memcached里 public void getTicket(String url){ String jsonstr = sendGet(url); JSONObject json = JSONObject.parseObject(jsonstr); String ticket = String.valueOf(json.get("ticket")); if (ticket != null) { try { memcachedClient.set("TICKET", 0, ticket); log.info("memcached存储的数据为:" + ticket); } catch (Exception e) { log.info("memcachedClient获取数据异常" + e); throw new BusinessException("memcachedClient获取数据异常"); } }else{ log.info("获取ticket错误,错误码为:"); throw new BusinessException("获取ticket错误"); } } public String sendGet(String url) { String result = ""; BufferedReader in = null; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { log.info("发送Get请求异常:"+e); throw new BusinessException("发送Get请求异常"); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { log.info("关闭流异常:"+e2); throw new BusinessException("关闭流异常"); } } return result; }
以上,我放到了定时任务里,因为tocken和ticket的有效期为7200秒,重复获取可能引起冲突,所以我这是一个专门跑批的任务。
一下是分享的前端部分
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE html> <html lang="zh-CN"> <script type="text/javascript" src="./js/jweixin-1.0.0.js"></script> <script type="text/javascript" src="./js/jquery-1.7.2.min.js"></script> <script type="text/javascript"> var title = ''; var desc = ''; var imgUrl = ''; var link = ''; wx.ready(function(){ wx.onMenuShareAppMessage({ title: title, // 分享标题 desc: desc,// 分享描述 link: link,// 分享链接 imgUrl: imgUrl }); wx.onMenuShareTimeline({ title: title, // 分享标题 link: link,// 分享链接 imgUrl: imgUrl }); wx.onMenuShareQQ({ title: title, // 分享标题 desc: desc, // 分享描述 link: link, // 分享链接 imgUrl: imgUrl }); wx.onMenuShareWeibo({ title: title, // 分享标题 desc: desc, // 分享描述 link: link, // 分享链接 imgUrl: imgUrl }); wx.onMenuShareQZone({ title: title, // 分享标题 desc: desc, // 分享描述 link: link, imgUrl: imgUrl }); }); $(document).ready(function(){ var url = window.location.href; $.ajax({ url:'<%=basePath%>rest/walletFxController/fxIndex',// 跳转到 action data : { url : url }, type : 'get', dataType : 'json', success : function(data) { var obj = eval(data); title = obj.title; desc = obj.desc; imgUrl = '<%=basePath%>'+obj.imgUrl; link = obj.link; wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: obj.appId, // 必填,公众号的唯一标识 timestamp: obj.timestamp, // 必填,生成签名的时间戳 nonceStr: obj.nonceStr, // 必填,生成签名的随机串 signature: obj.signature,// 必填,签名,见附录1 jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); } }); }); </script> <head> <meta charset="UTF-8"> <body> <h1>404</h1> </body> </html>
我这里试了下,不能放在includ里和js文件里,只能直接放在jsp,大家可以自己测试下。
下面是java部分。
@Controller @RequestMapping("/walletFxController") public class WalletFxController { @Autowired private MemcachedClient memcachedClient; @RequestMapping("/fxIndex") public void fxIndex(HttpServletRequest request,HttpServletResponse response){ String ticket = ""; try { ticket = memcachedClient.get("TICKET"); } catch (Exception e) { e.printStackTrace(); } String strBackUrl = request.getParameter("url"); String time = WeixinUtil.getTimestamp(); String noncestr = WeixinUtil.getNoncestr(12); // String signature = WeixinUtil.Getsignature(strBackUrl,"wxa916d2eaf629ac6c", "d4624c36b6795d1d99dcf0547af5443d",noncestr,time, ticket); String signature = WeixinUtil.getSignature(strBackUrl,noncestr,time,ticket); Map<String,Object> map = new HashMap<String, Object>(); map.put("appId", WeiXinConfig.APPID); map.put("link", strBackUrl); map.put("title", WeiXinConfig.TITLE); map.put("desc", WeiXinConfig.DESC); map.put("imgUrl", WeiXinConfig.IMGURL); // map.put("appId", "wxa916d2eaf629ac6c"); map.put("timestamp", time); map.put("nonceStr", noncestr); map.put("signature", signature); String json = JSONObject.fromObject(map).toString(); try { PrintWriter pw = response.getWriter(); pw.write(json); pw.flush(); pw.close(); } catch (IOException e) { e.printStackTrace(); } } }
微信要求的参数有:
分享url,这里我只是简单的用js获取了下当前的。
随机字符串:可以混合数字,貌似是不长于32为
时间戳:1970年到现在的秒数,注意:不是毫秒
ticket:刚才有获取。
他要求,把这些参数按照ACSII排序并组合,再进行SHA1加密。
可以查看代码。
/** * 生成singature,需要把所有参数ACSII排序后,用SHA1加密 * @param strBackUrl 请求的url * @param noncestr 随机字符串 * @param time 时间戳 * @param ticket 从微信官方请求来的参数 * @return */ public static String getSignature(String strBackUrl, String noncestr, String time, String ticket) { String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + time + "&url=" + strBackUrl; System.out.println("url:"+str); String singature = getSHA1(str); System.out.println("singature:"+singature); String ss = singature; return ss; }
/** * SHA1加密 * @param decript * @return */ public static String getSHA1(String decript) { try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(decript.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字节数组转换为 十六进制 数 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; }
public static String getTimestamp(){ Date date = new Date(); return date.getTime()/1000+""; } public static String getNoncestr(int 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(); }
测试这个需要耐心,微信官方有提供各种测试工具,可以测试。
需要配置js安全域名,这个不能加http,二级域名需要把第一个点前面都去掉。