企業微信開發,嵌入自定義專案,及JS-SDK的引用
阿新 • • 發佈:2019-01-04
目標:
基於H5開發專案,嵌入到企業微信中,並接入js-sdk 並運用企業微信介面。
開發環境:
騰訊企業微信最新版本。後端環境不做要求,能跑通即可(這裡我選用的是eclipse的maven專案,之前也出了一篇搭建後臺專案的部落格,可以瞭解一下)
需要工具:
企業微信註冊。花生殼開通內網穿透(花費6元)
一、建立專案 能執行即可
隨便一個能執行的專案即可。
二、花生殼配置
三、申請企業微信
(1)安卓手機上下載 企業微信APP
(2)直接使用微信登入即可,需要新建一個公司,直接根據提示申請一個測試的即可
(4)使用企業微信掃一掃登入即可
(5)建立一個應用
設定網頁授權JS-SDK
設定成功後
四、前端整合js-sdk
直接上頁面程式碼,頁面上的註釋注意看看
<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta charset="utf-8" /> <meta content="telephone=no" name="format-detection" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <title>企業微信</title> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <!-- 企業微信的JS-SDK --> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <style type="text/css"> .daiban { width: 60%; height: 40px; text-align: center; line-height: 2.5; border: 0px solid #ddd; background-color: yellow; margin: 20px 20% 0px 20%; border-radius: 5px; } .genzong { width: 60%; height: 40px; text-align: center; line-height: 2.5; border: 0px solid #ddd; background-color: pink; margin: 20px 20% 0px 20%; border-radius: 5px; } </style> </head> <body> <div id="a1" class="daiban">待辦</div> <div id="a2" class="genzong">交換跟蹤</div> <script type="text/javascript"> //初始化方法 function init() { getToken(); bindClick(); } //從後臺獲取wx.config中所需要的引數 function getToken() { $.ajax({ url : "/zboxService/zwwx/getSignature", type : "get", dataType : "json", success : function(data) { console.log(data) var json = data; wx.config({ beta : true,// 必須這麼寫,否則wx.invoke呼叫形式的jsapi會有問題 debug : false, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。 appId : 'ww01c11527d43106b5', // 必填,企業微信的corpID timestamp : json.timestamp, // 必填,生成簽名的時間戳 nonceStr : json.noncestr, // 必填,生成簽名的隨機串 signature : json.signature,// 必填,簽名,見附錄1 jsApiList : [ 'checkJsApi', 'chooseImage', 'openEnterpriseChat' ] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2 }); wx.ready(function() { wx.checkJsApi({ jsApiList : [ 'chooseImage' ], // 需要檢測的JS介面列表,所有JS介面列表見附錄2, success : function(ress) { alert(2) // 以鍵值對的形式返回,可用的api值true,不可用為false // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} } }); }); } }) } //繫結兩個按鈕的點選事件 function bindClick() { //這個介面是開啟userIds對話方塊,執行則微信端直接跳到聊天框 $("#a1").click(function() { wx.openEnterpriseChat({ // 注意:userIds和externalUserIds至少選填一個,且userIds+openIds總數不能超過2000。 userIds : 'DingSaiSai02;ZhuHao', //參與會話的企業成員列表,格式為userid1;userid2;...,用分號隔開。 externalUserIds : '', // 參與會話的外部聯絡人列表,格式為userId1;userId2;…,用分號隔開。 groupName : '討論組', // 必填,會話名稱。單聊時該引數傳入空字串""即可。 success : function(res) { // 回撥 }, fail : function(res) { if (res.errMsg.indexOf('function not exist') > -1) { alert('版本過低請升級') } } }); }); //這是選擇本地圖片的介面 $("#a2").click(function() { wx.chooseImage({ count : 1, // 預設9 sizeType : [ 'original', 'compressed' ], // 可以指定是原圖還是壓縮圖,預設二者都有 sourceType : [ 'album', 'camera' ], // 可以指定來源是相簿還是相機,預設二者都有 defaultCameraMode : "batch", //表示進入拍照介面的預設模式,目前有normal與batch兩種選擇,normal表示普通單拍模式,batch表示連拍模式,不傳該引數則為normal模式。(注:使用者進入拍照介面仍然可自由切換兩種模式) success : function(res) { var localIds = res.localIds; // 返回選定照片的本地ID列表, // andriod中localId可以作為img標籤的src屬性顯示圖片; // 而在IOS中需通過上面的介面getLocalImgData獲取圖片base64資料,從而用於img標籤的顯示 } }); }); } init(); </script> </body> </html>
後臺程式碼,本人直接封裝成了工具類
constens檔案,裡面寫了幾個對接企業微信的遠端介面URL及引數格式
package com.hao.qywx.web; public class ZwwxPostTencentConstants { /** * 獲取企業微信token地址及對應引數 */ public static final String QYWX_GET_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"; public static final String QYWX_GET_TOKEN_URL_PARAM_CORPID = "corpid"; public static final String QYWX_GET_TOKEN_URL_PARAM_CORPSECRET = "corpsecret"; /** * 獲取企業微信token返回成功對應errcode值 */ public static final String QYWX_GET_TOKEN_RETURN_SUCCESS_CODE = "0"; public static final String QYWX_GET_TOKEN_RETURN_ERRCODE = "errcode"; public static final String QYWX_GET_TOKEN_RETURN_ERRMSG = "errmsg"; public static final String QYWX_GET_TOKEN_RETURN_TOKEN = "access_token"; /** * 獲取企業微信引入JS-SDK的ticket地址及對應引數 */ public static final String QYWX_GET_JSAPITICKET_URL = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; public static final String QYWX_GET_JSAPITICKET_URL_PARAM_TOKEN = "access_token"; public static final String QYWX_GET_JSAPITICKET_URL_PARAM_TICKET = "jsapi_ticket"; public static final String QYWX_GET_JSAPITICKET_URL_PARAM_NONCESTR = "noncestr"; public static final String QYWX_GET_JSAPITICKET_URL_PARAM_TIMESTAMP = "timestamp"; public static final String QYWX_GET_JSAPITICKET_URL_PARAM_URL = "url"; public static final String QYWX_GET_JSAPITICKET_RETURN_SIGNATURE = "signature"; /** * 獲取使用者ticket引數 */ public static final String QYWX_GET_JSAPITICKET_RETURN_SUCCESS_CODE = "0"; public static final String QYWX_GET_JSAPITICKET_RETURN_ERRCODE = "errcode"; public static final String QYWX_GET_JSAPITICKET_RETURN_ERRMSG = "errmsg"; public static final String QYWX_GET_JSAPITICKET_RETURN_TICKET = "ticket"; /** * 通過code獲取使用者資訊url及其對應引數 */ public static final String QYWX_GET_USERINFO_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo"; public static final String QYWX_GET_USERINFO_URL_PARAM_TOKEN = "access_token"; public static final String QYWX_GET_USERINFO_URL_PARAM_CODE = "code"; /** * 通過code獲取使用者資訊返回引數 */ public static final String QYWX_GET_USERINFO_RETURN_SUCCESS_CODE = "0"; public static final String QYWX_GET_USERINFO_RETURN_ERRCODE = "errcode"; public static final String QYWX_GET_USERINFO_RETURN_ERRMSG = "errmsg"; public static final String QYWX_GET_USERINFO_RETURN_USERID = "UserId"; /** * 企業微信的CorpID,在企業微信管理端檢視 */ public static final String QYWX_CORPID = ""; /** * 授權方的網頁應用ID,在具體的網頁應用中檢視 */ public static final String QYWX_AGENTID = ""; /** * 應用的憑證金鑰,在具體的網頁應用中檢視 */ public static final String QYWX_CORPSECRET = ""; /** * 引數連線符 */ public static final String QYWX_AND = "&"; public static final String QYWX_EQUAL = "="; public static final String QYWX_QUERY = "?"; }
工具類,
package com.hao.qywx.web;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.alibaba.fastjson.JSONObject;
public class ZwwxPostTencentUtil {
/**
* @name 中文名稱
* @description 根據頁面URL和頁面ticket生成接入JS-SDK接入碼
* @time 建立時間:2018年7月23日19:58:05
* @param url:接入js-sdk的頁面地址
* ticket:通過token生成的接入js-sdk的ticket
* @return 請求返回接入js-sdk所需json物件
* @author 朱浩
* @history 修訂歷史(歷次修訂內容、修訂人、修訂時間等)
*/
public static JSONObject getSignature(String url, String ticket) {
JSONObject rul = new JSONObject();
String noncestr = getRandomString(16);
String timestamp = (int)(System.currentTimeMillis()/1000)+"";
String sign = "";
sign += ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_TICKET
+ ZwwxPostTencentConstants.QYWX_EQUAL
+ ticket
+ ZwwxPostTencentConstants.QYWX_AND
+ ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_NONCESTR
+ ZwwxPostTencentConstants.QYWX_EQUAL
+ noncestr
+ ZwwxPostTencentConstants.QYWX_AND
+ ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_TIMESTAMP
+ ZwwxPostTencentConstants.QYWX_EQUAL + timestamp
+ ZwwxPostTencentConstants.QYWX_AND
+ ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_URL
+ ZwwxPostTencentConstants.QYWX_EQUAL + 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();
}
rul.put(ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_RETURN_SIGNATURE,
signature);
rul.put(ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_NONCESTR,
noncestr);
rul.put(ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_TIMESTAMP,
timestamp);
return rul;
}
/**
* @name 中文名稱
* @description 根據掃碼登入返回的code值和應用token值獲取掃碼登入人使用者id(注:id為企業微信掃碼人id)
* @time 建立時間:2018年7月23日14:07:28
* @param code
* :前臺掃碼登入後微信js外掛會自動跳轉連結,且附帶該code。 accessToken: 應用呼叫介面憑證,
* 該類下getTencentToken()方法可直接獲取。
* @return 請求返回userid
* @author 朱浩
* @history 修訂歷史(歷次修訂內容、修訂人、修訂時間等)
*/
public static String getTencentUserInfo(String code, String accessToken) {
String url = "";
url += ZwwxPostTencentConstants.QYWX_GET_USERINFO_URL
+ ZwwxPostTencentConstants.QYWX_QUERY;
url += ZwwxPostTencentConstants.QYWX_GET_USERINFO_URL_PARAM_TOKEN
+ ZwwxPostTencentConstants.QYWX_EQUAL + accessToken;
url += ZwwxPostTencentConstants.QYWX_AND;
url += ZwwxPostTencentConstants.QYWX_GET_USERINFO_URL_PARAM_CODE
+ ZwwxPostTencentConstants.QYWX_EQUAL + code;
JSONObject userInfoJson = sendPostRequest(url);
String errcode = userInfoJson
.getString(ZwwxPostTencentConstants.QYWX_GET_USERINFO_RETURN_ERRCODE);
if (ZwwxPostTencentConstants.QYWX_GET_USERINFO_RETURN_SUCCESS_CODE
.equals(errcode)) {
return userInfoJson
.getString(ZwwxPostTencentConstants.QYWX_GET_USERINFO_RETURN_USERID);
} else {
}
return null;
}
/**
* @name 中文名稱
* @description 獲取企業微信Token(應用呼叫介面憑證) 該值具有以下特性: 1、通用性:該企業微信應用下通用, 2、
* 有效性:該值有效時長為7200秒, 3、微信端不可長期無限制請求,推薦使用快取儲存改值
* @time 建立時間:2018年7月23日14:07:28
* @param 請求URL地址
* ,引數需自行拼接
* @return 請求返回token值
* @author 朱浩
* @history 修訂歷史(歷次修訂內容、修訂人、修訂時間等)
*/
public static String getTencentToken() {
String url = "";
url += ZwwxPostTencentConstants.QYWX_GET_TOKEN_URL
+ ZwwxPostTencentConstants.QYWX_QUERY;
url += ZwwxPostTencentConstants.QYWX_GET_TOKEN_URL_PARAM_CORPID
+ ZwwxPostTencentConstants.QYWX_EQUAL
+ ZwwxPostTencentConstants.QYWX_CORPID;
url += ZwwxPostTencentConstants.QYWX_AND
+ ZwwxPostTencentConstants.QYWX_GET_TOKEN_URL_PARAM_CORPSECRET
+ ZwwxPostTencentConstants.QYWX_EQUAL;
url += ZwwxPostTencentConstants.QYWX_CORPSECRET;
JSONObject tokenJson = sendPostRequest(url);
String errcode = tokenJson
.getString(ZwwxPostTencentConstants.QYWX_GET_TOKEN_RETURN_ERRCODE);
if (ZwwxPostTencentConstants.QYWX_GET_TOKEN_RETURN_SUCCESS_CODE
.equals(errcode)) {
return tokenJson
.getString(ZwwxPostTencentConstants.QYWX_GET_TOKEN_RETURN_TOKEN);
} else {
}
return null;
}
/**
* @name 中文名稱
* @description 根據token獲取接入js-sdk的ticket
* @time 建立時間:2018年7月23日19:33:47
* @param accessToken
* : 應用呼叫介面憑證, 該類下getTencentToken()方法可直接獲取。
* @return 請求返回ticket值。
* @author 朱浩
* @history 修訂歷史(歷次修訂內容、修訂人、修訂時間等)
*/
public static String getTencentJSSDKTicket(String token) {
String url = "";
url += ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL
+ ZwwxPostTencentConstants.QYWX_QUERY;
url += ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_URL_PARAM_TOKEN
+ ZwwxPostTencentConstants.QYWX_EQUAL + token;
JSONObject ticketJson = sendPostRequest(url);
String errcode = ticketJson
.getString(ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_RETURN_ERRCODE);
if (ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_RETURN_SUCCESS_CODE
.equals(errcode)) {
return ticketJson
.getString(ZwwxPostTencentConstants.QYWX_GET_JSAPITICKET_RETURN_TICKET);
} else {
}
return null;
}
/**
* @name 中文名稱
* @description 相關說明
* @time 建立時間:2018年7月23日11:48:33
* @param 請求URL地址
* ,引數需自行拼接
* @return 請求返回json物件
* @author 朱浩
* @history 修訂歷史(歷次修訂內容、修訂人、修訂時間等)
*/
private static JSONObject sendPostRequest(String url) {
StringBuffer stringBuffer = new StringBuffer("");
try {
URL postUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) postUrl
.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestProperty("Content-Type", "application/json");
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
stringBuffer.append(line);
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return JSONObject.parseObject(stringBuffer.toString());
}
/**
* @name 中文名稱
* @description 獲取指定位數的隨機字串(包含小寫字母、大寫字母、數字,0<length)
* @time 建立時間:2018年7月23日14:17:21
* @param 獲取字串長度
* @return 對應長度的隨機字串
* @author 朱浩
* @history 修訂歷史(歷次修訂內容、修訂人、修訂時間等)
*/
private static String getRandomString(int length) {
// 隨機字串的隨機字元庫
String KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuffer sb = new StringBuffer();
int len = KeyString.length();
for (int i = 0; i < length; i++) {
sb.append(KeyString.charAt((int) Math.round(Math.random()
* (len - 1))));
}
return sb.toString();
}
}
實現介面
JSONObject rul = new JSONObject();
String token = ZwwxPostTencentUtil.getTencentToken();
String ticket = ZwwxPostTencentUtil.getTencentJSSDKTicket(token);
rul = ZwwxPostTencentUtil.getSignature(url, ticket);
五、踩坑記錄
(1)必須有可以外網訪問的專案,推薦花生殼內網穿透直接搞定。
(2)在企業微信後臺配置js-sdk可信域名的時候需要根據提示下載一個檔案放在專案根目錄下
(3)網頁端是無法除錯JS-SDK介面的,包括微信開發工具其實也不是很好用,最好是用手機測試
(4)我在用手機測試的時候一直沒有反應,但是在微信開發工具中測試又是有反應的(這裡的反應指的是alert),最終在大神的指導下,寫在APP從新安裝(好吧,這個確實是個坑,當你在微信開發工具中測試有反應,但手機上沒反應的話可以試試)
(5)注意一下我獲取Signature這段程式碼,其中的timestamp 單位是秒 秒 秒 !
(6)還有各種坑,可能想不起來了,歡迎各位留言,有可能我就遇到過!