js源代码:

<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js" ></script>
	<script type="text/javascript">
		var chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
		function generateMixed(n) {
		     var res = "";
		     for(var i = 0; i < n ; i ++) {
		         var id = Math.ceil(Math.random()*35);
		         res += chars[id];
		     }
		     return res;
		}
		
		var timestamp = new Date().getTime();
		var nonceStr = generateMixed(16);
		var url = window.location.href;
		
		$(function(){
			$.ajax({
        		type: "POST",
            	url: "/user/ajax_do_signature",
            	data: {"timestamp":timestamp, "nonceStr":nonceStr, "url":url},
           		dataType:'json',
            	success: function(data){
            		console.log("分享签名 : " + data.items);
            		wx.config({
					    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
					    appId: 'wx3fab5f07a024a1ba', 
					    timestamp: timestamp, //必填,生成签名的时间戳
					    nonceStr: nonceStr, // 必填,生成签名的随机串
					    signature: data.items,// 必填,签名,见附录1
					    jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
					});
					
					wx.ready(function(){
					    // 分享到朋友圈
						wx.onMenuShareTimeline({
						    title: '大众点股分享测试标题', // 分享标题
						    link: url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
						    imgUrl: 'http://dud2.dataudata.com/static/images/qmdg.jpg', // 分享图标
						    success: function () { 
						        // 用户确认分享后执行的回调函数
						    },
						    cancel: function () { 
						        // 用户取消分享后执行的回调函数
						    }
						});
						
						// 分享给朋友
						wx.onMenuShareAppMessage({
						    title: '大众点股分享测试标题', // 分享标题
						    desc: '大众点股分享描述测试', // 分享描述
						    link: url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
						    imgUrl: 'http://dud2.dataudata.com/static/images/qmdg.jpg', // 分享图标
						    type: '', // 分享类型,music、video或link,不填默认为link
						    dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
						    success: function () { 
						        // 用户确认分享后执行的回调函数
						    },
						    cancel: function () { 
						        // 用户取消分享后执行的回调函数
						    }
						});
					});
					
					wx.error(function(res){
					    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
					});
            	}
        	});
		});
		
	</script>




SignatureController.java源代码:

@Controller
public class SignatureController extends BaseSearchController {
	private Logger log = Logger.getLogger(this.getClass());
	
	/**
	 * 获取微信分享的签名
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/ajax_do_signature")
	public String signature(HttpServletRequest request, HttpServletResponse response) throws Exception {
		JsonDetail json = new JsonDetail();
		try {
			String ticket = (String)CacheUtil.getData(CacheConstants.WEIXIN_SHARE_PARAM, CacheConstants.TICKET);
			if (StringUtils.isBlank(ticket)) {
				ticket = WeiXinShareUtil.getTicket();
				CacheUtil.setData(CacheConstants.WEIXIN_SHARE_PARAM, CacheConstants.TICKET, ticket, 7200);
			}
			
			String timestamp = request.getParameter("timestamp");
			String nonceStr = request.getParameter("nonceStr");
			String url = request.getParameter("url");
			
			StringBuilder signatureParam = new StringBuilder();
			signatureParam.append("jsapi_ticket=");
			signatureParam.append(ticket);
			signatureParam.append("&noncestr=");
			signatureParam.append(nonceStr);
			signatureParam.append("×tamp=");
			signatureParam.append(timestamp);
			signatureParam.append("&url=");
			signatureParam.append(url);
			
			String signature = WeiXinShareUtil.geteSignature(signatureParam.toString());
			System.out.println(signature);
			
			json.setStatus(true);
			json.setItems(signature);
		} catch (Exception e) {
			log.error("获取微信分析签名出错 --> ", e);
			e.printStackTrace();
			json.setStatus(false);
			json.setInfo("数据出错");
		}
		return this.json2Response(json, response);
	}

}




工具类源代码:

WeiXinShareUtil.java:
import flexjson.JSONDeserializer;

public class WeiXinShareUtil {
	private static Logger log = Logger.getLogger(WeiXinShareUtil.class);
	
	/**
	 * 返回access_token
	 * @return
	 * @throws Exception
	 */
	public static String getAccessToken() throws Exception{
		StringBuilder urlStr = new StringBuilder();
		urlStr.append("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=");
		urlStr.append(Config.getString("weixin.appID"));
		urlStr.append("&secret=");
		urlStr.append(Config.getString("weixin.appsecret"));
		
		String tokenJson = HttpURLConnectionUtil.getUrlContent(urlStr.toString());
		log.info("-------getAccessToken return--------\n" + tokenJson);
		AccessToken accessTokenVo = new JSONDeserializer<AccessToken>().deserialize(tokenJson, AccessToken.class);
		return accessTokenVo.getAccess_token();
	}
	
	/**
	 * 返回ticket
	 * @return
	 * @throws Exception
	 */
	public static String getTicket() throws Exception{
		String accessToken = (String)CacheUtil.getData(CacheConstants.WEIXIN_SHARE_PARAM, CacheConstants.ACCESSTOKEN);
		if (StringUtils.isBlank(accessToken)) {
			accessToken = getAccessToken();
			CacheUtil.setData(CacheConstants.WEIXIN_SHARE_PARAM, CacheConstants.ACCESSTOKEN, accessToken, 7200);
		}
		StringBuilder ticketUrl = new StringBuilder();
		ticketUrl.append("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=");
		ticketUrl.append(accessToken);
		ticketUrl.append("&type=jsapi");
		String ticketJson = HttpURLConnectionUtil.getUrlContent(ticketUrl.toString());
		log.info("-------getTicket return--------\n" + ticketJson);
		JsapiTicket ticketVo = new JSONDeserializer<JsapiTicket>().deserialize(ticketJson, JsapiTicket.class);
		return ticketVo.getTicket();
	}
	
	/**
	 * SHA-1算法加密
	 * 
	 * @param text
	 * @return
	 */
	public static String geteSignature(String text) {
		MessageDigest md = null;
		String outStr = null;
		try {
			md = MessageDigest.getInstance("SHA-1");
			byte[] digest = md.digest(text.getBytes());
			outStr = byteToString(digest);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		return outStr;
	}

	/**
	 * 字节数组转字符串
	 * 
	 * @param digest
	 * @return
	 */
	private static String byteToString(byte[] digest) {
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < digest.length; i++) {
			String tempStr = Integer.toHexString(digest[i] & 0xff);
			if (tempStr.length() == 1) {
				buf.append("0").append(tempStr);
			} else {
				buf.append(tempStr);
			}
		}
		return buf.toString().toLowerCase();
	}
}



AccessToken.java:
public class AccessToken {
	
	// 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
	private String access_token;

	// access_token接口调用凭证超时时间,单位(秒)
	private int expires_in;

	public String getAccess_token() {
		return access_token;
	}

	public void setAccess_token(String access_token) {
		this.access_token = access_token;
	}

	public int getExpires_in() {
		return expires_in;
	}

	public void setExpires_in(int expires_in) {
		this.expires_in = expires_in;
	}
	
}



JsapiTicket.java:
public class JsapiTicket {
	
	// 错误code
	private int errcode;
	
	// 错误细心你
	private String errmsg;
	
	// 获取到的凭证
	private String ticket;

	// 接口调用凭证超时时间,单位(秒)
	private int expires_in;

	public int getErrcode() {
		return errcode;
	}

	public void setErrcode(int errcode) {
		this.errcode = errcode;
	}

	public String getErrmsg() {
		return errmsg;
	}

	public void setErrmsg(String errmsg) {
		this.errmsg = errmsg;
	}

	public String getTicket() {
		return ticket;
	}

	public void setTicket(String ticket) {
		this.ticket = ticket;
	}

	public int getExpires_in() {
		return expires_in;
	}

	public void setExpires_in(int expires_in) {
		this.expires_in = expires_in;
	}
}