1、登录企业微信管理后台(https://work.weixin.qq.com/wework_admin/frame)
2、获取企业ID,我的企业>企业信息>企业ID(ww28b3c6e7a00ee381)
3、获取应用id及secret。应用管理>应用>自建>企业应用(test)>AgentId(1000011)、Secret(t5gPkJsvlEvp0i_bTeJpzAJ0jQ-edqS7fsrdmYPTKLc)
4、申请域名校验。应用管理>应用>自建>企业应用(test)>开发者接口>网页授权及JS-SDK>申请域名校验,填写域名,申请域名校验,根据提示完成校验。
通过后,如下图所示:
5、需要唤起小程序的企业微信内置H5页面
5.1 引入js文件
(支持https)http://res.wx.qq.com/open/js/jweixin-1.2.0.js
https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js
5.2 请求token、ticket并缓存
5.2.1、请求accessToken
“https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=” + corpId + “&corpsecret=” + secret
corpId为企业id,必须是整型,不能为字符串,secret为应用秘钥,分别从2,3步骤中获取,返回结果中的expires_in为token有效时长,单位为s。详见:https://work.weixin.qq.com/api/doc/90000/90135/91039
需要缓存accessToken。
5.2.2、请求应用的jsapi_ticket(非企业的jsapi_ticket)
“https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=” + token + “&type=agent_config”
其中token为5.2.1中需要缓存的token。接口详见:https://work.weixin.qq.com/api/doc/90001/90144/90539#%E8%8E%B7%E5%8F%96%E5%BA%94%E7%94%A8%E7%9A%84jsapi_ticket,返回的ticket需缓存。
5.3、签名权限
将字段jsapi_ticket、noncestr、timestamp、url及对应值拼接成字符串,再进行sha1签名
jsapi_ticket为5.2.2需要缓存的ticket、noncestr为随机字符串、timestamp为时间戳、url为当前网页url。详见:https://work.weixin.qq.com/api/doc/90001/90144/90539
至此,wx.agentConfig所需的参数corpid、agentid、timestamp、nonceStr、signature已准备完毕。其中jsApiList填写固定值:[‘launchMiniprogram’]即可。
注意事项:timestamp、nonceStr必须与签名权限时使用的一致
6、事件触发唤起小程序(以下代码可置于点击事件内)
wx.invoke(‘launchMiniprogram’, {
“appid” : “wxa810a2ace2fd6a2d”, // 需跳转的小程序appid
“path” : “pages/index/index”, // 所需跳转的小程序内页面路径及参数。非必填
}, function(res) {
if(res.err_msg == “launchMiniprogram:ok”) {
// 正常
} else {
// 错误处理
}
}
);
触发后,即可从企业微信的H5页面进入小程序。
7、调试部署
登录pc企业微信,工作台>企业应用>index.html页面,ctrl+shift+alt+d开启调试模式,进入页面后,空白处右键showDevTools即可打开浏览器进行调试。当console出现“agentConfig成功回调”表明已经没有问题。进入移动端的应用,即可唤醒小程序。
pc端企业微信,仅仅是调试作用,是无法唤醒小程序的。
Index.html代码
<script>
$(function() {
let corpId = "ww28b3c6e7a00ee381"; //企业ID
let agentId = 1000011; //应用ID, agentId, 必须是整型
let appSecret = "t5gPkJsvlEvp0i_bTeJpzAJ0jQ-edqS7fsrdmYPTKLc"; // 应用secret
let token = "FZdCHMh-y5GV7G3ynW7LNK_LuZiIa1J6cLtXoPiZoFA4xTesw2BY53lrdXPCaavxOxCmFeYSed0rmKYmtX9UGLGTWAW8qSXzlfJZPVpljY7T43PLSjDCbDhiQGmk_BI4TAXL1h97Yk_2NzyltlW36aBM4dnFOailK2ChMYXbDK9tl8NA9QZIJyiUxxK1rzOUyEGtPM3qa_kTOVncNrSv1w";
//getAccessToken(corpId, appSecret); //有效期2小时
let ticket = "f16a44b24ceb5639f96ea7eeb8aff87b";
//getTicket(token); //有效期2小时
let timeStamp = 1605756762083;
let obj = {
jsapi_ticket: ticket, //应用ticket
noncestr: '10014', //随机字符串, wx.agentConfig内的nonceStr值要与此值一致
timestamp: timeStamp, //时间戳, wx.agentConfig内的timestamp值要与此值一致
url: 'https://twcao.xyz:8090/index.html' //当前网页的url
}
let signature = getSignature(obj); //签名权限
console.log(signature);
wx.agentConfig({
corpid: corpId, // 必填,企业微信的corpid,必须与当前登录的企业一致
agentid: 1000011, // 必填,企业微信的应用id
timestamp: timeStamp, // 必填,生成签名的时间戳
nonceStr: obj.noncestr, // 必填,生成签名的随机串
signature: signature,// 必填,签名,见附录-JS-SDK使用权限签名算法
jsApiList: ['launchMiniprogram'], //必填
success: function(res) {
console.log(res + "agentConfig成功回调");
},
fail: function(res) {
console.log("agentConfig失败回调")
if(res.errMsg.indexOf('function not exist') > -1){
alert('版本过低请升级')
}
}
});
$(".site-video").click(function() {
// 调用前, 需确保wx.agentConfig配置成功
wx.invoke('launchMiniprogram', {
"appid" : "wxa810a2ace2fd6a2d", // 需跳转的小程序appid
"path" : "pages/index/index", // 所需跳转的小程序内页面路径及参数。非必填
}, function(res) {
if(res.err_msg == "launchMiniprogram:ok") {
// 正常
} else {
// 错误处理
}
}
);
});
});
function getAccessToken(appId, appSecret) {
$.ajax({
url: "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + appId + "&corpsecret=" + appSecret,
type: "GET",
async: false,
success: function(resp) {
console.log(resp);
return resp.responseText.access_token;
},
error: function(a, b, c) {
return "";
}
})
}
function getTicket(token) {
$.ajax({
url: "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=" + token + "&type=agent_config",
type: "GET",
async: false,
success: function(resp) {
return resp.responseText.ticket;
},
error: function(a, b, c) {
return "";
}
})
}
function getSignature(obj) {
let sign = "jsapi_ticket=" + obj.jsapi_ticket + "&noncestr=" + obj.noncestr + "×tamp=" + obj.timestamp + "&url=" + obj.url;
return sha1(sign);
}
function encodeUTF8(s) {
var i, r = [], c, x;
for (i = 0; i < s.length; i++)
if ((c = s.charCodeAt(i)) < 0x80) r.push(c);
else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F));
else {
if ((x = c ^ 0xD800) >> 10 == 0) //对四字节UTF-16转换为Unicode
c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000,
r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F));
else r.push(0xE0 + (c >> 12 & 0xF));
r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
};
return r;
}
// 字符串加密成 hex 字符串
function sha1(s) {
var data = new Uint8Array(encodeUTF8(s))
var i, j, t;
var l = ((data.length + 8) >>> 6 << 4) + 16, s = new Uint8Array(l << 2);
s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer);
for (t = new DataView(s.buffer), i = 0; i < l; i++)s[i] = t.getUint32(i << 2);
s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8);
s[l - 1] = data.length << 3;
var w = [], f = [
function () { return m[1] & m[2] | ~m[1] & m[3]; },
function () { return m[1] ^ m[2] ^ m[3]; },
function () { return m[1] & m[2] | m[1] & m[3] | m[2] & m[3]; },
function () { return m[1] ^ m[2] ^ m[3]; }
], rol = function (n, c) { return n << c | n >>> (32 - c); },
k = [1518500249, 1859775393, -1894007588, -899497514],
m = [1732584193, -271733879, null, null, -1009589776];
m[2] = ~m[0], m[3] = ~m[1];
for (i = 0; i < s.length; i += 16) {
var o = m.slice(0);
for (j = 0; j < 80; j++)
w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1),
t = rol(m[0], 5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0,
m[1] = rol(m[1], 30), m.pop(), m.unshift(t);
for (j = 0; j < 5; j++)m[j] = m[j] + o[j] | 0;
};
t = new DataView(new Uint32Array(m).buffer);
for (var i = 0; i < 5; i++)m[i] = t.getUint32(i << 2);
var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function (e) {
return (e < 16 ? "0" : "") + e.toString(16);
}).join("");
return hex;
}
</script>