網頁分享到微信自定義標題,內容和圖片
阿新 • • 發佈:2018-12-20
網頁分享到微信中自定義標題,內容和圖片
隨便說說:
網頁現在也可以通過微信中直接開啟,這就是用到時微信的瀏覽器,也可以通過微信瀏覽器中右上角進行分享到朋友,朋友圈,QQ等。這是需要微信的JSSDK的機制所以還是要進行一些配置才可以,而這些配置是需要微信公眾號的appId和appsecret的,所以如果沒有這些,也是不能進行自定義的。
實現過程
- 首先可以先閱讀以下微信的JS-SDK的說明文件微信JS-SDK說明文件
- 繫結域名,登入微信公眾平臺,進入“公眾號設定”的功能設定裡面填寫js介面安全域名,這個是要填寫的是你微信瀏覽器要開啟的域名地址。不能新增IP地址。
- 引入js檔案
- 通過config介面注入許可權並驗證配置
- 這一步算是整個步驟中最關鍵的一步,必須正確的配置資訊才可以進行呼叫JS-SDK。
wx.config({ debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。 appId: '', // 必填,公眾號的唯一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名 jsApiList: [] // 必填,需要使用的JS介面列表 });
下面講如何獲取 timestamp, noceStr(記得這個駝峰結構),singature
獲取配置
先說說最煩人的singature,對於初學小程式的簡直要了老夫的命,這是啥玩意,還是簽名,所以我會把自己踩的坑給大家說一下。 獲取簽名實際是需要四步
1. 根據appId和appsecret獲取access_token;
2. 使用access_token獲取jsapi_ticket;
3. 使用時間戳,隨機數,jsapi_ticket和要訪問的url按照簽名演算法拼接字串;
4. 對第三步的字串進行SHA1加密,得到簽名;
第一步,獲取access_token
appId和appsecret可以在微信公眾平臺--開發-基本配置中查詢
public static String getAccess_token(String appId, String appSecret){
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
String accessToken = null;
try
{
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必須是get方式請求
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 連線超時30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 讀取超時30秒
http.connect();
InputStream is = http.getInputStream();
int size = is.available();
byte[] jsonBytes = new byte[size];
is.read(jsonBytes);
String message = new String(jsonBytes, "UTF-8");
JSONObject jsonObj = JSONObject.fromObject(message);
accessToken = jsonObj.getString("access_token");
}
catch (Exception e)
{
e.printStackTrace();
}
return accessToken;
}
第二步 獲取jsapi_ticket
/**
* 獲得ACCESS_TICKET
*
* @Title: ACCESS_TICKET
* @Description: 獲得ACCESS_TICKET
* @param @return 設定檔案
* @return String 返回型別
* @throws
*/
public static String getAccess_ticket(String access_token) {
String ticket = null;
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//這個url連結和引數不能變
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必須是get方式請求
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 連線超時30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 讀取超時30秒
http.connect();
InputStream is = http.getInputStream();
int size = is.available();
byte[] jsonBytes = new byte[size];
is.read(jsonBytes);
String message = new String(jsonBytes, "UTF-8");
JSONObject demoJson = JSONObject.fromObject(message);
System.out.println("JSON字串:"+demoJson);
ticket = demoJson.getString("ticket");
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return ticket;
}
這裡拿到對應的jsapi_ticket之後就可以進行引數排序和拼接字串並加密
第三步:SHA1加密
public static String SHA1(String decript) {
try {
MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
digest.update(decript.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
// 位元組陣列轉換為 十六進位制 數
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
第四步: 獲取簽名
public static void main(String[] args) {
//1、獲取AccessToken
String accessToken = getAccessToken();
//2、獲取Ticket
String jsapi_ticket = getTicket(accessToken);
//3、時間戳和隨機字串
String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//隨機字串
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//時間戳
System.out.println("accessToken:"+accessToken+"\njsapi_ticket:"+jsapi_ticket+"\n時間戳:"+timestamp+"\n隨機字串:"+noncestr);
//4、獲取url
String url="http://www.luiyang.com/add.html";
/*根據JSSDK上面的規則進行計算,這裡比較簡單,我就手動寫啦
String[] ArrTmp = {"jsapi_ticket","timestamp","nonce","url"};
Arrays.sort(ArrTmp);
StringBuffer sf = new StringBuffer();
for(int i=0;i<ArrTmp.length;i++){
sf.append(ArrTmp[i]);
}
*/
//5、將引數排序並拼接字串
String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url;
//6、將字串進行sha1加密
String signature =SHA1(str);
System.out.println("引數:"+str+"\n簽名:"+signature);
}
改寫之後的程式碼,json格式返回。
protected void doPost(HttpServletRequest request, HttpServletResponse response){
//appId和appSecret
String appId = "XXXXX";
String appSecret = "XXXXX";
//外部傳入url獲取url url需要是微信中開啟的url否則會報錯。
String URL = request.getParameter("url");
//轉換url
String url="";
//需要轉換解碼url
try {
url = java.net.URLDecoder.decode(URL,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//獲取access_token
String aeecss_token = HttpUtil.getAccess_token(appId, appSecret);
//獲取access_ticket
String aeecss_ticket = HttpUtil.getAccess_ticket(aeecss_token);
//3、時間戳和隨機字串
String nonceStr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//隨機字串
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//時間戳
System.out.println("accessToken:"+aeecss_token+"\njsapi_ticket:"+aeecss_ticket+"\n時間戳:"+timestamp+"\n隨機字串:"+nonceStr);
//4、獲取url
//5、將引數排序並拼接字串
String str = "jsapi_ticket="+aeecss_ticket+"&noncestr="+nonceStr+"×tamp="+timestamp+"&url="+url;
//6、將字串進行sha1加密
String signature =SHA1(str);
System.out.println("引數:"+str+"\n簽名:"+signature);
Map<String,String> map=new HashMap();
map.put("appId",appId);
map.put("timestamp",timestamp);
map.put("accessToken",aeecss_token);
map.put("ticket",aeecss_ticket);
map.put("nonceStr",nonceStr);
map.put("signature",signature);
JSONObject jsonObject = JSONObject.fromObject(map);
response.setHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = null;
try {
pw = response.getWriter();
} catch (IOException e1) {
logger.error("**********reponse getWriter exception**********");
e1.printStackTrace();
}
pw.write(jsonObject.toString());
pw.close();
}
這一段程式碼是改寫了,獲取簽名後把所有的資訊都返回json格式了。概要的都有了,這是就可以配置config了,此時應該是:
$.ajax({
url: 'http://10.25.74.68:8088',
type: 'POST',
dataType: 'json',
//url需要編碼傳入而且要是完整的url除#之後的
data: {"url":encodeURIComponent(window.location.href.split("#")[0])}
})
.done(function(res) {
wx.config({
debug: ture, //除錯階段建議開啟
appId: res.appId,//APPID
timestamp: res.timestamp,//上面main方法中拿到的時間戳timestamp
nonceStr: res.nonceStr,//上面main方法中拿到的隨機數nonceStr
signature: res.signature,//上面main方法中拿到的簽名signature
//需要呼叫的方法介面
jsApiList: [ 'onMenuShareTimeline','onMenuShareAppMessage','onMenuShareWeibo','onMenuShareQQ','onMenuShareQZone']
});
}
注意:
- url一定要是完整的url(當前網頁的URL,不包含#及其後面部分)最好是使用window.location.href.split("#")獲取得到,如果傳入固定的好像會報invalid signature錯誤,所以為了安全起見還是直接傳入當前的url
- 這個簽名的有效時間為7200秒,也就是2個小時,因此當超過兩個小時候,再訪問也會報invalid signature錯誤。但是這個我還沒有遇見,並不知道這麼解決,其他說是需要快取access_token和access_ticket
- 另外還有一個錯誤:invalid url domain 這個跟生成簽名時用的url有關係,官網的說法是: invalid url domain當前頁面所在域名與使用的appid沒有繫結,請確認正確填寫繫結的域名,如果使用了埠號,則配置的繫結域名也要加上埠號(一個appid可以繫結三個有效域名) 這個url必須是:“公眾號設定---功能設定----JS介面安全域名”中繫結的三個域名之一
- 如果以上配置都是正確,而且debug也設定為true了,在微信中訪問連線會出現config:ok的介面,就說明配置成功了
- 有時也可以把ajax請求放在setTimeout中進行請求。
自定義標題,內容和圖片
wx.ready(function(){
// alert("我已經進來了");
wx.onMenuShareTimeline({
title: title, // 分享標題
link: window.location.href, // 分享連結,該連結域名或路徑必須與當前頁面對應的公眾號JS安全域名一致
imgUrl: "//upload-images.jianshu.io/upload_images/3429385-09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享圖示
success: function () {
// alert("成功")
// 使用者點選了分享後執行的回撥函式
}
});
wx.onMenuShareAppMessage({
title: title, // 分享標題
desc: descContent, // 分享描述
link: window.location.href, // 分享連結,該連結域名或路徑必須與當前頁面對應的公眾號JS安全域名一致
imgUrl: "//upload-images.jianshu.io/upload_images/3429385-09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享圖示
type: '', // 分享型別,music、video或link,不填預設為link
dataUrl: '', // 如果type是music或video,則要提供資料鏈接,預設為空
success: function () {
// alert("成功")
// 使用者點選了分享後執行的回撥函式
}
});
wx.onMenuShareQQ({
title: title, // 分享標題
desc: descContent, // 分享描述
link: window.location.href, // 分享連結
imgUrl: "//upload-images.jianshu.io/upload_images/3429385-09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享圖示
success: function () {
// alert("成功")
// 使用者確認分享後執行的回撥函式
},
cancel: function () {
// alert("失敗")
// 使用者取消分享後執行的回撥函式
// config資訊驗證失敗會執行error函式,如簽名過期導致驗證失敗,具體錯誤資訊可以開啟config的debug模式檢視,也可以在返回的res引數中檢視,對於SPA可以在這裡更新簽名。
}
});
});
注意:
- 應該把自定義的內容解除安裝wx.ready( // config資訊驗證後會執行ready方法,所有介面呼叫都必須在config介面獲得結果之後,config是一個客戶端的非同步操作,所以如果需要在頁面載入時就呼叫相關介面,則須把相關介面放在ready函式中呼叫來確保正確執行。對於使用者觸發時才呼叫的介面,則可以直接呼叫,不需要放在ready函式中。 )裡面,
- link該連結域名或路徑必須與當前頁面對應的公眾號JS安全域名
- imgUrl:最好是絕對地址的圖片,相對位置好像出不來 比如:'../assets/image/213.png'這樣是出不來的
作者:holy俊輝 連結:https://www.jianshu.com/p/bf743d52c6d3 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。