Spring Boot +VUE微信好友分享
使用工具
IDEA 2020.3
安装微信的JS-SDK
// 在终端输入
npm install weixin-js-sdk
前端代码(vue)
使用异步请求从服务端获取微信jssdk的授权参数
// ***.js文件内容
import request from '@/router/axios';
export const getWxConfig= (url) => {
return request({
url: '这里是你接口地址',
method: 'post',
data: {
url:url
}
})
}
.VUE文件
// 在页面引入微信的jdk
import wx from "weixin-js-sdk";
// 在页面引入异步
import {getWxConfig} from "js文件位置路径";
// 在页面mounted()里动态获取当前分享页面的URL,我们只要#之前的。如果每次分享的时候动态获取URL会导致二次分享失败
//在你第一次分享后,微信会在你的域名后拼接一些参数,导致二次分享失败
this.firstUrl=location.href.split('#')[0];
// 在页面引入异步
//wx.config如果是一个页面,只需获取一次即可。我这里是每次分享前都会获取一次(这个我待优化)
getWxConfigMessage() {
getWxConfig(this.firstUrl).then(res => {
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.data.data.appId, // 必填,公众号的唯一标识
timestamp: res.data.data.timesTamp, // 必填,生成签名的时间戳
nonceStr: res.data.data.nonceStr, // 必填,生成签名的随机串
signature: res.data.data.signaTure,// 必填,签名
jsApiList: ["updateAppMessageShareData"] // 必填,需要使用的JS接口列表,这个接口是分享好友接口
});
})
//wx.ready里的参数必须同步请求获取并且必须获取到授权后方可访问
this.$nextTick(() => {
//因为微信官方把跳转外部链接这条路封死了,所以用一个新页面进行间接跳转,如果你跳转的url的域名与js安全域名一样,则无需此操作
let jumpUrl = this.firstUrl + "#/toJump?url=" + window.btoa("外部链接URL");
wx.ready(function () { //需在用户可能点击分享按钮前就先调用
wx.updateAppMessageShareData({
title: '', // 分享标题
desc: '', // 分享描述
link: jumpUrl,// 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致,不支持在此处拼接,必须是变量。
imgUrl: '', // 分享图标
success: function () {
}
})
});
});
},
后端代码(主要是获取wx.config权限)
微信分享授权所需要的实体类
public class AccessToken extends BaseEntity {
/**
* 微信获取的凭证
*/
@ApiModelProperty(value = "凭证")
private String accessToken;
/**
* 凭证有效时间,单位:秒
*/
@ApiModelProperty(value = "凭证有效时间")
private String expiresIn;
}
public class WxConfig extends BaseEntity {
/**
* 公众号唯一标识
*/
@ApiModelProperty(value = "公众号唯一标识")
private String appId;
/**
* 生成签名的时间戳
*/
@ApiModelProperty(value = "时间戳")
private String timesTamp;
/**
* 生成签名的随机串
*/
@ApiModelProperty(value = "随机串")
private String nonceStr;
/**
* 签名
*/
@ApiModelProperty(value = "时间戳")
private String signaTure;
}
#application-xx.yml文件内容
#微信配置
wx:
appid: *********
secret: ***************
//这个是在application-xx.yml里配置appid与秘钥用的实体类。
@Data
@Component
@ConfigurationProperties(prefix = "wx")
public class WxDTO {
private static final long serialVersionUID = 1L;
/**
* Wx 的appid
* */
private String appid;
/**
* Wx 的秘钥
* */
private String secret;
}
微信分享授权所需要的工具类
/***
* 模拟get请求
* @param url
* 格式
* @param charset
* 超时时间
* @param timeout
* @return result
*/
public static String sendGet(String url, String charset, int timeout) {
String result = "";
try
{
URL u = new URL(url);
try
{
URLConnection conn = u.openConnection();
conn.connect();
conn.setConnectTimeout(timeout);
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
String line="";
while ((line = in.readLine()) != null)
{
result = result + line;
}
in.close();
} catch (IOException e) {
return result;
}
}
catch (MalformedURLException e)
{
return result;
}
return result;
}
/***
* 获取AccessToken
* appid
* @param appid
* 秘钥
* @param appSecret
* @return token
*/
//这里需要访问外网发送get请求
public static AccessToken getAccessToken(String appid,String appSecret) {
String url ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appSecret;
String backData= WxUtil.sendGet(url, "utf-8", 15000);
JSONObject jsonObject = JSON.parseObject(backData);
String accessToken =jsonObject.getString("access_token");
String expiresIn = jsonObject.getString("expires_in");
AccessToken token= new AccessToken();
token.setAccessToken(accessToken);
token.setExpiresIn(expiresIn);
return token;
}
public static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
/***
* 生成签名的随机串
* @return 随机串
*/
public static String createNonceStr() {
return UUID.randomUUID().toString();
}
/***
* 生成签名的时间戳
* @return 时间戳
*/
public static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
微信分享授权服务层
@Service
public class WXDeveloperServiceImpl implements WXDeveloperService {
@Autowired
private WxDTO wxDTO;
//redis操作工具类
@Resource
private BladeRedis bladeRedis;
@Override
public String getJSApiTicket(String accessToken) {
//获取token
String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi";
String backData = WxUtil.sendGet(urlStr, "utf-8", 10000);
JSONObject jsonObject = JSON.parseObject(backData);
String jsapiTicket = jsonObject.getString("ticket");
return jsapiTicket;
}
@Override
public WxConfig sign(String jsapiTicket, String url) {
WxConfig wxConfig = new WxConfig();
wxConfig.setAppId(wxDTO.getAppid());
wxConfig.setNonceStr(WxUtil.createNonceStr());
wxConfig.setTimesTamp(WxUtil.createTimestamp());
String string1;
String signaTure = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsapiTicket +
"&noncestr=" + wxConfig.getNonceStr() +
"×tamp=" + wxConfig.getTimesTamp() +
"&url=" + url;
System.out.println(string1);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signaTure = byteToHex(crypt.digest());
wxConfig.setSignaTure(signaTure);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return wxConfig;
}
}
微信分享授权controller
@Autowired
private WxDTO wxDTO;
/**
* redis操作工具类
*/
private final BladeRedis bladeRedis;
/**
* JS-SDK的页面注入配置信息
*/
@PostMapping("/*********")
@ApiOperation(value = "微信分享注入配置信息", notes = "传入用户ID,返回用户信息")
public R<WxConfig> injectInformation(@RequestBody Map<String, String> urlMap ) throws UnsupportedEncodingException {
String url = urlMap.get("url");
//从redis获取jsapi
String jsapi = bladeRedis.get(CacheNames.JSAPI_KEY);
/* 如果获取不到 */
if (StringUtils.isEmpty(jsapi)) {
//获取普通accessToken
String accessToken = WxUtil.getAccessToken(wxDTO.getAppid(), wxDTO.getSecret()).getAccessToken();
//插入redis 这是我们的redis工具accessToken时效只有两个小时
bladeRedis.setEx(CacheNames.SHARE_KEY, accessToken, Duration.ofSeconds(7200));
//获取JSApiTicket
String JSApiTicket = WXDeveloperService.getJSApiTicket(accessToken);
bladeRedis.setEx(CacheNames.JSAPI_KEY, JSApiTicket, Duration.ofSeconds(7200));
WxConfig wxConfig = WXDeveloperService.sign(JSApiTicket, url);
return R.data(wxConfig);
} else {
WxConfig wxConfig = WXDeveloperService.sign(jsapi, url);
return R.data(wxConfig);
}
}
总结
pc端用微信开发者工具进行调试,实验微信分享是否好用,只能去手机端验证。以上代码复制即可使用,只需更改appid与秘钥信息就行。相关错误代码请去微信开发者文档查阅
微信开发者文档网址