最近做了微信分享转发的需求, 说起来也是头疼, 平常都是刷推特微博的, 还特意为了做这个需求下了个微信.
1. 注册一个测试公众号 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
接口配置和js安全域名填自己线上测试环境地址
Token随便填
2. github上面搜个demo项目 https://github.com/binarywang/weixin-java-mp-demo-springboot
稍微看看, 东西还挺多的, 也懒得看了, 拿来主义!
3. 项目的配置文件有了模板, 抄过来
4. 公众号管理里面接口配置就用Controller里面的地址(抄过来是/wx/portal/{appid}, 嫌路径不好记就改成自己的)
5. wx.config需要后端生成签名, 继续抄(我抄到了,你们抄我的吧)
@GetMapping("/wechatParam")
public ResponseModel getWXConfigSignature(String url) {
WxMpProperties.MpConfig config = wxMpProperties.getConfigs().get(0);
long timeStampSec = System.currentTimeMillis() / 1000;
String timestamp = String.format("%010d", timeStampSec);
String nonceStr = Fun.randString(8);
String[] urls = url.split("#");
String newUrl = urls[0];
logger.info("随机串:"+nonceStr+", 获取签名URL: " + newUrl);
JSONObject respJson = new JSONObject();
String wxJsapiTicket = getWXJsapiTicket(config.getAppId(),config.getSecret());
String[] signArr = new String[]{"url=" + newUrl, "jsapi_ticket=" + wxJsapiTicket, "noncestr=" + nonceStr, "timestamp=" + timestamp};
Arrays.sort(signArr);
String signStr = String.join("&",signArr);
String resSign = DigestUtils.sha1Hex(signStr);
logger.info("返回的签名:" + resSign);
respJson.put("appId", config.getAppId());
respJson.put("timestamp", timestamp);
respJson.put("nonceStr", nonceStr);
respJson.put("signature", resSign);
respJson.put("url", url);
logger.info(respJson.toJSONString());
return ResponseModel.newSuccess(respJson);
}
private String getWXJsapiTicket(String appid,String secret) {
ValueOperations valueOperations = redisTemplate.opsForValue();
String ticket = (String) valueOperations.get(appid);
if (Strings.isBlank(ticket)) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + getWXaccessToken(appid,secret) + "&type=jsapi";
String resp = restTemplate.getForObject(url, String.class);
JSONObject resJson = JSONObject.parseObject(resp);
logger.info("获取到ticket:" + resJson.getString("ticket"));
valueOperations.set(appid, resJson.getString("ticket"), 2, TimeUnit.HOURS);
return resJson.getString("ticket");
}
return ticket;
}
private String getWXaccessToken(String appid,String secret) {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret;
String resp = restTemplate.getForObject(url, String.class);
JSONObject resJson = JSONObject.parseObject(resp);
logger.info("获取到access_token:" + resJson.getString("access_token"));
return resJson.getString("access_token");
}
逻辑咱不关心,就是一个wechatParam接口(wxMpProperties是Autowired拿到的)
6. 前端找后端拿签名, 监听分享事件, 自己测试的js代码:
<h1 id="msg"></h1>
<script>
$(function(){
var url = location.href.split('#').toString();//url不能写死
$.ajax({
type : "get",
url : "/wx/{公众号的appid}/wechatParam",
dataType : "json",
async : false,
data:{url:url},
success : function(data) {
wx.config({
debug: true,生产环境需要关闭debug模式
appId: data.data.appId,//appId通过微信服务号后台查看
timestamp: data.data.timestamp,//生成签名的时间戳
nonceStr: data.data.nonceStr,//生成签名的随机字符串
signature: data.data.signature,//签名
jsApiList: [//需要调用的JS接口列表
'checkJsApi',//判断当前客户端版本是否支持指定JS接口
'onMenuShareTimeline',//分享给好友
'onMenuShareAppMessage'//分享到朋友圈
]
});
alertx('config is over:'+JSON.stringify(data.data));
},
error: function(xhr, status, error) {
alertx(JSON.stringify(status));
alertx(JSON.stringify(xhr));
alertx(JSON.stringify(error));
}
});
});
wx.ready(function () {
var link = window.location.href;
var protocol = window.location.protocol;
var host = window.location.host;
alertx('wx is ready');
//分享朋友圈
wx.onMenuShareTimeline({
title: '分享朋友圈!',
link: link,
imgUrl: protocol+'//'+host+'/resources/images/icon.jpg',// 自定义图标
trigger: function (res) {
// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回.
alertx('click shared');
},
success: function (res) {
alertx('shared success');
//some thing you should do
},
cancel: function (res) {
alertx('shared cancle');
},
fail: function (res) {
alertx(JSON.stringify(res));
}
});
//分享给好友
wx.onMenuShareAppMessage({
title: '分享给好友!', // 分享标题
desc: '分享给好友123!', // 分享描述
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: protocol+'//'+host+'/resources/images/icon.jpg', // 自定义图标
type: 'link', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户确认分享后执行的回调函数
alertx('shared success!');
},
cancel: function () {
// 用户取消分享后执行的回调函数
alertx('shared cancle!');
}
});
wx.error(function (res) {
alertx(JSON.stringify(res));
});
});
function alertx(msg) {
alert(msg);
console.log(msg);
$('#msg').append(msg+'<br/>');
}
</script>