企業微信JS-SDK

企業微信JS-SDK是企業微信面向網頁開發者提供的基於企業微信內的網頁開發工具包。
通過使用企業微信JS-SDK,網頁開發者可藉助企業微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時可以直接使用企業微信分享、掃一掃等企業微信特有的能力,爲企業微信用戶提供更優質的網頁體驗。

使用說明

所有的JS接口只能在企業微信應用的可信域名下調用(包括子域名),且可信域名必須有ICP備案且在管理端驗證域名歸屬。
驗證域名歸屬的方法在企業微信的管理後臺“我的應用”裏,進入應用,設置應用可信域名。

步驟一:引入js文件

在需要調用JS接口的頁面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
在vue中使用npm進行安裝

	npm install weixin-js-sdk

使用require引入

	var wx = require("weixin-js-sdk");

步驟二:通過config接口注入權限驗證配置

所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調用(同一個url僅需調用一次,對於變化url的SPA的web app可在每次url變化時進行調用)。

wx.config({
    beta: true,// 必須這麼寫,否則wx.invoke調用形式的jsapi會有問題
    debug: true, // 開啓調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時纔會打印。
    appId: '', // 必填,企業微信的corpID
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的隨機串
    signature: '',// 必填,簽名,見 附錄-JS-SDK使用權限簽名算法
    jsApiList: [] // 必填,需要使用的JS接口列表,凡是要調用的接口都需要傳進來
});

去後端獲取config接口必要的參數

權限的簽名算法需要使用到當前網頁的URL,不包含#及其後面部分
前端獲取當前網頁的url

location.href.split("#")[0] ///向服務端提供授權url參數,並且不需要#後面的部分

後端新建一個jssdk配置參數的bean類JssdkConfig

	public class JssdkConfig {
	    private String appId; //企業微信的corpID
	    private String timestamp; //生成簽名的時間戳
	    private String nonceStr; //生成簽名的隨機串
	    private String signature; //簽名,見 附錄-JS-SDK使用權限簽名算法
	    getter/setter方法
	}

獲取企業微信的corpID,簽名的時間戳,簽名的隨機串:

jssdkConfig.setAppId(WeChatParames.corpId);//必填,企業微信的corpID
String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成簽名的時間戳
String nonceStr = UUID.randomUUID().toString(); // 必填,生成簽名的隨機串
jssdkConfig.setTimestamp(timestamp);
jssdkConfig.setNonceStr(nonceStr);

獲取簽名
生成簽名需要jsapi_ticket,所以必須先了解一下jsapi_ticket,jsapi_ticket是H5應用調用企業微信JS接口的臨時票據。正常情況下,jsapi_ticket的有效期爲7200秒,通過access_token來獲取。由於獲取jsapi_ticket的api調用次數非常有限(一小時內,一個企業最多可獲取400次,且單個應用不能超過100次),頻繁刷新jsapi_ticket會導致api調用受限,影響自身業務,開發者必須在自己的服務全局緩存jsapi_ticket

獲取簽名的步驟如下

  • 獲取企業的jsapi_ticket(jsapi_ticket必須進行緩存,每次獲取都得先去緩存中獲取,緩存中沒有的話再去重新請求)
//獲取企業的jsapi_ticket
String jsapiTicket = this.getJsapiTicket();

//獲取企業的jsapi_ticket具體方法
private String getJsapiTicket() {
    if(this.jsapiTicket != null) {
        return this.jsapiTicket;
    }
    if(緩存中存儲的jsapi_ticket沒有或者已經過期) {
		String accessToken = this.accessTokenService.getWeChatAccessToken().getAccessToken();
    String url = WeChatParames.jsapiTicketUrl.replace("{ACCESS_TOKEN}", accessToken);
    HttpClientResult httpClientResult = null;
    String jsapiTicket = null;
    try {
        httpClientResult = HttpClientUtils.doGet(url);
    } catch (Exception e) {
        e.printStackTrace();
    }
    JSONObject jsonObject = JSONObject.parseObject(httpClientResult.getContent());
    if("0".equals(jsonObject.get("errcode").toString())) {
        jsapiTicket = jsonObject.get("ticket").toString();
        this.jsapiTicket = jsapiTicket;
        System.out.println("jsapiTicket=" + jsapiTicket);
    } else {
        System.out.println("獲取企業的jsapi_ticket" + jsonObject.get("errmsg").toString());
    }
    return jsapiTicket;
} else {
	//直接返回緩存中jsapi_ticket
}
   
}
  • 進行sha1簽名

參與簽名的參數有四個: noncestr(隨機字符串), jsapi_ticket, timestamp(時間戳), url(當前網頁的URL, 不包含#及其後面部分)

將這些參數使用URL鍵值對的格式 (即 key1=value1&key2=value2…)拼接成字符串string1。
有兩個注意點:1. 字段值採用原始值,不要進行URL轉義;2. 必須嚴格按照如下格式拼接,不可變動字段順序。
jsapi_ticket=JSAPITICKET&noncestr=NONCESTR&timestamp=TIMESTAMP&url=URL

//進行sha1簽名
String sign = "jsapi_ticket="+ jsapiTicket +"&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
String signature = "";
try {
    // 指定sha1算法
    MessageDigest digest = MessageDigest.getInstance("SHA-1");
    digest.update(sign.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);
    }
    signature = hexString.toString();

} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
    jsonModel.setSuccess(false);
    jsonModel.setMsg("sha1簽名出錯");
}
jssdkConfig.setSignature(signature);

通過ready接口處理成功驗證

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

通過error接口處理失敗驗證

wx.error(function(res){
    // config信息驗證失敗會執行error函數,如簽名過期導致驗證失敗,具體錯誤信息可以打開config的debug模式查看,也可以在返回的res參數中查看,對於SPA可以在這裏更新簽名。
});

Config信息驗證成功後就可以調用js接口了,

接口調用說明

所有接口通過wx對象(也可使用jWeixin對象)來調用,參數是一個對象,除了每個接口本身需要傳的參數之外,還有以下通用參數:
success:接口調用成功時執行的回調函數。
fail:接口調用失敗時執行的回調函數。
complete:接口調用完成時執行的回調函數,無論成功或失敗都會執行。
cancel:用戶點擊取消時的回調函數,僅部分有用戶取消操作的api纔會用到。
trigger: 監聽Menu中的按鈕點擊時觸發的方法,該方法僅支持Menu中的相關接口。

注意:不要嘗試在trigger中使用ajax異步請求修改本次分享的內容,因爲客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回

以上幾個函數都帶有一個參數,類型爲對象,其中除了每個接口本身返回的數據之外,還有一個通用屬性errMsg,其值格式如下:

調用成功時:”xxx:ok” ,其中xxx爲調用的接口名
用戶取消時:”xxx:cancel”,其中xxx爲調用的接口名
調用失敗時:其值爲具體錯誤信息

基礎接口

判斷當前客戶端版本是否支持指定JS接口

wx.checkJsApi({
    jsApiList: ['chooseImage'], // 需要檢測的JS接口列表,所有JS接口列表見附錄2,
    success: function(res) {
        // 以鍵值對的形式返回,可用的api值true,不可用爲false
        // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
    }
});

預覽文件接口

企業微信api文檔使用下列方法進行調用,

wx.previewFile({
    url: '', // 需要預覽文件的地址(必填,可以使用相對路徑)
    name: '', // 需要預覽文件的文件名(不填的話取url的最後部分)
    size: 1048576 // 需要預覽文件的字節大小(必填)
});

實際上調用不起來,需要使用invoke方式進行調用,具體方法如下

wx.invoke("previewFile", {
              url: fileUrl,
              size: size //大小必須與文件實際大小保持一致,不然出現其他問題(預覽後返回點擊打開文件按鈕出現繼續下載按鈕)
            });

此接口將url對應的文件下載後,在內置瀏覽器中預覽。目前支持圖片、音頻、視頻、文檔等格式的文件。僅企業微信APP手機端可用。注意size的大小必須爲文件的實際大小,不然預覽文件不能正常預覽

常見問題

企業微信jssdk文件預覽url填的是文件服務器存放文件的地址,而在實際項目中有時候是存在oracle數據庫中的

文件預覽的url填寫下載文件流的後端方法。

fileUrl =
          "http://zzx.mynatapp.cc/fjticinno/wxCommon/downloadFile.do?idKey=附件id";

後端設置響應頭

response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(name, "UTF-8") + "\"");
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream-dummy; charset=utf-8");

還要記得設置content-length響應頭,不然顯示文件的下載進度會出現問題。雖然這樣已經使用jssdk的文件預覽正常預覽文件了。但是還有個安全性問題,因爲企業微信是通過url去請求地址並下載文件,如果這個url對應的後端方法不進行登錄攔截或者權限校驗的話。那麼只要知道這個地址和參數的話,就可以隨意下載數據庫中存儲的文件了。如果通過cookie進行登錄攔截的話,從2.4.6版本開始,IOS版企業微信瀏覽器升級爲WkWebView,企業微信原生層面的網絡請求讀取不到WKWebview中設置的cookie,即使域名是相同的。在企業微信內長按保存,或者點擊預覽文件時,原生層面發起的網絡請求將不會完整地帶上所設置的Cookie,會導致圖片保存失敗或預覽失敗。暫時使用在登錄過濾器中判斷請求來源控制權限,

//企業微信調用文件預覽,直接放行
String referer = request.getHeader("referer");
if("前端調用文件預覽的地址".equals(referer)) {
    filterChain.doFilter(request, response);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章