1,首先需要有微信開發(fā)者賬號
- 直接使用微信測試號:http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index。個人微信訂閱號非認證狀態(tài)不支持分享接口,所以只能使用測試號。
2,測試號配置說明
- 接口配置信息,先將本地ip內網(wǎng)穿透成外網(wǎng)可訪問的域名,在通過你服務器的接口校驗token(url指向你服務器端的接口)。 參考https://blog.csdn.net/Curtisjia/article/details/106041565?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.searchformbaiduhighlight&spm=1001.2101.3001.4242 內網(wǎng)穿透建議使用https://natapp.cn/免費的版本就夠用了

image-20210917132925577.png
-
JS接口安全域名。配置你服務器的域名,不加http(s)://這些,例如www.baidu.com詳見開發(fā)文檔
image-20210917134206088.png -
測試號二維碼,自己微信關注就好了,微信號列就是對應的openIdimage-20210917134410465.png
-
體驗接口權限表。有的接口需要手動設置或者開啟,關注一下。image-20210917134457417.png
-
注意,如果后期過渡到服務號真實開發(fā)實現(xiàn)功能,還需要配置JS安全域名里的服務器秘鑰image-20210917134714898.png

image-20210917134756726.png
測試號不需要設置。
3,找到微信jssdk開發(fā)文檔
4,引入微信的JS文件
-
可以直接引用image-20210917135040815.png
-
vue中也可以npm install weixin-js-sdk --save 然后在頁面中引用image-20210917135227455.png
5,后端業(yè)務邏輯
- 部分后端處理代碼
//前端請求的url
JSONObject reqJson = JSONObject.fromObject(reqStr);
String accessToken = WeixinUtil.getAccessToken();
String ticket = WeixinUtil.getJSAPITicket(accessToken);
Map<String, String> result = JSSign.sign(ticket,
JSONObject.fromObject(reqJson.getString("config")).getString("url"));
respJson.put("appId",Config.getWxConfig().getAppId());
respJson.put("nonceStr",result.get("nonceStr"));
respJson.put("signature",result.get("signature"));
respJson.put("timestamp",result.get("timestamp"));
respJson.put(ConstantUtil.RESP_CODE, ConstantUtil.RespCode.SUCC);
private static ConcurrentHashMap<String, String> TICKET_MAP = new ConcurrentHashMap<>();
private static final String JSAPI_TICKET = "jsapi_ticket";
private static final String EXPIRES_IN = "expires_in";
private static ConcurrentHashMap<String, String> ACCESS_TOKEN_MAP = new ConcurrentHashMap<>();
private static final String ACCESS_TOKEN = "access_token";
/**
* 獲取微信access_token
* @return
* @throws Exception
*/
public static String getAccessToken() throws Exception{
String accessToken = null;
String response = null;
if (ACCESS_TOKEN_MAP.get(ACCESS_TOKEN) != null && Integer.parseInt(ACCESS_TOKEN_MAP.get(EXPIRES_IN)) > Utility.getCurrentTimeStamp()) {
accessToken = ACCESS_TOKEN_MAP.get(ACCESS_TOKEN);
log.info("getWxToken() end, access-token from redis, expires_in, accessToken={}"+accessToken);
return accessToken;
}
try {
//assessTokenUrl:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET
response = sendGET(Config.getWxConfig().getAccessTokeUrl().replace("APPID", appid).replace("SECRET", secret),null);
} catch (Exception e) {
log.error("getWxToken() exception. ", e);
}
if (response != null) {
JSONObject jsonObject = JSONObject.fromObject(response);
accessToken = jsonObject.getString("access_token");
Integer expiresIn = Integer.parseInt(jsonObject.getString("expires_in"));
ACCESS_TOKEN_MAP.put(ACCESS_TOKEN, accessToken);
ACCESS_TOKEN_MAP.put(EXPIRES_IN, String.valueOf(expiresIn + Utility.getCurrentTimeStamp() - 600));
}
return accessToken;
}
/**
* 獲取jsapiticket
* @return
* @throws Exception
*/
public static String getJSAPITicket(String token) throws Exception{
String JsApiTicket = null;
String response = null;
if (TICKET_MAP.get(JSAPI_TICKET) != null && Integer.parseInt(TICKET_MAP.get(EXPIRES_IN)) > Utility.getCurrentTimeStamp()) {
JsApiTicket = TICKET_MAP.get(JSAPI_TICKET);
log.info("getJSAPITicket() end, js_api_ticket from redis, expires_in, accessToken={}"+JsApiTicket);
return JsApiTicket;
}
try {
//jsapiticket:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
response = sendGET(Config.getWxConfig().getJsapiTicketUrl().replace("ACCESS_TOKEN", token),null);
} catch (Exception e) {
log.error("getWxToken() exception. ", e);
}
if (response != null) {
JSONObject jsonObject = JSONObject.fromObject(response);
JsApiTicket = jsonObject.getString("ticket");
Integer expiresIn = Integer.parseInt(jsonObject.getString("expires_in"));
TICKET_MAP.put(JSAPI_TICKET, JsApiTicket);
TICKET_MAP.put(EXPIRES_IN, String.valueOf(expiresIn + Utility.getCurrentTimeStamp() - 600));
}
return JsApiTicket;
}
6,前端業(yè)務邏輯
<template>
<div>
<a @click="onShareClick">點擊分享</a>
</div>
</template>
<script>
export default {
name: "TestShare",
created() {
let loading = this.$loading({
lock: true,
text: '初始化中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
let config = {
url: location.href.split('#')[0]
};
//下單
this.$post('api/Wx/getWxConfig.do', {
config: config
}).then((response) => {
if (response.respCode == '00') {
// // console.log("1111");
config.nonceStr = response.nonceStr;
config.signature = response.signature;
config.timestamp = response.timestamp;
config.appId = response.appId;
config.debug = true;
config.jsApiList = [ // 所有要調用的 API 都要加到這個列表中
'checkJsApi',
'updateAppMessageShareData',
'updateTimelineShareData',
],
wx.config(config);
wx.ready(() => {
this.wx = wx;
wx.checkJsApi({
jsApiList: ['updateAppMessageShareData'], // 需要檢測的JS接口列表,所有JS接口列表見附錄2,
success: function(res) {
// 以鍵值對的形式返回,可用的api值true,不可用為false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
alert("success");
}
});
});
wx.error(function (res) {
alert(res.errMsg);
console.info('error 驗證失敗', res);
});
} else {
this.$message.error('微信SDK初始化失?。? + response.respDesc);
}
loading.close();
}).catch((e) => {
this.$message.error('微信SDK初始化失??!'+e);
loading.close();
});
},
share() {
wx.updateAppMessageShareData({
title: "分享", // 分享標題
desc: "分享", // 分享描述
link: "", // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應的公眾號JS安全域名一致
imgUrl: "", // 分享圖標
success: function() {
alert("預分享成功");
// 設置成功
},
});
},
}
</script>
7,流程總結
前端上送當前地址url,請求token和ticket獲取簽名(需要服務端緩存)。拿到簽名。在前端wx.config中初始化jssdk。初始化成功后就可以正常調用jssdk的方法啦。
-
image-20210917142531769.png
image-20210917143306319.png
8,注意事項
目前分享接口僅支持預分享(分享后還需點擊右上角三個點手動分享),不支持點擊直接跳出好友列表(以前支持的已廢棄)。優(yōu)化處理可以使用https://blog.csdn.net/chuchenqian9735/article/details/101019938的方法。
-
大坑!?。∏岸松纤偷漠斍绊撁鎢rl是 location.href.split('#')[0]。微信文檔有的地方說需要加image-20210917141620782.png
但是實際簽名中不需要加encodeURL():

image-20210917141707349.png
所以上送就直接送當前地址就好了,不需要轉義。
- ios設備真機調試時候會報簽名失敗,是因為ios設備在初始化config時只認第一次進入時的url(比如初始化的頁面是http://xx/pay。但是發(fā)請求時候的地址是http://xx,所以導致上送簽名的url和調用初始化的url不一致。可通過把初始化操作放在項目第一次進入的頁面解決。android無此問題)








