本文主要介绍了SpringBoot 基于JS-SDK实现自定义微信分享,并通过本地测试的方式进行调试,文中通过微信实现分享流程及示例代码进行非常详细的介绍,希望本文对开发爱好者学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧!

一 准备工作

1.微信公众平台appID和appsecret

2.微信开发文档(相当烂,但一定要看)

3.微信web开发者工具

二 开发步骤

1.申请接口测试号并进行JS接口安全域名设置

接口测试号申请。点击访问,选择接口测试号申请,如下图所示:

或者直接访问 :申请测试账号页面 如下图所示:

点击登录进行扫码登录,如下图所示:

登录后如下图所示:

配置JS接口安全域名

2.windows下配置本地回环地址

找到windows统中 hosts 文件,配置回环地址的域名,C:\Windows\System32\drivers\etc

配置回环地址

3. 下载微信web开发者工具,可以在PC 进行测试

下载微信web开发者工具,点击访问下载页面如下图所示:

下载完成之后,安装微信web开发者工具,一步一步傻瓜式安装。

4.参照微信开发文档实现

点击访问微信JS-SDK说明文档 如下图所示:

JSSDK使用步骤

步骤一:绑定域名(上面已经操作了)

步骤二:引入JS文件(下面实战代码中会介绍到如何使用)

步骤三:通过config接口注入权限验证配置(下面实战代码中会介绍到如何使用)

步骤四:通过ready接口处理成功验证

步骤五:通过error接口处理失败验证

接口调用说明

5.代码实现

上面步骤步骤三中的 signature是一个重要的参数,生成它需要获取 jsapi_ticket,而生成 jsapi_ticket 需要通过 access_token。

获取signature流程如下:

  • 获取 access_token 然后根据 access_token 获取 jsapi_ticket 。
  • 排序 noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳),url(当前网页的URL,不包含#及其后面部分)4个参数拼接例如:noncestr=XX&jsapi_ticket=XX&jtimestamp=XX&jurl=XX
  • 然后通过sha1加密拼接的4个参数获取到signature

初始化微信JSSDK配置信息

 @Controller
@RequestMapping("/weixin")
public class WeiXinDemoController { @Autowired
private WeiXinService weiXinService;
@Autowired
private WXConfig weiXinConfig; /**
* 初始化微信JSSDK配置信息
* @param request
* @param response
* @param shareUrl 分享地址
* @return
* @throws Exception
*/
@RequestMapping("/initWXJSSDKConfigInfo")
@ResponseBody
public String initWXJSConfig (HttpServletRequest request, HttpServletResponse response, String shareUrl) throws Exception{
Map map = weiXinService.initJSSDKConfigInfo(shareUrl);
String json = weiXinService.mapToJson(map);
return json;
}
}

初始化JSSDK配置信息,配置信息有:noncestr(随机字符串)、有效的jsapi_tickettimestamp(时间戳)、shareUrl(当前网页的URL,不包含#及其后面部分)appid(公众号 appid

 /**
* @description 初始化JSSDK配置信息
* @param shareUrl 分享的url地址
* @return
* @throws Exception
*/
public Map initJSSDKConfigInfo(String shareUrl) throws Exception {
String accessToken = this.getJSSDKAccessToken();
String jsapiTicket = this.getJSSDKJsapiTicket(accessToken);
String timestamp = Long.toString(System.currentTimeMillis() / );
String nonceStr = UUID.randomUUID().toString();
String signature = this.buildJSSDKSignature(jsapiTicket,timestamp,nonceStr,shareUrl);
Map<String,String> map = new HashMap<String,String>();
map.put("shareUrl", shareUrl);
map.put("jsapi_ticket", jsapiTicket);
map.put("nonceStr", nonceStr);
map.put("timestamp", timestamp);
map.put("signature", signature);
map.put("appid", weiXinConfig.getAppID());
return map;
}

 

获取 JSSDK
access_token 

   /**
* @description 获取JSSDK的认证token
* @return 返回JSSDK的认证token
*/
public String getJSSDKAccessToken() {
String token = null;
String url = WXContants.JSSDK_ACCESSTOKEN.replaceAll(WXContants.REPLACE_FEILD_APPID,
weiXinConfig.getAppID()).replaceAll(WXContants.REPLACE_FEILD_APPSECRET,
weiXinConfig.getAppsecret());
String json = postRequestForWeiXinService(url);
Map map = jsonToMap(json);
if (map != null) {
token = (String) map.get("access_token");
}
return token;
}

获取 JSSDK jsapi_ticket

     /**
* @description 获取JSSDK的ticket
* @param token JSSDK的认证token
* @return 返回JSSDK的ticket
*/
public String getJSSDKJsapiTicket(String token) {
String url = WXContants.JSSDK_TICKET.replaceAll(WXContants.REPLACE_FEILD_ACCESS_TOKEN, token);
String json = postRequestForWeiXinService(url);
Map map = jsonToMap(json);
String ticket = null;
if (map != null) {
ticket = (String) map.get("ticket");
}
return ticket;
}
 

拼接 noncestr(随机字符串), 有效的jsapi_ticket timestamp(时间戳)、url(当前网页的URL,不包含#及其后面部分)并通过sha1进行加密

      /**
* @description 构建分享链接的签名
* @param ticket
* @param nonceStr
* @param timestamp
* @param url
* @return
* @throws Exception
*/
public static String buildJSSDKSignature(String ticket,String timestamp,String nonceStr ,String url) throws Exception {
StringBuffer signaStr = new StringBuffer();
signaStr.append("jsapi_ticket=").append(ticket);
signaStr.append("&noncestr=").append(nonceStr);
signaStr.append("&timestamp=").append(timestamp);
signaStr.append("&url=").append(url);
return sha1(signaStr.toString());
} /**
* @description sha1 加密JSSDK微信配置参数获取签名
* @param signaStr 构建分享链接的签名
* @return 返回加密签名
*/
public static String sha1(String signaStr) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(signaStr.getBytes());
return byteToStr(digest).toLowerCase();
}
/**
* @description 将字节数组转换为十六进制字符串
* @param byteArray 待转换的字节数组
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = ; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
} /**
* @description 将字节转换为十六进制字符串
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '', '', '', '', '', '', '', '', '', '', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[];
tempArr[] = Digit[(mByte >>> ) & 0X0F];
tempArr[] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}

基础工具方法

 /**
* @description 将map转换成json字符串
* @param map map对象
* @return json字符串
*/
public String mapToJson(Map map){
Gson gson = new Gson();
String json = gson.toJson(map);
return json;
} /**
* @description 将json字符串转换成map字符串
* @param json json字符串
* @return map对象
*/
private Map jsonToMap(String json) {
Gson gons = new Gson();
Map map = gons.fromJson(json, new TypeToken<Map>(){}.getType());
return map;
} private String postRequestForWeiXinService(String accessTokenUrl) {
ResponseEntity<String> postForEntity = restTemplate.postForEntity(accessTokenUrl, null, String.class);
String json = postForEntity.getBody();
return json;
} private String getRequestForWeiXinService(String getUserInfoUrl) {
ResponseEntity<String> postForEntity = restTemplate.getForEntity(getUserInfoUrl.toString(), String.class);
String json = postForEntity.getBody();
return json;
}
 

wxShare.js 主要是获取JSSDK配置信息并定义分享功能处理。具体代码如下:

 /***用户点击分享到微信圈后加载接口接口*******/
$.post("/weixin/initWXJSSDKConfigInfo",{"shareUrl":window.location.href.split('#')[]},function(data,status){
data=eval("("+data+")");
wx.config({
debug: false,
appId: data.appid,
timestamp:data.timestamp,
nonceStr:data.nonceStr,
signature:data.signature,
jsApiList: [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone',
//'updateAppMessageShareData',
//'updateTimelineShareData',
//'hideOptionMenu',
]
});
var shareTitle = $("#wx_share_span").data("shareTitle");
if(!shareTitle){
shareTitle = $("title").html();
}
var shareImg = $("#wx_share_span").data("shareImg");
if(!shareImg){
//shareImg = common.bp()+'/m_images/shareImg.jpg';
}
var shareLink = $("#wx_share_span").data("shareLink");
if(!shareLink){
shareLink = window.location.href.split('#')[];
}
var shareDesc = $("#wx_share_span").data("shareDesc");
if(!shareDesc){
shareDesc = $("meta[name=description]").attr("content");
}
wx.ready(function(){
// alert("准备分享");
wx.onMenuShareTimeline({
title : shareTitle, // 分享标题
link : shareLink, // 分享链接
imgUrl : shareImg, // 分享图标
success : function() {
// 用户确认分享后执行的回调函数
//alert("分享成功");
},
cancel : function() {
// 用户取消分享后执行的回调函数
//alert("分享取消");
}
});
//wx.hideOptionMenu();/!***隐藏分享菜单****!/
wx.onMenuShareAppMessage({
title: shareTitle, // 分享标题
desc: shareDesc, // 分享描述
link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImg, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
wx.onMenuShareQQ({
title: shareTitle, // 分享标题
desc: shareDesc, // 分享描述
link: shareLink, // 分享链接
imgUrl: shareImg, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
wx.onMenuShareQZone({
title: shareTitle, // 分享标题
desc: shareDesc, // 分享描述
link: shareLink, // 分享链接
imgUrl: shareImg, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
Wx.checkJsApi({
jsApiList: ['updateAppMessageShareData','updateTimelineShareData','onMenuShareWeibo'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: function(res) {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
}
});
//wx.hideOptionMenu();/!***隐藏分享菜单****!/
wx.updateAppMessageShareData({
title: shareTitle, // 分享标题
desc: shareDesc, // 分享描述
link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImg, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
wx.updateTimelineShareData({
title: shareTitle, // 分享标题
link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareImg, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
wx.onMenuShareWeibo({
title: shareTitle, // 分享标题
desc: shareDesc, // 分享描述
link: shareLink, // 分享链接
imgUrl: shareImg, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
});

分享页面该页面需要引入wxShare.jsjweixin-1.6.0.js,并且通过在隐藏的span标签上定义自定义分享的内容,具体代码如下:

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>微信JS-SDK分享</title>
<script type="text/javascript" th:src="@{/js/jquery-1.8.3.min.js}" ></script>
<script type="text/javascript" th:src="@{/js/wxShare.js}"></script>
<script type="text/javascript" src="http://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
<span id="wx_share_span" style="display: none"></span>
<h1>SpringMVC + Thymeleaf Hello World example</h1>
<p th:text="${content}"></p> <!-- ${...}变量表达式 -->
<script type="text/javascript">
$(document).ready(function(){
$("#wx_share_span").data("shareTitle", "微信JS-SDK分享");
$("#wx_share_span").data("shareDesc", "一个简单的基于微信JS-SDK分享的demo");
//$("#wx_share_span").data("shareLink", "/wxShare");
$("#wx_share_span").data("shareImg", "http://www.zcg.com:8090/img/img.png");
});
</script>
</body>
</html>

6.测试

打开微信开发者工具,在地址栏输入http://www.zcg.com:8090/weixin/wxShare,点击分享,能够出现以下界面,说明已经可以实现分享了!

gitee源码地址:https://gitee.com/zcgxj/zxj-boot-wx-share.git

springboot 基于JS-SDK实现微信分享(一)的更多相关文章

  1. weixinShare.js / 极简微信分享插件

    weixinShare.js / 极简微信分享插件 / 版本:0.1 这是一个很简单.很实用的微信分享插件,无需jQuery,只需要在网页里加入一行JS代码,即可自动识别微信浏览器并启动微信分享的提示 ...

  2. php框架tp3.2.3和js写的微信分享功能心得,分享的标题内容图片自定义

    https://blog.csdn.net/weixin_42231483/article/details/81585322 最近用PHP的tp3.2.3框架和js写的微信分享功能心得,分享的标题内容 ...

  3. 不接入微信sdk,在APP中实现微信分享,支付

    前段时间在很多地方接入了微信的sdk,发现过程比较繁琐,此外因为导入的sdk比较大会影响最终APP打包的体积,所以就有了不接入sdk也实现相同的功能的想法. 要实现这个目标我个人认为最困难的地方是不知 ...

  4. 在vue中使用weixin-js-sdk自定义微信分享效果

    在做微信分享的时候,产品要求分享效果要有文字和图片,使用weixin-js-sdk解决了, 原始的分享效果: 使用微信JS-SDK的分享效果: 首先需要引入weixin-js-sdk npm inst ...

  5. 微信JS SDK配置授权,实现分享接口

    微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享.扫一扫.卡券.支付等微信特有的能力.7月份的时候,因为这个分享的证书获取问题深深的栽了一坑, ...

  6. 微信开发(2):微信js sdk分享朋友圈,朋友,获取config接口注入权限验证(转)

    进行微信开发已经一阵子了,从最初的什么也不懂,到微信授权登录,分享,更改底部菜单,素材管理,等. 今天记录一下微信jssdk 的分享给朋友的功能,获取config接口注入. 官方文档走一下简单说:四步 ...

  7. 实战微信JS SDK开发:贺卡制作与播放(1)

    前段时间忙于CanTK 2.0的开发,所以博客一直没有更新.CanTK 2.0主要增强了游戏和富媒体的开发,现在编码和测试基本完成了,等文档完成了再正式发布,里面有不少激动人心的功能,等发布时再一一细 ...

  8. 微信开发(一)基于Wx-java的微信分享功能

    最近在做微信服务号开发,简单总结一下,便于自己学习积累和分享给大家: 环境介绍: Spring+ Spring MVC +Mybatis 开发语言: JAVA 微信公众平台的开发中,微信只公布了一个基 ...

  9. 微信JS SDK Demo 官方案例[转]

    摘要: 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用 ...

随机推荐

  1. max depth exceeded when dereferencing c0-param0问题的解决

    在做项目的时候,用到了dwr,有一次居然报错,错误是 max depth exceeded when dereferencing c0-param0 上网查了一下,我居然传参数的时候传的是object ...

  2. 字符串String和list集合判空验证

    1`字符串判断处理: 结论: 当if判断条件为两个,并且它们两个为或的关系,如果第一个条件为false,则继续第二个条件的判断:如果第一个条件为true,该例子不足以说明是否判断第二个条件, 最终可以 ...

  3. linux crontab 定时任务 邮件问题 及其相关的 dead.letter 问题

    最近开发项目的时候发现公司服务器用root账号登录的时候 一直会提示有新的信件,一直提示一直提示. 联想到另一台服务器上 的dead.letter文件每天都不断的变大  而且在 root家目录里 ,系 ...

  4. Spring — 循环依赖

    读完这篇文章你将会收获到 Spring 循环依赖可以分为哪两种 Spring 如何解决 setter 循环依赖 Spring 为何是三级缓存 , 二级不行 ? Spring 为啥不能解决构造器循环依赖 ...

  5. hive sql 解析json

    在hive中会有很多数据是用json格式来存储的,而我们用数据的时候又必须要将json格式的数据解析成为正常的数据,今天我们就来聊聊hive中是如何解析json数据的. 下面这张表就是json格式的表 ...

  6. POJ3262贪心

    题意:FJ去砍树,然后和平时一样留了 N (2 ≤ N ≤ 100,000)头牛吃草.当他回来的时候,他发现奶牛们正在津津有味地吃着FJ种的美丽的花!为了减少后续伤害,FJ决定立即采取行动:运输每头牛 ...

  7. flask 源码专题(二):请求上下文与全文上下文

    源码解析 0. 请求入口 if __name__ == '__main__': app.run() def run(self, host=None, port=None, debug=None, lo ...

  8. scrapy 源码解析 (四):启动流程源码分析(四) Scheduler调度器

    Scheduler调度器 对ExecutionEngine执行引擎篇出现的Scheduler进行展开.Scheduler用于控制Request对象的存储和获取,并提供了过滤重复Request的功能. ...

  9. OSCP Learning Notes - Enumeration(1)

    Installing Kioptrix: Level 1 Download the vm machine form https://www.vulnhub.com/entry/kioptrix-lev ...

  10. 多国正在遭遇新型勒索病毒Petya侵袭

    北京时间2017年6月27日晚,据外媒消息,多国正在遭遇 Petya 勒索病毒袭击,政府.银行.电力系统.通讯系统.企业以及机场都受到不同程度影响.请予关注,并做相应防范.相关事件描述及防范措施如下: ...