本文主要介绍了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. 【错误】fatal: destination path already exists and is not an empty directory. 错误及解决办法

    今天在使用Git for Windows clone代码时,遇到了题目所示的错误,简单来说就是目标路径‘.’已经存在并且不是一个空目录. 可是在我在文件夹下并没有看到任何文件,显示“该文件夹为空”,然 ...

  2. asp.net core 发布包含文件

    这样这个文件在发布的时候,就会包含进去了.

  3. 初用MySQL Mysql示例库 Navicat15

    初用MySQL Mysql示例库 Navicat15   查询MySQl版本 Mysql shell > select version(); 右括号,not version   查看初始密码 M ...

  4. Spring Boot 2.x基础教程:事务管理入门

    什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...

  5. requests接口自动化6-Body里json格式数据形式的post请求:json

    Body里json格式数据形式的post请求:用json传参 fiddler里请求响应内容: 传递的json数据 [{"stepId":"0","ca ...

  6. python 爬虫:HTTP ERROR 406

    解决方法: 设置了Accept头后解决了,但是还是不知道原因 headers:{ Accept:"text/html, application/xhtml+xml, */*" }原 ...

  7. 李航统计学习方法(第二版)(六):k 近邻算法实现(kd树(kd tree)方法)

    1. kd树简介 构造kd树的方法如下:构造根结点,使根结点对应于k维空间中包含所有实例点的超矩形区域;通过下面的递归方法,不断地对k维空间进行切分,生成子结点.在超矩形区域(结点)上选择一个坐标轴和 ...

  8. PHP 反序列化漏洞入门学习笔记

    参考文章: PHP反序列化漏洞入门 easy_serialize_php wp 实战经验丨PHP反序列化漏洞总结 PHP Session 序列化及反序列化处理器设置使用不当带来的安全隐患 利用 pha ...

  9. redis必知会

    Redis 是单进程单线程的? Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消 除了传统数据库串行控制的开销. Redis 的持久化机制是什么?各自的优缺点? Red ...

  10. 各种jar包下载地址

    standard.jar和jstl.jar的下载地址 http://repo2.maven.org/maven2/javax/servlet/jstl/ http://repo2.maven.org/ ...