java版微信分享开发+ssm框架
简介
本人第一次写csdn博客,表示这个编辑器第一次用户体验不是很好啊!不过功能还不错,日常吐槽一下。关于微信分享,微信官方文档给出了详细的开发流程,但是呢还是有许多坑,于是就想记录下来,方便自己回顾,也希望可以给看到的童鞋一些启发。
分享过程步骤简述
1.引入微信官方提供的JSSDK
我们的项目是maven项目,可以直接在pom.xml添加项目依赖。如下
<!--微信SDK-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
2.后台controller层开发
(1) 在前端页面加载的过程中,利用ajax从controller层获得需要向微信接口注入权限验证所需的配置信息。
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.noncestr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名,见附录1
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage']// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
根据配置信息,现在在后台将信息拼接好。
@ResponseBody
@RequestMapping("/coverAjax")
public JSON coverAjax(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
//微信分享开始
String appId = Constants.APP_ID;//取项目中配置的公众号id
String secret = Constants.APP_SECRET;//取项目中配置的公众号密钥
String domainAddr = Constants.DOMAIN_URL;//项目中配置的网站的域名
String strs = request.getParameter("memberId"); //前台传递的参数
String url = request.getParameter("hurs"); //前台传递的参数
Map<String, String> map = new HashMap<String, String>();
map.put("appid", appId);
map.put("secret", secret);
map.put("url", url); //这个地址是传给页面使用
request.setAttribute("shareUrl", url);
session.setAttribute("shareUrl", url);
System.out.println(url);
//开始微信分享链接签名
Map<String, String> params = wxService.weixinjsIntefaceSign(map, session);
request.setAttribute("params", params);
session.setAttribute("params", params);
System.out.println(params);
params.put("shareUrl", url);
return (JSON) JSON.toJSON(params);
}
(2)前端配置好微信的配置信息,同时调用微信分享朋友和朋友圈接口 (担心像我一样刚做项目的小白,我就把前端ajax页面全部提出来放在下面)
$(function(){
var hurs = location.href.split('#')[0];
$.ajax({
type: "POST",
url: "${pageContext.request.contextPath}/WxShare/coverAjax",
data: {
"hurs":hurs
},//传递到后台中的参数
dataType: "json",
cache: false,
success: function (data) {
wxConfig(data);
},
error:function () {
alert("错误")
}
});
});
function wxConfig(data) {
wx.config({
debug: false, // 开启调试模式
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.noncestr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名,见附录1
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage']// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
wx.ready(function () {
wx.onMenuShareAppMessage({
title: '${memberInfo.nickname}',
desc: '${memberInfo.reInfo}',
link: data.shareUrl,
imgUrl: '${memberInfo.headImg}',
success: function () {
//alert("分享朋友成功");
}
});
wx.onMenuShareTimeline({
title: '${memberInfo.nickname}',
link: data.shareUrl,
imgUrl: '${memberInfo.headImg}',
success: function () {
//alert("分享朋友圈成功");
}
});
});
}
注:分享的信息,title 和link 等信息 是在页面的后台包装好放在model里传给前端。
3.微信分享所需的签名算法
public Map<String, String> weixinjsIntefaceSign(Map<String, String> map,HttpSession session){
//查看缓存数据是否存在
Object cacheAccess_token = session.getAttribute("access_token_hl");
Object cacheTicket = session.getAttribute("ticket");
String cacheAccess_token_hl = (String) cacheAccess_token;
String cacheTicket_hl = (String) cacheTicket;
//取出来为空的话则说明cacheAccess_token缓存过期,重新获取
if(null == cacheAccess_token_hl||cacheAccess_token_hl==""){
//获取cacheAccess_token
StringBuffer buffer = new StringBuffer();
buffer.append("https://api.weixin.qq.com/cgi-bin/token?");
buffer.append("grant_type=client_credential");
buffer.append("&appid="+map.get("appid"));
buffer.append("&secret="+map.get("secret"));
System.out.println(buffer);
try {
String resultMsg = WxShareUtil.sendGet(buffer.toString(), "UTF-8");
String jsons = resultMsg.substring(resultMsg.indexOf("{"), resultMsg.lastIndexOf("}") + 1);
String[] result = jsons.split(",");
String[] str1 = result[0].split(":");
String str2 = str1[1].replace("\"","");
cacheAccess_token_hl = str2;
session.setAttribute("access_token_hl",cacheAccess_token_hl);
} catch (IOException e) {
e.printStackTrace();
}
}
//取出来为空的话则说明cacheTicket缓存过期,重新获取
if(null == cacheTicket_hl||cacheTicket_hl==""){
获得jsapi_ticket
StringBuffer buffer = new StringBuffer();
buffer.append("https://api.weixin.qq.com/cgi-bin/ticket/getticket?");
buffer.append("type=jsapi");
buffer.append("&access_token="+session.getAttribute("access_token_hl"));
String ticket = null;
try {
ticket = WxShareUtil.sendGet(buffer.toString(), "UTF-8");
String jsons_t = ticket.substring(ticket.indexOf("{"), ticket.lastIndexOf("}") + 1);
String[] result = jsons_t.split(",");
String[] str1 = result[2].split(":");
String str2 = str1[1].replace("\"","");
cacheTicket_hl = str2;
session.setAttribute("ticket",cacheTicket_hl);
System.out.println("重新获取cacheTicket");
System.out.println(ticket);
} catch (IOException e) {
e.printStackTrace();
}
}
//生成签名
SortedMap<Object,Object> params = new TreeMap<Object,Object>();
params.put("timestamp", Long.toString(new Date().getTime()/1000));
params.put("noncestr", WXPayUtil.generateNonceStr());
params.put("jsapi_ticket",cacheTicket_hl);
params.put("url",map.get("url"));//url地址
StringBuffer sb = new StringBuffer();
Set es = params.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
sb.append(k + "=" + v + "&");
}
String signStr = sb.toString().substring(0, sb.toString().length()-1);
String sign = WxShareUtil.getSha1Sign(signStr);//签名
Map<String, String> result = new HashMap<String,String>();
result.put("timestamp",(String)params.get("timestamp"));
result.put("noncestr", (String)params.get("noncestr"));
result.put("signature", sign);
result.put("appId",map.get("appid"));
session.setMaxInactiveInterval(7200);
return result;
}
4.开发所需的工具类和遇到的坑
(1)常量类 Constants 就不展示出来了。分享的工具类代码如下: WxShareUtil
public class WxShareUtil {
public static String sendGet(String url,String charset) throws IOException {
//新建客户端
HttpClient httpclient = new HttpClient();
GetMethod getMethod = new GetMethod(url);
httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, charset);
httpclient.executeMethod(getMethod);
String responseMsg = getMethod.getResponseBodyAsString();
return responseMsg;
}
public static String getSha1Sign(String decript) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
try {
digest.update(decript.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
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 "";
}
}
(2)开发微信分享遇到的坑
第一,微信分享,你需要将域名添加到微信公众平台上
第二,你要将服务器的ip添加在微信公众平台的ip白名单里。
第三,分享页面的url,最好是动态获取当前页面的url,在传给后台,但是传的时候要做处理,使用 location.href.split(’#’)[0];去除多次分享后面的参数。
第四,在测试分享功能时,可以开启调试功能,然后在前端确保所需的配置参数都有。
第五,一定要将分享签名的token 和ticket 放在缓存里,微信是设置2个小时失效,所以 你需要设置两小时后 缓存清理,重新向微信申请获得access_token,注意,这个token和授权登录的token不一样。
最后:签名错误经常会碰到,耐心检查 一定会成功的。
5.写给大家和自己
感谢曾经写过微信分享的各位大佬,本人就是一个java后台开发菜鸟,基本都是面向百度编程,感谢他们的分享,让我顺利完成微信分享功能,如果代码中有一些很冗余甚至很智障的命名,请多担待认可,然后,如果有不是很懂的,也可以发邮件给我,我们可以talk一哈,以后,我还会继续写微信授权登录的java版功能开发和微信支付开发等等 ,希望自己能够逐渐成长为我很羡慕的大佬,加油!!!
最后,附上我的邮箱 3231394682@qq.com