示例网页
二帅
init share
wechat_common.share.js
var init_share_url = "http://[host]/wechat/initWechatConfig.xhtml";
/**
* 初始化分享
* @param initUrl 当前初始化网页地址
* @param lineLink 点击后跳转地址
* @param shareTitle 分享标题
* @param shareContent 分享内容
* @param shareLogo 分享logo
*/
function initShare(initUrl, lineLink, shareTitle, shareContent, shareLogo) {
$.ajax({
type : "post",
url : init_share_url,
data : {
"initUrl" : initUrl,
"initType" : "jsapi"
},
dataType : "json",
error : function(request) {
alert('初始化分享失败,请稍后重试');
},
success : function(ajaxRes) {
var state = ajaxRes.state;
if (state == 1) {
var data = ajaxRes.data;
//初始化微信配置
wxShareConfig(data.appId, data.timestamp, data.nonceStr, data.signature);
//分享准备
wxShareReady(lineLink, shareTitle, shareContent, shareLogo);
} else {
alert(ajaxRes.msg);
}
}
});
};
/**
* 初始化微信分享配置
* @param appId
* @param timestamp
* @param nonceStr
* @param signature
*/
function wxShareConfig(appId, timestamp, nonceStr, signature) {
wx.config({
debug: false,
appId: appId,
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
jsApiList: [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareQZone'
]
});
wx.error(function (res) {
alert(res.errMsg);
});
}
/**
* 分享准备
* @param lineLink
* @param shareTitle
* @param shareContent
* @param shareLogo
*/
function wxShareReady(lineLink, shareTitle, shareContent, shareLogo) {
wx.ready(function () {
//获取“分享到朋友圈”
wx.onMenuShareTimeline({
title: shareTitle, // 分享标题
link: lineLink, // 分享链接
imgUrl: shareLogo, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//获取“分享给朋友”
wx.onMenuShareAppMessage({
title: shareTitle, // 分享标题
desc: shareContent, // 分享描述
link: lineLink, // 分享链接
imgUrl: shareLogo, // 分享图标
type: 'link', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户确认分享后执行的回调函数
//alert('已分享');
//window.location.href = "https://www.baidu.com";
},
cancel: function () {
// 用户取消分享后执行的回调函数
//alert('已取消');
}
});
//获取“分享到QQ”
wx.onMenuShareQQ({
title: shareTitle, // 分享标题
desc: shareContent, // 分享描述
link: lineLink, // 分享链接
imgUrl: shareLogo, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//获取“分享到QQ空间”
wx.onMenuShareQZone({
title: shareTitle, // 分享标题
desc: shareContent, // 分享描述
link: lineLink, // 分享链接
imgUrl: shareLogo, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//获取“分享到腾讯微博”
wx.onMenuShareWeibo({
title: shareTitle, // 分享标题
desc: shareContent, // 分享描述
link: lineLink, // 分享链接
imgUrl: shareLogo, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
}
到这里,前端就完事了
现在实现,init_share_url方法
var init_share_url = "http://[host]/wechat/initWechatConfig.xhtml";
initWechatConfig方法内容:
(因为我这个有多个服务号要维护,是根据rawId来判断的;一般情况是不用rawId参数的)
@RequestMapping("/initWechatConfig.xhtml")
public void initWechatConfig(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
String initUrl = getParams("initUrl");//当前网页地址
String initType = getParams("initType");
if (CommonUtil.isNull(initUrl) || CommonUtil.isNull(initType)) {//判断null
throw new BizException(ErrorMsg.PARAMS_NULL);
}
String rawId = getParams("rawId");
if (CommonUtil.isNull(rawId)) {
rawId = Constants.RawId_broker;
}
HashMap respMap = new HashMap();
if ("jsapi".equals(initType)) {//初始化分享
String noncestr = RandomUtil.nextInt(initType.toUpperCase(), 100, 999);//随机数,用uuid什么的也可以
String timestamp = DateUtil.getTimestampWx();//时间戳 Long.toString(System.currentTimeMillis() / 1000)
String signature = null;
//获取
Ticket ticket = this.wechatService.getJsapiTicket(rawId);
signature = SHA1Util.signForJsapiTicket(ticket.getTicket(), noncestr, timestamp, initUrl);
respMap.put("appId", Constants.getAppId(rawId));
respMap.put("timestamp", timestamp);
respMap.put("nonceStr", noncestr);
respMap.put("signature", signature);
} else if ("pay".equals(initType)) {//初始化支付
}
writeSuccMsg(response, respMap);
} catch (Exception e) {
log.error("初始化微信配置 异常:", e);
writeErrorMsg(response, e.getMessage());
}
}
RequestAddr的参数配置
// 获取access_token的接口地址(GET) API要求每天限制2000 - 全局access_token
public static final String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
// 获取ticket_url的接口地址(GET) API
public static final String ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
// 获取ticket_url的参数
public static final String ticket_url_params = "jsapi_ticket=JSAPI_TICKET&noncestr=NONCESTR×tamp=TIMESTAMP&url=INIT_URL";
getJsapiTicket方法
public Ticket getJsapiTicket(String rawId) throws Exception {
//请求全局access_token
AccessToken accessToken = getAccessToken(rawId);
//获取jsapi_ticket
Ticket ticket = WeChatUtils.getJsapiTicket(accessToken.getAccess_token());
return ticket;
}
/**
* 获取全局access_token 公共方法
* @author ershuai
* @version V1.0
* @param rawId
* @return
* @throws Exception
*/
public AccessToken getAccessToken(String rawId) throws Exception {
//请求全局access_token
AccessToken accessToken = WeChatUtils.getAccessToken(rawId);
return accessToken;
}
WeChatUtils类
/**
* 凭证access_token的获取方法 - 全局access_token
* @author ershuai
* @version V1.0
* @return
* @throws Exception
*/
public static AccessToken getAccessToken(String rawId) throws Exception {
String appId = Constants.getAppId(rawId);
String appSecret = Constants.getAppSecret(rawId);
//url
String access_token_url = RequestAddr.access_token_url;
//匹配参数
access_token_url = access_token_url.replace("APPID", appId);
access_token_url = access_token_url.replace("SECRET", appSecret);
//匹配参数
//请求
String respStr = WebUtils.doGet(access_token_url, null);
AccessToken accessToken = null;
if (null != respStr) {
accessToken = JSON.parseObject(respStr, AccessToken.class);
}
return accessToken;
}
/**
* 凭证JsapiTicket的获取方法
* @author ershuai
* @version V1.0
* @param accessToken
* @return
* @throws Exception
*/
public static Ticket getJsapiTicket(String accessToken) throws Exception {
//url
String jsapi_ticket_url = RequestAddr.ticket_url.replace("ACCESS_TOKEN", accessToken);
//匹配参数
jsapi_ticket_url = jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
//请求
String respStr = WebUtils.doGet(jsapi_ticket_url, null);
Ticket ticket = null;
if (null != respStr) {
ticket = JSON.parseObject(respStr, Ticket.class);
}
return ticket;
}
SHA1Util类
/**
* sign签名,对于 jsapi_ticket
* @author ershuai
* @version V1.0
* @param jsapiTicket
* @param noncestr
* @param timestamp
* @param initUrl
* @return
*/
public static String signForJsapiTicket(String jsapiTicket, String noncestr, String timestamp, String initUrl) {
String signature = null;
// 注意这里参数名必须全部小写,且必须有序
String signatureStr = RequestAddr.ticket_url_params;
signatureStr = signatureStr.replace("JSAPI_TICKET", jsapiTicket);
signatureStr = signatureStr.replace("NONCESTR", noncestr);
signatureStr = signatureStr.replace("TIMESTAMP", timestamp);
signatureStr = signatureStr.replace("INIT_URL", initUrl);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(signatureStr.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return signature;
}
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;
}
PS:做完以上流程,应该就可以完成分享功能了;出现最多的错误应该就是签名不正确,这个问题检查几个微信参数就好了;
config:invalid url domain 错误是需要去 公众号设置 - 功能设置 - JS接口安全域名;配置域名