免费男女视频_国产系列 视频二区_羞羞视频免费入口网站_久国久产久精永久网页_国产免费观看av_一区二区三区日韩在线观看

手把手带你使用JS-SDK自定义微信分享效果

前言

剛進入一家新公司,接到的第一個任務就是需要需要自定義微信分享的效果(自定義縮略圖,標題,摘要),一開始真是一臉懵逼,在網上搜索了半天之后大概有了方案。值得注意的是一開始搜索到的解決方案全是調用微信的自帶的JS-SDK,然而騰訊是不會讓廣大吃瓜群眾這么輕而易舉的調用他們的東西的。微信開發團隊已經把調用的權限收回,現在無法直接在頁面直接調用JS-SDK了。話不多說,直接上干貨。

預期效果

原始的分享效果:

 

使用微信JS-SDK的分享效果:

可以看出縮略圖,標題,摘要樣式良好,給用戶的體驗很好。

準備工作

微信官方開發者文檔地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

現在的思路已經很明確了,就是通過調用微信的JS-SDK實現自定義分享效果。但是這個調用過程比較繁瑣,需要提前準備如下東西:

(1)微信服務號一個,并且已經通過了實名認證;

沒有實名認證的話,一些接口沒有調用權限。

(2)一個ICP備案的域名;

這個域名需要設置為微信公眾號后臺的JS接口安全域名,否則微信仍然不允許調用它的接口。

這時大家應該就犯難了,這樣的話豈不是不能在本地測試,只能部署到生產環境才能測試?不用著急,解決方案告訴大家:花生殼的內網穿透服務(收費,20元以內)

花生殼官網:http://hsk.oray.com/price/#personal

選擇個人免費版就可以了,雖然說是免費版,但是其實注冊過程中還是要收幾塊錢的,因為我自己買了域名和流量所以花的錢更多一些,但也在20元以內。不建議大家購買流量,送的流量可以用很久了。

當準備好上面提到的就可以開始敲代碼了。

(3)安裝微信開發者工具,用于本地調試。

下載地址:https://mp.weixin.qq.com/debug/cgi-bin/webdebugger/download?from=mpwiki&os=x64

官方使用教程:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140

具體步驟

(1)查看AppId,AppSecret以及綁定域名

進入微信后臺,找到下面的菜單、獲取AppID和AppSecret和設置JS接口安全域名


請見官網文檔:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

 

 

注意第三步,如果微信服務器不能在我們的服務器上訪問到這個txt文件,域名是無法設置成功的

 

(2)引入JS文件

這里需要注意是http還是https,如果生產環境是https,務必前綴是https,都則會出現mix content這樣的錯誤,導致引入失敗。

<script typet="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

 

(3)通過AppId和AppSecret請求accessToken,然后通過accessToken獲取jsapi_ticket,生成config接口所需參數

因為獲取這兩個參數的次數是有限制的(accessToke 每日2000次,jsapi_ticket 每日100000次),有效期是7200秒,每兩小時請求一次就行啦,把獲取的accessToke和jsapi_ticket保存在后臺,所以accessToken和jsapi_ticket這兩個參數的獲取是通過ajax方式請求后臺,而不是實時去獲取的。

config幾個參數需要詳細說明一下:

  1. timestamp  生成簽名的時間戳  create_nonce_str()
  2. nonceStr  隨機生成的字符串 create_timestamp()
  3. signature  按照微信文檔簽名算法生成的簽名 makeWXTicket()

附上signature算法的官方說明:

https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.15697429783636763#buzhou3

在附錄1中可以找到詳細說明。

此外,官方提供了一個簽名算法的校驗工具:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

下面只附上了主要的方法:

復制代碼
//獲取accessToken private JSONObject getAccessToken(){ //String accessTokenUrl= https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET String requestUrl = accessTokenUrl.replace("APPID",appId).replace("APPSECRET",appSecret);
    log.info("getAccessToken.requestUrl====>"+requestUrl);
    JSONObject result = HttpUtil.doGet(requestUrl); return result ;
} //獲取ticket private JSONObject getJsApiTicket(){ //String apiTicketUrl= https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);
    log.info("getJsApiTicket.requestUrl====>"+requestUrl);
    JSONObject result = HttpUtil.doGet(requestUrl); return result;
} //生成微信權限驗證的參數 public Map<String, String> makeWXTicket(String jsApiTicket, String url) {
    Map<String, String> ret = new HashMap<String, String>();
    String nonceStr = createNonceStr();
    String timestamp = createTimestamp();
    String string1;
    String signature = ""; //注意這里參數名必須全部小寫,且必須有序 string1 = "jsapi_ticket=" + jsApiTicket +
            "&noncestr=" + nonceStr +
            "&timestamp=" + timestamp +
            "&url=" + url;
    log.info("String1=====>"+string1); try {
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(string1.getBytes("UTF-8"));
        signature = byteToHex(crypt.digest());
        log.info("signature=====>"+signature);
    } catch (NoSuchAlgorithmException e)
    {
        log.error("WeChatController.makeWXTicket=====Start");
        log.error(e.getMessage(),e);
        log.error("WeChatController.makeWXTicket=====End");
    } catch (UnsupportedEncodingException e)
    {
        log.error("WeChatController.makeWXTicket=====Start");
        log.error(e.getMessage(),e);
        log.error("WeChatController.makeWXTicket=====End");
    }

    ret.put("url", url);
    ret.put("jsapi_ticket", jsApiTicket);
    ret.put("nonceStr", nonceStr);
    ret.put("timestamp", timestamp);
    ret.put("signature", signature);
    ret.put("appid", appId); 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 createNonceStr() { return UUID.randomUUID().toString();
} //生成時間戳 private static String createTimestamp() { return Long.toString(System.currentTimeMillis() / 1000);
} 
復制代碼

HttpUtil代碼

復制代碼
public class HttpUtil {
    public static Log logger = LogFactory.getLog(HttpUtil.class); //get請求  public static com.alibaba.fastjson.JSONObject doGet(String requestUrl) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String responseContent = null;
        com.alibaba.fastjson.JSONObject result = null; try { //創建Get請求, HttpGet httpGet = new HttpGet(requestUrl); //執行Get請求, response = httpClient.execute(httpGet); //得到響應體 HttpEntity entity = response.getEntity(); //獲取響應內容 responseContent  = EntityUtils.toString(entity,"UTF-8"); //轉換為map result = JSON.parseObject(responseContent);
        } catch (IOException e) {
            logger.error("HttpUtil=====Start");
            logger.error(e.getMessage(),e);
            logger.error("HttpUtil=====End");
        } return result;
    }
}
復制代碼

 

(4)通過config接口注入權限驗證配置

官方示例:

復制代碼
wx.config({  debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。 appId: '', // 必填,公眾號的唯一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名,見附錄1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2 });
復制代碼

自己的代碼:

其中的url不能硬編碼寫在后臺,必須通過動態傳遞。

復制代碼
$(function(){ var url = location.href.split('#').toString();//url不能寫死  $.ajax({
        type : "get",
        url : "/wechatParam",
        dataType : "json",
        async : false,
        data:{url:url},
        success : function(data) {
            wx.config({
                debug: false,////生產環境需要關閉debug模式 appId: data.appid,//appId通過微信服務號后臺查看 timestamp: data.timestamp,//生成簽名的時間戳 nonceStr: data.nonceStr,//生成簽名的隨機字符串 signature: data.signature,//簽名 jsApiList: [//需要調用的JS接口列表 'checkJsApi',//判斷當前客戶端版本是否支持指定JS接口 'onMenuShareTimeline',//分享給好友 'onMenuShareAppMessage'//分享到朋友圈  ]
            });
        },
        error: function(xhr, status, error) { //alert(status); //alert(xhr.responseText);  }
    })
});
復制代碼

 

(5)通過ready接口處理成功驗證

官方示例:

wx.ready(function(){ // config信息驗證后會執行ready方法,所有接口調用都必須在config接口獲得結果之后,config是一個客戶端的異步操作,所以如果需要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。對于用戶觸發時才調用的接口,則可以直接調用,不需要放在ready函數中。  });

自己的代碼:

復制代碼
wx.ready(function () { var link = window.location.href; var protocol = window.location.protocol; var host = window.location.host; //分享朋友圈  wx.onMenuShareTimeline({
            title: '這是一個自定義的標題!',
            link: link,
            imgUrl: protocol+'//'+host+'/resources/images/icon.jpg',// 自定義圖標 trigger: function (res) { // 不要嘗試在trigger中使用ajax異步請求修改本次分享的內容,因為客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回. //alert('click shared');  },
            success: function (res) { //alert('shared success'); //some thing you should do  },
            cancel: function (res) { //alert('shared cancle');  },
            fail: function (res) { //alert(JSON.stringify(res));  }
        }); //分享給好友  wx.onMenuShareAppMessage({
            title: '這是一個自定義的標題!', // 分享標題 desc: '這是一個自定義的描述!', // 分享描述 link: link, // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應的公眾號JS安全域名一致 imgUrl: protocol+'//'+host+'/resources/images/icon.jpg', // 自定義圖標 type: 'link', // 分享類型,music、video或link,不填默認為link dataUrl: '', // 如果type是music或video,則要提供數據鏈接,默認為空 success: function () { // 用戶確認分享后執行的回調函數  },
            cancel: function () { // 用戶取消分享后執行的回調函數  }
        });
        wx.error(function (res) {
            alert(res.errMsg);
        });
    });
復制代碼

到這里所有的代碼都已經分享完畢了。

 

(6)啟動花生殼的內網穿透服務,設置JS接口安全域名

這個基本是傻瓜式的,只要下載他們的客戶端就可以了。

官網教程:http://hsk.oray.com/news/4345.html

添加一個映射就可以了


把之前下載的txt文件放在工程目錄webapp下,然后本地啟動工程,確定通過域名可以訪問本地項目后,設置JS安全域名

現在訪問 域名:端口號(例如:hkh3321313.vicp.io:8080)就可以訪問本地項目啦。

 

(7)使用微信開發者工具測試

微信開發者工具其實就是微信的瀏覽器,其中集成了chrome的調試工具,前面提到wx.config中的debug模式這里就發揮作用了,瀏覽器會自動彈出調用微信接口的返回結果。

成功返回的話結果應該是ok什么的,圖就不上了。提醒大家,上生產環境一定要把debug改為false~

 

后記

 雖然已經給了主要的代碼,大家一定還是不想寫接口,下面附上完整的代碼,如果你覺得解了燃眉之急,就點個頂吧,哈哈哈~

復制代碼
@Controller
public class WeChatController {
    private final Logger log = LoggerFactory.getLogger(this.getClass()); //獲取相關的參數,在application.properties文件中 @Value("${wechat.appId}")
    private String appId;
    @Value("${wechat.appSecret}")
    private String appSecret;
    @Value("${wechat.url.accessToken}")
    private String accessTokenUrl;
    @Value("${wechat.url.apiTicket}")
    private String apiTicketUrl; //微信參數  private String accessToken;
    private String jsApiTicket; //獲取參數的時刻 private Long getTiketTime = 0L;
    private Long getTokenTime = 0L; //參數的有效時間,單位是秒(s) private Long tokenExpireTime = 0L;
    private Long ticketExpireTime = 0L; //獲取微信參數 @RequestMapping("/wechatParam")
    @ResponseBody
    public Map<String, String> getWechatParam(String url){ //當前時間 long now = System.currentTimeMillis();
        log.info("currentTime====>"+now+"ms"); //判斷accessToken是否已經存在或者token是否過期 if(StringUtils.isBlank(accessToken)||(now - getTokenTime > tokenExpireTime*1000)){
            JSONObject tokenInfo = getAccessToken(); if(tokenInfo != null){
                log.info("tokenInfo====>"+tokenInfo.toJSONString());
                accessToken = tokenInfo.getString("access_token");
                tokenExpireTime = tokenInfo.getLongValue("expires_in"); //獲取token的時間 getTokenTime = System.currentTimeMillis();
                log.info("accessToken====>"+accessToken);
                log.info("tokenExpireTime====>"+tokenExpireTime+"s");
                log.info("getTokenTime====>"+getTokenTime+"ms");
            }else{
                log.info("====>tokenInfo is null~");
                log.info("====>failure of getting tokenInfo,please do some check~");
            }

        } //判斷jsApiTicket是否已經存在或者是否過期 if(StringUtils.isBlank(jsApiTicket)||(now - getTiketTime > ticketExpireTime*1000)){
            JSONObject ticketInfo = getJsApiTicket(); if(ticketInfo!=null){
                log.info("ticketInfo====>"+ticketInfo.toJSONString());
                jsApiTicket = ticketInfo.getString("ticket");
                ticketExpireTime = ticketInfo.getLongValue("expires_in");
                getTiketTime = System.currentTimeMillis();
                log.info("jsApiTicket====>"+jsApiTicket);
                log.info("ticketExpireTime====>"+ticketExpireTime+"s");
                log.info("getTiketTime====>"+getTiketTime+"ms");
            }else{
                log.info("====>ticketInfo is null~");
                log.info("====>failure of getting tokenInfo,please do some check~");
            }
        } //生成微信權限驗證的參數 Map<String, String> wechatParam= makeWXTicket(jsApiTicket,url); return wechatParam;
    } //獲取accessToken  private JSONObject getAccessToken(){ //String accessTokenUrl = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET String requestUrl = accessTokenUrl.replace("APPID",appId).replace("APPSECRET",appSecret);
        log.info("getAccessToken.requestUrl====>"+requestUrl);
        JSONObject result = HttpUtil.doGet(requestUrl); return result ;
    } //獲取ticket  private JSONObject getJsApiTicket(){ //String apiTicketUrl = https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);
        log.info("getJsApiTicket.requestUrl====>"+requestUrl);
        JSONObject result = HttpUtil.doGet(requestUrl); return result;
    } //生成微信權限驗證的參數 public Map<String, String> makeWXTicket(String jsApiTicket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonceStr = createNonceStr();
        String timestamp = createTimestamp();
        String string1;
        String signature = ""; //注意這里參數名必須全部小寫,且必須有序 string1 = "jsapi_ticket=" + jsApiTicket +
                "&noncestr=" + nonceStr +
                "&timestamp=" + timestamp +
                "&url=" + url;
        log.info("String1=====>"+string1); try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
            log.info("signature=====>"+signature);
        } catch (NoSuchAlgorithmException e)
        {
            log.error("WeChatController.makeWXTicket=====Start");
            log.error(e.getMessage(),e);
            log.error("WeChatController.makeWXTicket=====End");
        } catch (UnsupportedEncodingException e)
        {
            log.error("WeChatController.makeWXTicket=====Start");
            log.error(e.getMessage(),e);
            log.error("WeChatController.makeWXTicket=====End");
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsApiTicket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appid", appId); 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 createNonceStr() { return UUID.randomUUID().toString();
    } //生成時間戳  private static String createTimestamp() { return Long.toString(System.currentTimeMillis() / 1000);
    }
}
復制代碼

 

主站蜘蛛池模板: 欧美精品一区二区性色 | 中文字幕在线观看精品 | 羞羞答答视频 | 亚洲男人一区 | 看免费一级毛片 | 久久免费精品视频 | 亚洲欧美国产高清 | 国产一区免费观看 | 黄视频网站免费在线观看 | 免费一级在线观看 | 斗罗破苍穹在线观看免费完整观看 | 国产成人精品免高潮在线观看 | 久久久中精品2020中文 | 中文字幕精品在线播放 | 久久精品亚洲一区二区 | 精品一区二区三区中文字幕老牛 | 96视频在线免费观看 | 亚洲九色 | 午夜a狂野欧美一区二区 | 欧美a级一区二区 | 久久小视频 | 日韩视频在线一区二区三区 | 精品国产91久久久久久浪潮蜜月 | 在线a亚洲视频播放在线观看 | qyl在线视频精品免费观看 | 成人午夜免费看 | 日本免费一区二区三区四区 | bt 自拍 另类 综合 欧美 | 日韩午夜片 | 欧美一区二区三区免费不卡 | 高清视频91 | va免费视频 | 99激情| 爱福利视频网 | 黄污在线观看 | 一级毛片在线观看视频 | japan护士性xxxⅹhd | 国产精品自拍av | 日韩黄色在线播放 | 免费国产人成网站 | 国产自91精品一区二区 |