版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QWERTY1994/article/details/88872022
需要分页的网页引入下面jsp
weixin.jsp
<%--
Created by IntelliJ IDEA.
User:
Date: 2019/2/20
Time: 15:12
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--<%@ include file="/WEB-INF/views/modules/cms/front/include/taglib.jsp"%>--%>
<!-- 必须引入的文件-->
<script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<!-- 组装微信配置信息js文件-->
<%--<script src="${ctxStatic}/weixin/wxShare_data.js"></script>--%>
<!-- 微信分享时调用对应的接口js文件-->
<%--<script src="${ctxStatic}/weixin/wxShare.js"></script>--%>
<script>
//后台获取授权等信息的接口
var url = "http://" + window.location.host + "/f/weixinShare/getWxShareData";
// 分享网页图片地址
var shareImageUrl="http://xxxx/xxxx.jpg";
//分享网页后显示的标题
var title="xxxxx";
//分享网页的简介
var desc= "xxxxx";
//点击分享后页面跳转的页面
var link="http://xxxxx/f/xxxxx";
//上面这些数据也可以在后台动态生成
$.ajax({
url: url,//后台给你提供的接口
type: "Post",
// data: "{ 'url': '"+link+"' }",
async: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareWeibo','onMenuShareAppMessage','onMenuShareTimeline','onMenuShareQQ','onMenuShareQZone'] // 必填,需要使用的JS接口列表
});
wx.ready(function () {
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,
// 则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
//需在用户可能点击分享按钮前就先调用
// 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
wx.updateAppMessageShareData({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImageUrl, // 分享图标
success: function () {
// 设置成功
}
});
//自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
wx.updateTimelineShareData({
title: title, // 分享标题
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImageUrl, // 分享图标
success: function () {
// 设置成功
}
});
//获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口
wx.onMenuShareWeibo({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: shareImageUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
// 获取“分享给朋友”按钮点击状态及自定义分享内容接口(即将废弃)
wx.onMenuShareAppMessage({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImageUrl, // 分享图标
type: 'link', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户点击了分享后执行的回调函数
}
});
//获取“分享到朋友圈”按钮点击状态及自定义分享内容接口(即将废弃)
wx.onMenuShareTimeline({
title: title, // 分享标题
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImageUrl, // 分享图标
success: function () {
// 用户点击了分享后执行的回调函数
}
});
//获取“分享到QQ”按钮点击状态及自定义分享内容接口(即将废弃)
wx.onMenuShareQQ({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: shareImageUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//获取“分享到QQ空间”按钮点击状态及自定义分享内容接口(即将废弃)
wx.onMenuShareQZone({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: shareImageUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
wx.error(function (res) {
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
//alert(res);
});
},
error: function (error) {
layer.msg(error)
}
});
</script>
后台获取签名授权等信息的方法
下面的签名每天获取有次数限制,微信的签名2个小时内有效, 此处我用的是Memcached缓存起来,各位可以自行实现
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.memcached.MemcachedUtil;
import com.thinkgem.jeesite.common.utils.CacheUtils;
import com.thinkgem.jeesite.common.web.BaseController;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
/**
* 微信分享
*/
@Controller
@RequestMapping(value = "/f/weixinShare")
public class CourseWeixinShare extends BaseController {
// 微信分享入口
@RequestMapping(value = "getWxShareData")
@ResponseBody
public Map getWxShareData(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String,Object> returnMap = new HashMap<>();
String ticket = "";
String[] wxInfo = new String[]{Global.getConfig("appId"),Global.getConfig("appsecret")};//设置appid 和 appsecret
String ticketResString = this.getShareJsapiTicket(wxInfo);
if (StringUtils.isNotEmpty(ticketResString)) {
// JSONObject ticketJSONObject = JSONObject.fromObject(ticketResString);
Gson gson =new Gson();
Map<String,Object> ticketJSONObject = gson.fromJson(ticketResString,Map.class);
if ((Double)ticketJSONObject.get("errcode") == 0) {
// ticket = JSONObject.fromObject(ticketResString).optString("ticket", "");
if(ticketJSONObject.get("ticket")!=null){
ticket = (String) ticketJSONObject.get("ticket");
}
}
}
if (StringUtils.isEmpty(ticket)) {
returnMap.put("errcode", "10002");
returnMap.put("errmsg", "ticket_error");
// this.responseWrite(jsonObject.toString());
return returnMap;
}
String noncestr = this.createNonceStr();
int timestamp = this.createTimestamp();
String requestRefererURL = request.getHeader("referer");
logger.warn("requestRefererURL: " + requestRefererURL);
String signature = this.createSignature(noncestr, ticket, timestamp, requestRefererURL);
returnMap.put("errcode", 0);
returnMap.put("errmsg", "");
returnMap.put("appId", wxInfo[0]); // appId
returnMap.put("timestamp", timestamp);
returnMap.put("nonceStr", noncestr);
returnMap.put("signature", signature);
return returnMap;
}
/**
* 微信分享,获取Js api Ticket
* @param wxInfo
* @return
* @throws Exception
*/
private String getShareJsapiTicket(String[] wxInfo) throws Exception {
String jsapiTicket = null;
if(CacheUtils.get("jsapiTicket_addTime") !=null &&( System.currentTimeMillis() - (Long) CacheUtils.get("jsapiTicket_addTime"))<7080*1000){//不超过2个小时的缓存有效
jsapiTicket = (String) CacheUtils.get("jsapiTicket");
this.logger.warn(" from memcached jsapiTicket: " + jsapiTicket);
return jsapiTicket;
}else{
String accessToken = this.getWeiXinAccessToken(wxInfo);
if (StringUtils.isEmpty(accessToken)) { // 获取 accessToken 失败
this.logger.warn(" accessToken is empty.");
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("errcode", "10000");
jsonObject.addProperty("errmsg", "access_error");
return jsonObject.toString();
}
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ accessToken + "&type=jsapi";
jsapiTicket = this.httpReqExecute(url);
this.logger.warn(" from weixin api jsapiTicket is: " + jsapiTicket);
if(StringUtils.isNotEmpty(jsapiTicket)) {
// 向memcached里写内容,第二个参数为过期时间,单位为:秒 两个小时失效
// remoteMemcachedClient.set(siteId + "_jsapiTicket", 7200, jsapiTicket);
CacheUtils.put("jsapiTicket",jsapiTicket);
CacheUtils.put("jsapiTicket_addTime",System.currentTimeMillis());//设置 缓存的时间
return jsapiTicket;
}
return null;
}
}
/**
* 微信分享,获取access_token
* 先从memcached获取
* @param wxInfo 0:appId 1:secret
* @return
* @throws Exception
*/
private String getWeiXinAccessToken(String[] wxInfo) throws Exception {
String access_token = MemcachedUtil.get("ParentsSpace_access_token");
if(StringUtils.isNotBlank(access_token)){
return access_token;
}
/* if( CacheUtils.get("access_token_addTime")!=null && (System.currentTimeMillis() - (Long)CacheUtils.get("access_token_addTime")) <7080*1000 ){//不超过2个小时的缓存有效
return (String) CacheUtils.get("access_token");
}*/else{//失效了 就重新请求
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wxInfo[0] + "&secret=" + wxInfo[1];
String result = this.httpReqExecute(url);
this.logger.warn("from weixin api accessToken: " + result);
try {
if(StringUtils.isNotEmpty(result)) {
// 解析respContent,并获取其中的更新的key,
Gson gson =new Gson();
Map<String,String> resultMap = gson.fromJson(result,Map.class);
// String accessToken = JSONObject.fromObject(result).optString("access_token", "");
String accessToken = "";
if(resultMap.get("access_token")!=null){
accessToken = resultMap.get("access_token");
//缓存起来
/* CacheUtils.put("access_token_addTime",System.currentTimeMillis());
CacheUtils.put("access_token",accessToken);*/
//缓存118分钟
MemcachedUtil.set("ParentsSpace_access_token",accessToken,118*60);
}
return accessToken;
}
} catch (Exception e) {
logger.error("getAccessToken error in WeiXinShareAction", e);
}
return null;
}
}
/**
* 数据签名
* @param nocestr
* @param ticket
* @param timestamp
* @param url
* @return
*/
private String createSignature(String nocestr, String ticket, int timestamp, String url) {
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
String s = "jsapi_ticket=" + ticket + "&noncestr=" + nocestr + "×tamp=" + timestamp + "&url=" + url;
return DigestUtils.sha1Hex(s);
}
/**
* 创建随机串 自定义个数0 < ? < 32
* @return
*/
private String createNonceStr() {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String nonceStr = "";
for (int i = 0; i < 16; i++) {
int beginIndex = (int) Math.round(Math.random() * 10);
nonceStr += str.substring(beginIndex, beginIndex + 1);
}
return nonceStr;
}
/**
* 创建时间戳
* @return
*/
private int createTimestamp() {
return Calendar.getInstance().get(Calendar.SECOND);
}
// 输出信息
/*private void responseWrite(String content) {
try {
getResponse().setCharacterEncoding("utf-8");
getResponse().getWriter().write(content);
} catch (Exception e) {
logger.error("responseWrite error in WeiXinShareAction", e);
}
}*/
// HTTP远程调用
private String httpReqExecute(String url) {
String result = "";
// DefaultHttpClient httpclient = null ;
HttpClient httpclient = null ;
try {
httpclient = HttpClientBuilder.create().build();//获取DefaultHttpClient请求
HttpPost httppost = new HttpPost(url);
// 执行
org.apache.http.HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if(entity != null && response.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(entity, "UTF-8");
}
} catch (Exception e) {
logger.error(" WeiXinShareAction 调用微信 API 失败!", e);
} finally { // 关闭连接,释放资源
httpclient.getConnectionManager().shutdown();
}
return result;
}
}