随着腾讯帝国的强大,越来越多的APP、第三方平台需要倚靠腾讯的产品发展壮大了。微信拥有上十亿用户基础,各大小公司自然不会放过这么优质的平台,所以现在以及未来都会有很多很多与微信集成的地方,比如今天演示的与微信集成实现分享功能。

实现微信的分享功能需要前后端配合完成,前端主要是调用后台接口获取signature/nonceStr等信息来配置wx.config,然后设置微信的js事件,比如微信分享的标题,连接,图片等,分享成功之后要做的事情等。

后端主要是获取signature和nonceStr等,提供给前端。

前后端集成微信实现分享的主要步骤如下:

1、根据当前的url,获取signature,nonceStr,timestamp 和appId
2、通过signature,nonceStr,timestamp 和appId来配置微信 wx.config
3、通过wx.ready函数实现微信分享功能

前端要做的:

引入微信JS-SDK,并设置请求:

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>//分享核心js代码
$(document).ready(function () {//通过ajax,在页面加载的时候获取微信分享接口signature,nonceStr,timestamp 和appId$.ajax({type: "post",url: "/weixin/share",dataType: "json",data:"url="+window.location.href,success: function (data) {wx.config({debug: false,appId: data.appId,timestamp: data.timestamp,nonceStr: data.nonceStr,signature: data.signature,jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline', 'hideAllNonBaseMenuItem', 'showMenuItems']// 功能列表,我们要使用JS-SDK的什么功能});wx.ready(function () {// 获取“分享给朋友”按钮点击状态及自定义分享内容接口wx.onMenuShareAppMessage({title: "分享自定义标题", // 分享标题desc: "分享自定义描述", // 分享描述link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接imgUrl:'/images/photo/1.jpg', // 分享图标type: 'link', // 分享类型,music、video或link,不填默认为linksuccess: function () {//成功之后的回调}});wx.hideAllNonBaseMenuItem();wx.showMenuItems({menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline'] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3});wx.onMenuShareTimeline({title: "分享自定义标题", // 分享标题desc: "分享自定义描述", // 分享描述link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接imgUrl:'/images/photo/1.jpg', // 分享图标type: 'link', // 分享类型,music、video或link,不填默认为linksuccess: function () {//成功之后的回调}cancel: function () {// 用户取消分享后执行的回调函数}});});wx.error(function (res) {//打印错误消息。及把 debug:false,设置为debug:ture就可以直接在网页上看到弹出的错误提示});}})
});

后端要做的:

Java代码,获取 signature,nonceStr,timestamp 和appId

下面是/share接口信息:

@RequestMapping(value = "/share", method = RequestMethod.POST)@ResponseBodypublic Map<String, Object> share(HttpServletRequest request) {String urlTemp = "http://" + request.getServerName() + request.getContextPath();String urlpath = "http://" + request.getServerName();String appUrl = request.getParameter("url");if (request.getParameter("code") != null) {appUrl += "&code=" + request.getParameter("code");}if (request.getParameter("state") != null) {appUrl += "&state=" + request.getParameter("state");}return WxConfigUtil.getSignature(appUrl, ContentValues.APPID, ContentValues.SECRET, urlTemp, urlpath);}

工具类我就把整个贴上来了,其中有些方法是没有用到的。

getSignature()整个方法是微信分享中的核心方法,用来获取signature,nonceStr,timestamp 和appId这几个核心参数。

package com.blog.common.util;import com.alibaba.fastjson.JSONObject;
import com.blog.common.model.Token;import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;/*** 公众平台通用接口工具类** @author james* @date 2015-02-27*/
public class WxConfigUtil {// 获取access_token的接口地址(GET) 限2000(次/天)public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";// 获取jsapi_ticket的接口地址(GET) 限2000(次/天)public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";// 缓存添加的时间public static String cacheAddTime = null;// token,ticket缓存public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();// token对应的keyprivate static final String TOKEN = "token";// ticket对应的keyprivate static final String TICKET = "ticket";/*** 外部获取签名入口类** @param appUrl    应用的url* @return*/public static Map<String, Object> getSignature(String appUrl, String appId, String secret, String url, String urlpath) {// 生成签名的随机串String noncestr = RandomUtil.getStringRandom(4);if (appUrl == null || "".equals(appUrl)) {return null;}String signature = null;Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);Token accessTicket = getTicket(accessTocken.getToken(), System.currentTimeMillis() / 1000);signature = signature(accessTicket.getTicket(), cacheAddTime, noncestr, appUrl);System.out.println("-=-=-=-=-=-=-=-=appUrl:" + appUrl);System.out.println("-=-=-=-=-=-=-=-=token:" + accessTocken.getToken());System.out.println("-=-=-=-=-=-=-=-=ticket:" + accessTicket.getTicket());System.out.println("-=-=-=-=-=-=-=-=signature:" + signature);System.out.println("-=-=-=-=-=-=-=-=timestamp:" + cacheAddTime);Map<String, Object> map = new HashMap<>();map.put("appId", appId);map.put("timestamp", cacheAddTime);map.put("nonceStr", noncestr);map.put("appUrl", appUrl);map.put("signature", signature);map.put("url", url);map.put("urlpath", urlpath);return map;}/*** 获得Token** @return*/public static String getToken(String appId, String secret) {Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);return accessTocken.getToken();}/*** 签名** @param timestamp* @return*/private static String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;timestamp = "timestamp=" + timestamp;noncestr = "noncestr=" + noncestr;url = "url=" + url;String[] arr = new String[]{jsapi_ticket, noncestr, timestamp, url};// 将token、timestamp、nonce,url参数进行字典序排序Arrays.sort(arr);StringBuilder content = new StringBuilder();for (int i = 0; i < arr.length; i++) {content.append(arr[i]);if (i != arr.length - 1) {content.append("&");}}MessageDigest md = null;String tmpStr = null;try {md = MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[] digest = md.digest(content.toString().getBytes());tmpStr = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}content = null;return tmpStr;}/*** 获取access_token** @param appid     凭证* @param appsecret 密钥* @return*/public static Token getToken(String appid, String appsecret, long currentTime) {Token tockenTicketCache = getTokenTicket(TOKEN);Token Token = null;if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存存在并且没过期System.out.println("==========缓存中token已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");return tockenTicketCache;}System.out.println("==========缓存中token不存在或已过期===============");String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);JSONObject jsonObject = httpRequest(requestUrl, "GET", null);// 如果请求成功if (null != jsonObject) {Token = new Token();Token.setToken(jsonObject.getString("access_token"));Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次System.out.println("==========tocket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");Token.setAddTime(currentTime);updateToken(TOKEN, Token);}return Token;}/*** 获取ticket** @param token* @return*/private static Token getTicket(String token, long currentTime) {Token tockenTicketCache = getTokenTicket(TICKET);Token Token = null;if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存中有ticketSystem.out.println("==========缓存中ticket已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");return tockenTicketCache;}System.out.println("==========缓存中ticket不存在或已过期===============");String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);JSONObject jsonObject = httpRequest(requestUrl, "GET", null);// 如果请求成功if (null != jsonObject) {Token = new Token();Token.setTicket(jsonObject.getString("ticket"));Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次System.out.println("==========ticket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");Token.setAddTime(currentTime);updateToken(TICKET, Token);}return Token;}/*** 发起https请求并获取结果** @param requestUrl    请求地址* @param requestMethod 请求方式(GET、POST)* @param outputStr     提交的数据* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)*/private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {JSONObject jsonObject = null;StringBuffer buffer = new StringBuffer();try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = {new MyX509TrustManager()};SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());// 从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();httpUrlConn.setSSLSocketFactory(ssf);httpUrlConn.setDoOutput(true);httpUrlConn.setDoInput(true);httpUrlConn.setUseCaches(false);// 设置请求方式(GET/POST)httpUrlConn.setRequestMethod(requestMethod);if ("GET".equalsIgnoreCase(requestMethod))httpUrlConn.connect();// 当有数据需要提交时if (null != outputStr) {OutputStream outputStream = httpUrlConn.getOutputStream();// 注意编码格式,防止中文乱码outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 将返回的输入流转换成字符串InputStream inputStream = httpUrlConn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();// 释放资源inputStream.close();inputStream = null;httpUrlConn.disconnect();jsonObject = JSONObject.parseObject(buffer.toString());// jsonObject = JSONObject.fromObject(buffer.toString());} catch (ConnectException ce) {System.out.println("Weixin server connection timed out.");} catch (Exception e) {System.out.println("https request error:{}" + e.getMessage());}return jsonObject;}/*** 将字节数组转换为十六进制字符串** @param byteArray* @return*/private static String byteToStr(byte[] byteArray) {String strDigest = "";for (int i = 0; i < byteArray.length; i++) {strDigest += byteToHexStr(byteArray[i]);}return strDigest;}/*** 将字节转换为十六进制字符串** @param mByte* @return*/private static String byteToHexStr(byte mByte) {char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}/*** 从缓存中读取token或者ticket** @return*/private static Token getTokenTicket(String key) {if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {System.out.println("==========从缓存中获取到了" + key + "成功===============");return TOKEN_TICKET_CACHE.get(key);}return null;}/*** 更新缓存中token或者ticket** @return*/private static void updateToken(String key, Token accessTocken) {if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {TOKEN_TICKET_CACHE.remove(key);System.out.println("==========从缓存中删除" + key + "成功===============");}TOKEN_TICKET_CACHE.put(key, accessTocken);cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新缓存修改的时间System.out.println("==========更新缓存中" + key + "成功===============");}}

参考:
https://blog.csdn.net/juewang_love/article/details/76076417

Java + JS实现微信分享功能相关推荐

  1. java对接微信分享_Java编程调用微信分享功能示例

    本文实例讲述了Java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的 ...

  2. java如何调用微信功能_Java编程调用微信分享功能示例

    本文实例讲述了java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的 ...

  3. 微信分享功能问题-描述内容换行,导致js加载失败

    jsContent内容存在换行符,导致js处理失败, 解决办法,在后台接口中替换'/r/n'为空,并截取前30位 weiXinJsSdk.setSharcontent(StringUtils.isNo ...

  4. 服务器静态页面分享微信,JS中静态页面如何实现微信分享功能

    JS中静态页面如何实现微信分享功能 发布时间:2021-07-06 11:09:02 来源:亿速云 阅读:65 作者:小新 这篇文章主要介绍了JS中静态页面如何实现微信分享功能,具有一定借鉴价值,感兴 ...

  5. Android微信h5分享,H5网页实现微信分享功能

    H5网页实现微信分享功能 一,首先在公众号管理后台"公众号设置"的"功能设置"里填写JS接口安全域名,域名需要通过ICP备案,没有备案域名可以用SAE.BAE等 ...

  6. centos + nodejs + egg2.x 开发微信分享功能

    前言 近期把自用的微信公众号微信分享模块从 php 修改为 nodejs 的版本,虽然这是一个很小的功能,但仍然选择了 egg 框架,也算是为未来继续开发公众号,做点扩展的准备. 本文章仅为项目介绍, ...

  7. vue项目做微信分享功能

    vue项目做微信分享功能 安装sdk npm install weixin-js-sdk --save 方法 1.新建js文件wxapi.js 2.在wxapi.js中引入sdk以及配置一些基本信息( ...

  8. vue 如何调用微信分享_Vue开发 添加微信分享功能(全局分享)

    在Vue4.0开发微信公众号的时候,需要做微信分享功能.这个功能其实还算简单,具体的思路如下: 1.安装微信JSSDK和Axios(axios是http请求插件) 2.向后台请求微信配置参数 3.初始 ...

  9. Android Studio 微信分享功能(包括可以分享到朋友圈,分享到朋友)

    第一步:配置sdk 在build.gradle文件中,添加如下依赖即可: 在Android Studio中新建你的工程,并保证网络设置可以成功从jcenter下载微信SDK即可. dependenci ...

最新文章

  1. UFS和eMMC闪存差异在哪?
  2. python哪些是可变对象_什么是Python可变对象和不可变对象
  3. python 测试框架之---testtools
  4. 派生类的友元与析构【C++继承】
  5. easyUI parser的使用
  6. 词云图 - WorldCloud - Python代码实现
  7. 通过动态获取cookie爬取国家企业信用信息公司系统
  8. Java回调函数使用
  9. 【android】读取/res/raw目录下的文件
  10. Django之ORM的增删改查
  11. 地表反照率数据、地表净辐射通量、太阳辐射数据、地表温度、地表显热通量、NDVI、NPP、土地利用数据
  12. ascll编码表图片_ASCLL编码表
  13. RecyclerView.ViewHolder、Adapter
  14. Arduino基础应用学习
  15. win10装win7进入不了bios的解决方法
  16. e3是合法浮点数吗_下面四个选项中,均是合法浮点数的是()
  17. 找工作面试会遇到哪些坑(校招篇)
  18. java任意键继续_java 按任意键继续怎么写
  19. 《Java程序设计》复习整理
  20. EFR32MG22与TI CC2652RSIP对比

热门文章

  1. 红外控制Windows音量by python
  2. XP系统装PhotoShop的CS3版本
  3. 求有限集上等价关系等价类的数目
  4. Visual Studio 2010
  5. LaTeX技巧心得28:如何在文中实现带圈的数字和圈中加号
  6. 数学建模----图与网络模型
  7. u校园刷题脚本一键答题挂时长支持视听说读写综合
  8. [Java]Java面试题全集(下)
  9. 数字信号处理matlab实验报告,数字信号处理,matlab实验报告
  10. spring boot +ajax上传文件前后端分离完整实现示例代码