前提:拥有已认证的公众号 + 备案域名
如果还没有已认证的公众号,可先用测试账号 微信测试账号地址:
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
一、登录微信公众号平台
1.在“开发者中心”查看是否拥用网页服务-分享接口的权限
2.在公众号平台JS接口安全域名添加对应域名,例:(www.xxx.com 切记不带http)
3.拿到公众号对应的appID、appsecret
二、JAVA提供接口
描述:接口主要返回appid(公众号id)、timestamp(生成签名的时间戳)、nonceStr(生成签名的随机字符串)、signature(签名)
流程:
1.根据appID、appsecret获取access_token
(access_token有效期2小时,频繁刷新会被禁用,建议存储到redis或其它缓存中)
2.根据access_token获取jsapi_ticket
(jsapi_ticket有效期2小时,频繁刷新会被禁用,建议存储到redis或其它缓存中)
3.根据jsapi_ticket生成signature
注意:此接口需要接收url传参地址,地址是指在微信里的地址,所以必须动态传入,第三、四步均有前端传参步骤
代码:
controller层: 注意:如果不是@RestController,就在此方法上再加个@ResponseBody
@Resource
private WxSignService wxSignService;
/**
* 获取signature(微信分享)
*/
@RequestMapping(value = "/getSignature", method = RequestMethod.POST)
public Map<String, String>getSignature(@RequestBody UrlParam param) {
return wxSignService.getSignature(param);
}
UrlParam类:
package com.wealth.bean.model;
import java.io.Serializable;
/**
* 通用参数
*/
public class UrlParam implements Serializable {
private static final long serialVersionUID = 1L;
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
wxSignService接口:
/**
* 获取signature(微信分享)
*/
Map<String, String> getSignature(UrlParam param);
wxSignServiceImpl实现类:
1.把最上面的app_id和app_secret替换成自己的
2.缓存我用的是redis 可自行选择其它的缓存方式,redis工具类用自己项目中现成的就行
/**
* <p>微信相关</p>
* @date : 2021-10-08 15:26
**/
@Service
public class WxSignServiceImpl implements WxSignService {
private static final String app_id = "xxxx";
private static final String app_secret = "xxxxxx";
@Autowired
private RedisUtil redisUtil;
/**
* 获取signature(微信分享)
*/
@Override
public Map<String, String> getSignature(UrlParam param) {
if(param == null || StringUtils.isBlank(param.getUrl())){
return null;
}
//获取jsapi_ticket
String jsapi_ticket = getJsapiTicket();
if(StringUtils.isBlank(jsapi_ticket)) {
return null;
}
return sign(jsapi_ticket, URLDecoder.decode(param.getUrl(), "UTF-8"));
}
//获取jsapi_ticket
private String getJsapiTicket(){
//redis中是否存在
Object wx_access_token = redisUtil.get("wx_jsapi_ticket");
if(wx_access_token != null) {
return String.valueOf(wx_access_token);
}
String jsapi_ticket = "";
String accessToken = getAccessToken();
if(StringUtils.isBlank(accessToken)){
return jsapi_ticket;
}
//定义请求信息
StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgi-bin/ticket/getticket");
url.append("?");
url.append("type=jsapi");
url.append("&");
url.append("access_token=" + accessToken);
//请求微信获取jsapi_ticket
String sentGet = HttpUtil.sentGet(String.valueOf(url));
if(StringUtils.isBlank(sentGet)){
return jsapi_ticket;
}
JSONObject jsonObject = JSONObject.parseObject(sentGet);
if(jsonObject.containsKey("ticket")){
jsapi_ticket = jsonObject.getString("ticket");
//存入redis 1.5小时(微信过期机制为2小时)
redisUtil.set("wx_jsapi_ticket", jsapi_ticket, 60 * 90);
}
return jsapi_ticket;
}
//获取access_token
private String getAccessToken(){
//redis中是否存在
Object wx_access_token = redisUtil.get("wx_access_token");
if(wx_access_token != null) {
return String.valueOf(wx_access_token);
}
//定义请求信息
StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgi-bin/token");
url.append("?");
url.append("grant_type=client_credential");
url.append("&");
url.append("appid=" + app_id);
url.append("&");
url.append("secret=" + app_secret);
String access_token = "";
//请求微信获取access_token
String sentGet = HttpUtil.sentGet(String.valueOf(url));
if(StringUtils.isBlank(sentGet)){
return access_token;
}
JSONObject jsonObject = JSONObject.parseObject(sentGet);
if(jsonObject.containsKey("access_token")){
access_token = jsonObject.getString("access_token");
//存入redis 1.5小时(微信过期机制为2小时)
redisUtil.set("wx_access_token", access_token, 60 * 90);
}
return access_token;
}
//获取签名signature
public static Map<String, String> sign(String jsapi_ticket, String url) {
Map<String, String> ret = new HashMap<>();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsapi_ticket +
"&noncestr=" + nonce_str +
"×tamp=" + timestamp +
"&url=" + url;
try{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
}catch (NoSuchAlgorithmException e){
e.printStackTrace();
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
ret.put("appid", app_id);
return ret;
}
private 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;
}
//生成签名的随机串
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
//生成签名的时间戳
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
HttpUtil类:
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class HttpUtil {
/**
* get请求
* @return
* @param url
*/
public static String sentGet(String url) {
try {
HttpClient client = HttpClients.createDefault();
//发送get请求
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
/**请求发送成功,并得到响应**/
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
/**读取服务器返回过来的json字符串数据**/
String strResult = EntityUtils.toString(response.getEntity());
return strResult;
}
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
三、Vue请求接口以及设置微信分享
1.执行命令
npm install weixin-js-sdk
2.在需要分享的页面添加导包
import wx from 'weixin-js-sdk';
3.在需要分享的页面添加代码
描述:
1.mounted为页面初始化加载内容
2.this.$httpServer.post为封装的post请求,此处使用自己项目中的post请求方式即可
mounted() {
this.initData();
}
//微信分享源码
initData(){
const data = {
url: encodeURIComponent(location.href.split('#')[0])
}
this.$httpServer
.post("/getSignature", data)
.then((response) => {
var result = response;
wx.config({
debug: true,//生产环境需要关闭debug模式
appId: result.appid,
timestamp: result.timestamp,//生成签名的时间戳
nonceStr: result.nonceStr,//生成签名的随机字符串
signature: result.signature,//签名
jsApiList: [
'onMenuShareTimeline','onMenuShareAppMessage'
]
});
const shareData = {
"imgUrl": "",//这里填照片,必须是绝对路径 例http https开头可以直接访问
"title": "这是标题",
"desc": "这是内容",
'link': "https://www.xxx.com/"//这里要填和你js安全填的那个一致,不过这里需要加http
};
wx.ready(function() {
wx.onMenuShareTimeline(shareData);
wx.onMenuShareAppMessage(shareData);
wx.error(function(res) {
alert(res.errMsg);
});
});
})
.catch((e) => {
});
}
四、H5请求接口以及设置微信分享
1.在需要分享的页面引入js
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script src="/js/common/shareJssdk.js"></script>
2.shareJssdk.js内容
$(function(){
var url = encodeURIComponent(location.href.split('#')[0]);
//分享
$.ajax({
type : "get",
url : "/getSignature",
dataType : "json",
data:{
url:url
},
success : function(result){
wxstart(result);
},
error:function(data){
alert("连接失败!");
}
});
function wxstart(result){
wx.config({
debug: true, // 正式环境关闭调试模式
appId: result.appid, //公众号的唯一标识
timestamp: result.timestamp, //生成签名的时间戳
nonceStr: result.nonceStr, //生成签名的随机串
signature: result.signature,//签名
jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage"]
});
const shareData = {
"imgUrl": "",//这里填照片,必须是绝对路径 例http https开头可以直接访问
"title": "这是标题",
"desc": "这是内容",
'link': "https://www.xxx.com/"//这里要填和你js安全填的那个一致,不过这里需要加http
};
wx.ready(function() {
wx.onMenuShareTimeline(shareData);
wx.onMenuShareAppMessage(shareData);
wx.error(function(res) {
alert(res.errMsg);
});
});
}
})