網(wǎng)頁分享到微信自定義標(biāo)題,內(nèi)容和圖片

@(I-前端學(xué)習(xí))

網(wǎng)頁分享到微信中自定義標(biāo)題,內(nèi)容和圖片

隨便說說:

網(wǎng)頁現(xiàn)在也可以通過微信中直接打開,這就是用到時微信的瀏覽器,也可以通過微信瀏覽器中右上角進(jìn)行分享到朋友,朋友圈,QQ等。這是需要微信的JSSDK的機(jī)制所以還是要進(jìn)行一些配置才可以,而這些配置是需要微信公眾號的appId和appsecret的,所以如果沒有這些,也是不能進(jìn)行自定義的。

實(shí)現(xiàn)過程

  1. 首先可以先閱讀以下微信的JS-SDK的說明文檔
    微信JS-SDK說明文檔
  2. 綁定域名,登錄微信公眾平臺,進(jìn)入“公眾號設(shè)置”的功能設(shè)置里面填寫js接口安全域名,這個是要填寫的是你微信瀏覽器要打開的域名地址。不能添加IP地址。
  3. 引入js文件
  4. 在需要調(diào)用js接口的頁面接入JS文件 http://res.wx.qq.com/open/js/jweixin-1.2.0.js
  5. 通過config接口注入權(quán)限并驗(yàn)證配置
  6. 這一步算是整個步驟中最關(guān)鍵的一步,必須正確的配置信息才可以進(jìn)行調(diào)用JS-SDK。
wx.config({
    debug: true, // 開啟調(diào)試模式,調(diào)用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會通過log打出,僅在pc端時才會打印。
    appId: '', // 必填,公眾號的唯一標(biāo)識
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的隨機(jī)串
    signature: '',// 必填,簽名
    jsApiList: [] // 必填,需要使用的JS接口列表
});

下面講如何獲取 timestamp, noceStr(記得這個駝峰結(jié)構(gòu)),singature

獲取配置

先說說最煩人的singature,對于初學(xué)小程序的簡直要了老夫的命,這是啥玩意,還是簽名,所以我會把自己踩的坑給大家說一下。
獲取簽名實(shí)際是需要四步

1. 根據(jù)appId和appsecret獲取access_token;
2. 使用access_token獲取jsapi_ticket;
3. 使用時間戳,隨機(jī)數(shù),jsapi_ticket和要訪問的url按照簽名算法拼接字符串;
4. 對第三步的字符串進(jìn)行SHA1加密,得到簽名;
第一步,獲取access_token

appId和appsecret可以在微信公眾平臺--開發(fā)-基本配置中查找

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 設(shè)定文件
     * @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鏈接和參數(shù)不能變  
        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;  
    }  
    

這里拿到對應(yīng)的jsapi_ticket之后就可以進(jìn)行參數(shù)排序和拼接字符串并加密

第三步: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();  
            // 字節(jié)數(shù)組轉(zhuǎn)換為 十六進(jìn)制 數(shù)  
                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 "";  
    }  

加密算法轉(zhuǎn)載自:http://www.open-open.com/lib/view/open1392185662160.html

第四步: 獲取簽名
public static void main(String[] args) {  
    //1、獲取AccessToken  
    String accessToken = getAccessToken();  
      
    //2、獲取Ticket  
    String jsapi_ticket = getTicket(accessToken);  
      
    //3、時間戳和隨機(jī)字符串  
    String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//隨機(jī)字符串  
    String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//時間戳  
      
    System.out.println("accessToken:"+accessToken+"\njsapi_ticket:"+jsapi_ticket+"\n時間戳:"+timestamp+"\n隨機(jī)字符串:"+noncestr);  
      
    //4、獲取url  
    String url="http://www.luiyang.com/add.html";  
    /*根據(jù)JSSDK上面的規(guī)則進(jìn)行計(jì)算,這里比較簡單,我就手動寫啦 
    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、將參數(shù)排序并拼接字符串  
    String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;  
     
    //6、將字符串進(jìn)行sha1加密  
    String signature =SHA1(str);  
    System.out.println("參數(shù):"+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"); 
        //轉(zhuǎn)換url
        
        String url="";
        //需要轉(zhuǎn)換解碼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、時間戳和隨機(jī)字符串  
        String nonceStr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//隨機(jī)字符串  
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//時間戳  
          
        System.out.println("accessToken:"+aeecss_token+"\njsapi_ticket:"+aeecss_ticket+"\n時間戳:"+timestamp+"\n隨機(jī)字符串:"+nonceStr);  
          
        
        //4、獲取url  
        //5、將參數(shù)排序并拼接字符串  
        String str = "jsapi_ticket="+aeecss_ticket+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;  
         
        //6、將字符串進(jìn)行sha1加密  
        String signature =SHA1(str);  
        System.out.println("參數(shù):"+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了,此時應(yīng)該是:

 $.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, //調(diào)試階段建議開啟
                appId: res.appId,//APPID
                timestamp: res.timestamp,//上面main方法中拿到的時間戳timestamp
                nonceStr: res.nonceStr,//上面main方法中拿到的隨機(jī)數(shù)nonceStr
                signature: res.signature,//上面main方法中拿到的簽名signature
                //需要調(diào)用的方法接口
                jsApiList: [ 'onMenuShareTimeline','onMenuShareAppMessage','onMenuShareWeibo','onMenuShareQQ','onMenuShareQZone']
            });
   }
注意:
  1. url一定要是完整的url(當(dāng)前網(wǎng)頁的URL,不包含#及其后面部分)最好是使用window.location.href.split("#")獲取得到,如果傳入固定的好像會報invalid signature錯誤,所以為了安全起見還是直接傳入當(dāng)前的url
  2. 這個簽名的有效時間為7200秒,也就是2個小時,因此當(dāng)超過兩個小時候,再訪問也會報invalid signature錯誤。但是這個我還沒有遇見,并不知道這么解決,其他說是需要緩存access_token和access_ticket
  3. 另外還有一個錯誤:invalid url domain
    這個跟生成簽名時用的url有關(guān)系,官網(wǎng)的說法是:
    invalid url domain當(dāng)前頁面所在域名與使用的appid沒有綁定,請確認(rèn)正確填寫綁定的域名,如果使用了端口號,則配置的綁定域名也要加上端口號(一個appid可以綁定三個有效域名)
    這個url必須是:“公眾號設(shè)置---功能設(shè)置----JS接口安全域名”中綁定的三個域名之一
  4. 如果以上配置都是正確,而且debug也設(shè)置為true了,在微信中訪問連接會出現(xiàn)config:ok的界面,就說明配置成功了
  5. 有時也可以把a(bǔ)jax請求放在setTimeout中進(jìn)行請求。

自定義標(biāo)題,內(nèi)容和圖片

    wx.ready(function(){
                // alert("我已經(jīng)進(jìn)來了");
                wx.onMenuShareTimeline({
                    title: title, // 分享標(biāo)題
                    link: window.location.href, // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁面對應(yīng)的公眾號JS安全域名一致
                    imgUrl: "http://upload-images.jianshu.io/upload_images/3429385-09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享圖標(biāo)
                    success: function () {
                        // alert("成功")
                        // 用戶點(diǎn)擊了分享后執(zhí)行的回調(diào)函數(shù)
                    }
                });
                wx.onMenuShareAppMessage({
                    title: title, // 分享標(biāo)題
                    desc: descContent, // 分享描述
                    link: window.location.href, // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁面對應(yīng)的公眾號JS安全域名一致
                    imgUrl: "http://upload-images.jianshu.io/upload_images/3429385-09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享圖標(biāo)
                    type: '', // 分享類型,music、video或link,不填默認(rèn)為link
                    dataUrl: '', // 如果type是music或video,則要提供數(shù)據(jù)鏈接,默認(rèn)為空
                    success: function () {
                        // alert("成功")
                        // 用戶點(diǎn)擊了分享后執(zhí)行的回調(diào)函數(shù)
                    }
                });
                wx.onMenuShareQQ({
                    title: title, // 分享標(biāo)題
                    desc: descContent, // 分享描述
                    link: window.location.href, // 分享鏈接
                    imgUrl: "http://upload-images.jianshu.io/upload_images/3429385-09282d70c0390d94.png?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240", // 分享圖標(biāo)
                    success: function () {
                        // alert("成功")
                        // 用戶確認(rèn)分享后執(zhí)行的回調(diào)函數(shù)
                    },
                    cancel: function () {
                        // alert("失敗")
                        // 用戶取消分享后執(zhí)行的回調(diào)函數(shù)
                        // config信息驗(yàn)證失敗會執(zhí)行error函數(shù),如簽名過期導(dǎo)致驗(yàn)證失敗,具體錯誤信息可以打開config的debug模式查看,也可以在返回的res參數(shù)中查看,對于SPA可以在這里更新簽名。
                    }
                });
            });
注意:
  1. 應(yīng)該把自定義的內(nèi)容卸載wx.ready(
    // config信息驗(yàn)證后會執(zhí)行ready方法,所有接口調(diào)用都必須在config接口獲得結(jié)果之后,config是一個客戶端的異步操作,所以如果需要在頁面加載時就調(diào)用相關(guān)接口,則須把相關(guān)接口放在ready函數(shù)中調(diào)用來確保正確執(zhí)行。對于用戶觸發(fā)時才調(diào)用的接口,則可以直接調(diào)用,不需要放在ready函數(shù)中。
    )里面,
  2. link該鏈接域名或路徑必須與當(dāng)前頁面對應(yīng)的公眾號JS安全域名
  3. imgUrl:最好是絕對地址的圖片,相對位置好像出不來 比如:'../assets/image/213.png'這樣是出不來的

驗(yàn)證工具:
微信公眾平臺接口調(diào)試工具
微信 JS 接口簽名校驗(yàn)工具

參考:
解決微信JS-SDK掃一掃功能接入以及出現(xiàn)簽名無效 invalid signature
微信JS-SDK獲取signature簽名以及config配置

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容