使用说明:
在使用微信JS-SDK之前必须确认公众号已经获得使用微信js接口的权限,并且已填写安全域名,可登陆微信公众号平台查看。
1、引入微信js
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
2、根据需求添加js功能
<script type="text/javascript"> var id = '${id}';//服务端设置的id,用于下面拼接生成需要分享的link var timestamp = parseInt('${ret.timestamp}');//因为服务端是String类型,此处转化成数值类型 var nonceStr = '${ret.nonceStr}'; var signature = '${ret.signature}'; wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: 'wxa034b7003154ee6c', // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature,// 必填,签名,见附录1 jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 wx.onMenuShareTimeline({ title: 'xxxxxxxxxxxxx', // 分享标题 link: 'http://www.xxxxx.com:8082/xxx/xxx.do?id='+id, // 分享链接 imgUrl: 'http://www.xxxxx.com:8080/xxx/xxx.jpg', // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareAppMessage({ title: 'xxxxxxx', // 分享标题 desc: 'xxxxxxx', // 分享描述 link: 'http://www.xxxxx.com:8082/xxx/xxx.do?id='+id, // 分享链接 imgUrl: 'http://www.xxxxx.com:8080/xxx/xxx.jpg', // 分享图标 type: '', // 分享类型,music、video或link,不填默认为link dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); }); </script>
生成js页面需要的参数 及签名的生成:
1、获取access_token, 因为一般有效期是7200s,所以添加到了ehcache中,默认先从缓存中获取,失效后再发送GET请求获取
Object act = EhcacheUtil.getInstance().get("weixin_jsapi", "access_token"); Object apiticket = EhcacheUtil.getInstance().get("weixin_jsapi", "ticket"); logger.debug("[act] = " + act + " [apiticket] = " + apiticket); if (null == act) { String url = "https://api.weixin.qq.com/cgi-bin/token"; String jsonStrToken = Tools.sendGet(url, "grant_type=client_credential&appid="+ appId + "&secret=" + appSecret); logger.debug("[jsonStrToken] = " + jsonStrToken); JSONObject json = JSONObject.fromObject(jsonStrToken); access_token = (String) json.getString("access_token"); if (access_token == null) { return null; } EhcacheUtil.getInstance().put("weixin_jsapi", "access_token", access_token); } else { access_token = (String) act; }
2、根据上一步中的access_token获取jsapi_ticket:
if (null == apiticket) { String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; String jsonStrTicket = Tools.sendGet(url, "access_token=" + access_token + "&type=jsapi"); logger.debug("[jsonStrTicket] = " + jsonStrTicket); JSONObject json = JSONObject.fromObject(jsonStrTicket); ticket = (String) json.get("ticket"); } else { ticket = (String) apiticket; }
3、获取当前需要分享的网页的URL:
//获取URL String url = request.getRequestURL().toString();
4、最终生成签名:
(1)获取时间戳:
private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); }
(2)获取随机字符串:
private static String create_nonce_str() { return UUID.randomUUID().toString(); }
(3)将jsapi_ticket、noncestr、timestamp、url拼接,使用SHA1加密算法,最终生成签名
// 注意这里参数名必须全部小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; logger.debug("[string1] = " + string1); try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); logger.debug("[signature] = " + signature); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
5、将服务端生成的noncestr、timestamp、signature设置到model(使用的是spring mvc)中,返回到页面:
Map<String, String> ret = sign.sign(jsapi_ticket, url); mav.addObject("ret", ret); var timestamp = parseInt('${ret.timestamp}'); var nonceStr = '${ret.nonceStr}'; var signature = '${ret.signature}'; wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: 'wxa034b7003154ee6c', // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature,// 必填,签名,见附录1 jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 });
完整的服务端代码:
1、controller层:
//获取ticket String jsapi_ticket = weiXinRequest.getWeiXinTicket(); logger.debug("[jsapi_ticket] = " + jsapi_ticket); //获取URL String url = request.getRequestURL().toString(); Map<String, String> ret = sign.sign(jsapi_ticket, url); mav.addObject("ret", ret); logger.debug("[ret] = " + ret); return mav;
2、weiXinRequest
import net.sf.json.JSONObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Component; @Component("WeiXinRequest") public class WeiXinRequest { private String appId = "wxa034b7003154ee6c"; private String appSecret = "7fce4f1ee0f63b62f20fe8321a31dea8"; private Log logger = LogFactory.getLog(WeiXinRequest.class); public String getWeiXinTicket() throws Exception { String access_token = ""; String ticket = ""; Object act = EhcacheUtil.getInstance().get("weixin_jsapi", "access_token"); Object apiticket = EhcacheUtil.getInstance().get("weixin_jsapi", "ticket"); logger.debug("[act] = " + act + " [apiticket] = " + apiticket); if (null == act) { String url = "https://api.weixin.qq.com/cgi-bin/token"; String jsonStrToken = Tools.sendGet(url, "grant_type=client_credential&appid="+ appId + "&secret=" + appSecret); logger.debug("[jsonStrToken] = " + jsonStrToken); JSONObject json = JSONObject.fromObject(jsonStrToken); access_token = (String) json.getString("access_token"); if (access_token == null) { return null; } EhcacheUtil.getInstance().put("weixin_jsapi", "access_token", access_token); } else { access_token = (String) act; } if (null == apiticket) { String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; String jsonStrTicket = Tools.sendGet(url, "access_token=" + access_token + "&type=jsapi"); logger.debug("[jsonStrTicket] = " + jsonStrTicket); JSONObject json = JSONObject.fromObject(jsonStrTicket); ticket = (String) json.get("ticket"); } else { ticket = (String) apiticket; } return ticket; // 断开连接 } }
3、Sign签名类:
import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Formatter; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component("Sign") public class Sign { @Autowired private WeiXinRequest weiXinRequest; private Log logger = LogFactory.getLog(Sign.class); public Map<String, String> test(HttpServletRequest requesturl) throws Exception { String ticket = weiXinRequest.getWeiXinTicket(); // 注意 URL 一定要动态获取,不能 hardcode String url = requesturl.getRequestURL().toString(); Map<String, String> ret = sign(ticket, url); for (Map.Entry entry : ret.entrySet()) { System.out.println(entry.getKey() + ", " + entry.getValue()); } // ret.put("appId", weiXinRequest.appId); return ret; }; public Map<String, String> sign(String jsapi_ticket, String url) { Map<String, String> ret = new HashMap<String, String>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; // 注意这里参数名必须全部小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; logger.debug("[string1] = " + string1); try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); logger.debug("[signature] = " + signature); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret.put("url", url); ret.put("jsapi_ticket", jsapi_ticket); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); logger.debug("[ret] = " + ret); return ret; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } private static String create_nonce_str() { return UUID.randomUUID().toString(); } private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } /** * 用SHA1算法生成安全签名 * * @param token * 票据 * @param timestamp * 时间戳 * @param nonce * 随机字符串 * @param encrypt * 密文 * @return 安全签名 * @throws NoSuchAlgorithmException * @throws AesException */ public String getSHA1(String token, String timestamp, String nonce) throws NoSuchAlgorithmException { String[] array = new String[] { token, timestamp, nonce }; StringBuffer sb = new StringBuffer(); // 字符串排序 Arrays.sort(array); for (int i = 0; i < 3; i++) { sb.append(array[i]); } String str = sb.toString(); // SHA1签名生成 MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(str.getBytes()); byte[] digest = md.digest(); StringBuffer hexstr = new StringBuffer(); String shaHex = ""; for (int i = 0; i < digest.length; i++) { shaHex = Integer.toHexString(digest[i] & 0xFF); if (shaHex.length() < 2) { hexstr.append(0); } hexstr.append(shaHex); } return hexstr.toString(); } }
4、发送请求类Tools 这里用的是 Url 、UrlConnection 类 类似于httpClient
/** * 向指定URL发送GET方法的请求 * * @param url * 发送请求的URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; }
相关推荐
分享接分享接口sdk
基于springBoot2.0以上的微信分享接口后端实现,代码绝对可复用,稍加修改就可以为您所用
php实现微信分享接口 自己在用的 有需要的可以下载看看
本文将深入探讨微信JS-SDK中的微信分享接口开发,旨在帮助开发者解决在微信环境下实现分享功能时遇到的问题。 首先,微信JS-SDK是微信官方提供的JavaScript库,它允许开发者调用微信的一系列功能,如分享、支付、扫...
微信JS-SDK 微信分享接口开发 代码包微信JS-SDK 微信分享接口开发 代码包
本人新手,有大神帮助写了一个没有在html请求微信jssdk接口做的微信分享,希望有用
在本文中,我们将深入探讨如何在Discuz论坛中利用DZ官方微信登录接口设置开发者中心URL和TOKEN,并将系统接入TOM微信运营平台,以便提升微信用户的登录体验和论坛的运营效率。 首先,让我们理解一下核心概念。微信...
主要为大家详细介绍了js微信分享接口调用的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
【描述】描述中提到的"微信分享接口"是微信官方提供的JavaScript SDK(Software Development Kit),它允许开发者通过调用特定的API来实现网页内容在微信内的分享。通过引入PHP文件,开发者可以在服务器端处理与微信...
同时,由于描述中提到的“论坛运行在服务器上”,这意味着论坛必须部署在支持HTTPS的服务器上,因为微信分享接口要求调用的页面必须是安全的HTTPs链接。 总的来说,“Cack!微信分享图标”是一个提升DZ论坛用户体验...
接下来,涉及到微信分享接口的集成。微信提供了官方的SDK,包含各种分享功能,如文本、图片、网页等。开发者需要在项目中引入微信SDK,注册应用并获取AppID,然后在代码中配置分享参数。对于图片分享,需要将之前...
在开发微信应用时,微信分享接口是至关重要的一个部分,它允许用户在微信内部或微信浏览器中分享内容到他们的朋友圈或者微信好友。本实例将详细解释如何在ThinkPHP框架下集成微信分享接口JSSDK(JavaScript SDK)的...
"wxshareapi"很可能是一个包含微信分享功能相关的类库或模块,它封装了调用微信分享接口所需的方法。开发者需要按照微信官方文档的要求,进行相应的配置,包括获取AppID和AppSecret,注册应用,然后在代码中调用接口...
本文将详细解析“微信分享后端接口”的实现,并探讨与之相关的技术知识点,包括微信分享、微信API的使用、IO流处理以及线程锁。 首先,微信分享是指通过微信平台将应用程序内的内容(如文章、图片、链接等)分享到...
本资源使用spring mvc框架,如果使用ssh框架,可以使用...另外这个主要是微信公众号的开发,如果是微信企业号后续会有上传专门示例的,已经实现的功能有url验证,自定义菜单创建删除,常用高级接口的使用等。