使用微搭搭建网页之获取企微用户信息
单纯的数据提交修改或许不能满足我们所有的需求,有时候我们需要用到提交者的信息,接下来我们将尝试在微搭中获取企微用户的信息。
(一) 获取当前访问者用户信息
首先是要去企微应用中进行相应的配置,如何配置这里先不多介绍了可以参照企微文档。
我们可以在低代码编辑器中在全局中的生命周期中添加代码,我是添加在onAppLaunch中,
大致流程为用户在企微应用中打开我们的网页,配置了企微OAuth2.0网页授权功能的话我在跳转链接中携带一个CODE,我们使用这个code调用企微接口获取UserId,再根据UserId去获取我们想要的数据,我这边是通过自定义连接器调用后台方法直接通过code返回了用户的完整信息。再把自己想要的信息存放到全局变量中,这样我们在任何页面都可以使用到这个信息。
export default { async onAppLaunch(launchOpts) { //console.log('---------> LifeCycle onAppLaunch', launchOpts) var query = window.location.search.substring(1); var name ="code"; var vars = query.split("&"); for (var i = 0; i < vars.length; i++) { var pair = vars[i].split("="); console.log(pair); if (pair[0] == name) { $app.dataset.state.code=pair[1];} } console.log('CODE'+ $app.dataset.state.code); const lianjieqi=await app.cloud.callConnector({ name:'test_d9wq11x', methodName:'method_4c647cb973e6d', params:{'code':$app.dataset.state.code,'appName':'TEST'}, }); console.log(lianjieqi); $app.dataset.state.OpenWXUserId=lianjieqi.data.userid $app.dataset.state.OpenWXUserName=lianjieqi.data.name; console.log('openUserId'+$app.dataset.state.OpenWXUserId); console.log('openUserId'+$app.dataset.state.OpenWXUserName); },
(二)通过企微选人接口获取选中人的信息
在需要用到选人接口的页面中进行初始化
export default { async onPageLoad(query) { var script=document.createElement("script"); script.setAttribute("type","text/javascript"); script.setAttribute("src","https://res.wx.qq.com/open/js/jweixin-1.2.0.js"); document.body.appendChild(script); var script2=document.createElement("script"); script2.setAttribute("type","text/javascript"); script2.setAttribute("src","https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"); document.body.appendChild(script2); const lianjieqi=await app.cloud.callConnector({ name:'test_d9wq11x', methodName:'method_691f08d2b2b2b', params:{}, }) console.log(lianjieqi); var jsapi_ticket = lianjieqi.data; console.log(jsapi_ticket); var weburl=window.location.href; console.log("uri"+weburl); var now = parseInt(new Date().getTime() / 1000); var noncestr = "企业ID"; //var jsapi_ticket2 = "Rxh1eOhX9SIrk4pdYnMc2w=="; //var jsapi_ticket= "HoagFKDcsGMVCIY2vOjf9uiitf-v888cgo07fjmO5B6LX_5eO_I88kmLQiaEtBWTJlvvPYZ1AE8-gfPUJ4G98g"; var timestamp = now; //var url= "<%=url%>"; var url = weburl; var string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url; //var string2 = "jsapi_ticket="+jsapi_ticket2+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url; var signature = new jsSHA(string1, "TEXT"); //var signature2 =new jsSHA(string2,"TEXT"); var t = signature.getHash("SHA-1", "HEX"); //var t2=signature2.getHash("SHA-1","HEX"); var data = { timestamp: timestamp, nonceStr: noncestr, signature: t, //signature2:t2, } console.log(data, string1); wxconfig(data); }, onPageShow() { //console.log('---------> LifeCycle onPageShow') }, onPageReady() { //console.log('---------> LifeCycle onPageReady') }, onPageHide() { //console.log('---------> LifeCycle onPageHide') }, onPageUnload() { //console.log('---------> LifeCycle onPageUnload') }, }
wxconfig代码
function wxconfig(data) { wx.config({ bete: true, debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: "企业ID", // 必填,公众号的唯一标识 timestamp: data.timestamp, // 必填,生成签名的时间戳 nonceStr: data.nonceStr, // 必填,生成签名的随机串 signature: data.signature,// 必填,签名,见附录1 jsApiList: [ 'selectEnterpriseContact', ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function () { //是否支持js接口 // document.querySelector('#checkJsApi').onclick = function () { wx.checkJsApi({ jsApiList: [ 'selectEnterpriseContact' ], success: function (res) { //alert(JSON.stringify(res)); console.log("success") } }); // }; console.log("wxready"); }); wx.error(function (res) { console.log("wxerror", res); }); }
加密代码
function jsSHA(b, e, c) { var a = 0 , d = [0] , f = "" , g = null , f = c || "UTF8"; if ("UTF8" !== f && "UTF16" !== f) throw "encoding must be UTF8 or UTF16"; if ("HEX" === e) { if (0 !== b.length % 2) throw "srcString of HEX type must be in byte increments"; g = v(b); a = g.binLen; d = g.value } else if ("TEXT" === e) g = w(b, f), a = g.binLen, d = g.value; else if ("B64" === e) g = x(b), a = g.binLen, d = g.value; else if ("BYTES" === e) g = y(b), a = g.binLen, d = g.value; else throw "inputFormat must be HEX, TEXT, B64, or BYTES"; this.getHash = function(b, f, c, e) { var g = null, h = d.slice(), l = a, n; 3 === arguments.length ? "number" !== typeof c && (e = c, c = 1) : 2 === arguments.length && (c = 1); if (c !== parseInt(c, 10) || 1 > c) throw "numRounds must a integer >= 1"; switch (f) { case "HEX": g = z; break; case "B64": g = A; break; case "BYTES": g = B; break; default: throw "format must be HEX, B64, or BYTES"; } if ("SHA-1" === b) for (n = 0; n < c; n += 1) h = s(h, l), l = 160; else throw "Chosen SHA variant is not supported"; return g(h, C(e)) } ; this.getHMAC = function(c, b, e, g, q) { var h, l, n, r, p = [], t = []; h = null; switch (g) { case "HEX": g = z; break; case "B64": g = A; break; case "BYTES": g = B; break; default: throw "outputFormat must be HEX, B64, or BYTES"; } if ("SHA-1" === e) l = 64, r = 160; else throw "Chosen SHA variant is not supported"; if ("HEX" === b) h = v(c), n = h.binLen, h = h.value; else if ("TEXT" === b) h = w(c, f), n = h.binLen, h = h.value; else if ("B64" === b) h = x(c), n = h.binLen, h = h.value; else if ("BYTES" === b) h = y(c), n = h.binLen, h = h.value; else throw "inputFormat must be HEX, TEXT, B64, or BYTES"; c = 8 * l; b = l / 4 - 1; if (l < n / 8) { if ("SHA-1" === e) h = s(h, n); else throw "Unexpected error in HMAC implementation"; h[b] &= 4294967040 } else l > n / 8 && (h[b] &= 4294967040); for (l = 0; l <= b; l += 1) p[l] = h[l] ^ 909522486, t[l] = h[l] ^ 1549556828; if ("SHA-1" === e) e = s(t.concat(s(p.concat(d), c + a)), c + r); else throw "Unexpected error in HMAC implementation"; return g(e, C(q)) } }
完成之后我们在此页面下添加一个调用选人接口的方法
export default async function({event, data}) { xuanren(); console.log($page.dataset.state.wxUserName) } function xuanren() { (wx.invoke || window.WeixinJSBridge.invoke)( "selectEnterpriseContact", { "fromDepartmentId": 0,// 必填,表示打开的通讯录从指定的部门开始展示,-1表示自己所在部门开始, 0表示从最上层开始 "mode": "single",// 必填,选择模式,single表示单选,multi表示多选 "type": ["user"],// 必填,选择限制类型,指定department、user中的一个或者多个 }, function (res) { //console.log("xuanren",res) if (res.err_msg == "selectEnterpriseContact:ok") { if (typeof res.result == 'string') { res.result = JSON.parse(res.result) //由于目前各个终端尚未完全兼容,需要开发者额外判断result类型以保证在各个终端的兼容性 } // var selectedDepartmentList = res.result.departmentList;// 已选的部门列表 // for (var i = 0; i < selectedDepartmentList.length; i++) { // var department = selectedDepartmentList[i]; // var departmentId = department.id;// 已选的单个部门ID // var departemntName = department.name;// 已选的单个部门名称 // } var selectedUserList = res.result.userList; // 已选的成员列表 for (var i = 0; i < selectedUserList.length; i++) { var user = selectedUserList[i]; var userId = user.id; // 已选的单个成员ID var userName = user.name;// 已选的单个成员名称 var userAvatar = user.avatar;// 已选的单个成员头像 $page.dataset.state.wxUserName=userName; $page.dataset.state.wxUserId=userId; } } } ); }
然后就可以在页面上添加一个按钮并且绑定刚才新建的方法
在选人按钮的前面添加一个输入组件并把输入值绑定成我们用来存放用户姓名的参数
这样就完成了从企业微信通讯录选人的功能啦。
(三)将企业微信用户信息保存至数据源
由于企微用户信息我们是保存在变量中的,所以微搭自带的表单提交功能是无法满足我们的需求的,所以我们需要新建一个方法代替原来的插入方法,并点击表单,在它的提交事件中绑定我们自己的方法。
至此应用获取企业微信用户信息的功能就完成了,我们可以得知是谁在使用这个应用,也可以通过选人主动获取选中人的企业微信信息
function jsSHA(b, e, c) { var a = 0 , d = [0] , f = "" , g = null , f = c || "UTF8"; if ("UTF8" !== f && "UTF16" !== f) throw "encoding must be UTF8 or UTF16"; if ("HEX" === e) { if (0 !== b.length % 2) throw "srcString of HEX type must be in byte increments"; g = v(b); a = g.binLen; d = g.value } else if ("TEXT" === e) g = w(b, f), a = g.binLen, d = g.value; else if ("B64" === e) g = x(b), a = g.binLen, d = g.value; else if ("BYTES" === e) g = y(b), a = g.binLen, d = g.value; else throw "inputFormat must be HEX, TEXT, B64, or BYTES"; this.getHash = function(b, f, c, e) { var g = null, h = d.slice(), l = a, n; 3 === arguments.length ? "number" !== typeof c && (e = c, c = 1) : 2 === arguments.length && (c = 1); if (c !== parseInt(c, 10) || 1 > c) throw "numRounds must a integer >= 1"; switch (f) { case "HEX": g = z; break; case "B64": g = A; break; case "BYTES": g = B; break; default: throw "format must be HEX, B64, or BYTES"; } if ("SHA-1" === b) for (n = 0; n < c; n += 1) h = s(h, l), l = 160; else throw "Chosen SHA variant is not supported"; return g(h, C(e)) } ; this.getHMAC = function(c, b, e, g, q) { var h, l, n, r, p = [], t = []; h = null; switch (g) { case "HEX": g = z; break; case "B64": g = A; break; case "BYTES": g = B; break; default: throw "outputFormat must be HEX, B64, or BYTES"; } if ("SHA-1" === e) l = 64, r = 160; else throw "Chosen SHA variant is not supported"; if ("HEX" === b) h = v(c), n = h.binLen, h = h.value; else if ("TEXT" === b) h = w(c, f), n = h.binLen, h = h.value; else if ("B64" === b) h = x(c), n = h.binLen, h = h.value; else if ("BYTES" === b) h = y(c), n = h.binLen, h = h.value; else throw "inputFormat must be HEX, TEXT, B64, or BYTES"; c = 8 * l; b = l / 4 - 1; if (l < n / 8) { if ("SHA-1" === e) h = s(h, n); else throw "Unexpected error in HMAC implementation"; h[b] &= 4294967040 } else l > n / 8 && (h[b] &= 4294967040); for (l = 0; l <= b; l += 1) p[l] = h[l] ^ 909522486, t[l] = h[l] ^ 1549556828; if ("SHA-1" === e) e = s(t.concat(s(p.concat(d), c + a)), c + r); else throw "Unexpected error in HMAC implementation"; return g(e, C(q)) } } function w(b, e) { var c = [], a, d = [], f = 0, g; if ("UTF8" === e) for (g = 0; g < b.length; g += 1) for (a = b.charCodeAt(g), d = [], 128 > a ? d.push(a) : 2048 > a ? (d.push(192 | a >>> 6), d.push(128 | a & 63)) : 55296 > a || 57344 <= a ? d.push(224 | a >>> 12, 128 | a >>> 6 & 63, 128 | a & 63) : (g += 1, a = 65536 + ((a & 1023) << 10 | b.charCodeAt(g) & 1023), d.push(240 | a >>> 18, 128 | a >>> 12 & 63, 128 | a >>> 6 & 63, 128 | a & 63)), a = 0; a < d.length; a += 1) (f >>> 2) + 1 > c.length && c.push(0), c[f >>> 2] |= d[a] << 24 - f % 4 * 8, f += 1; else if ("UTF16" === e) for (g = 0; g < b.length; g += 1) (f >>> 2) + 1 > c.length && c.push(0), c[f >>> 2] |= b.charCodeAt(g) << 16 - f % 4 * 8, f += 2; return { value: c, binLen: 8 * f } } function v(b) { var e = [], c = b.length, a, d; if (0 !== c % 2) throw "String of HEX type must be in byte increments"; for (a = 0; a < c; a += 2) { d = parseInt(b.substr(a, 2), 16); if (isNaN(d)) throw "String of HEX type contains invalid characters"; e[a >>> 3] |= d << 24 - a % 8 * 4 } return { value: e, binLen: 4 * c } } function y(b) { var e = [], c, a; for (a = 0; a < b.length; a += 1) c = b.charCodeAt(a), (a >>> 2) + 1 > e.length && e.push(0), e[a >>> 2] |= c << 24 - a % 4 * 8; return { value: e, binLen: 8 * b.length } } function x(b) { var e = [], c = 0, a, d, f, g, m; if (-1 === b.search(/^[a-zA-Z0-9=+\/]+$/)) throw "Invalid character in base-64 string"; a = b.indexOf("="); b = b.replace(/\=/g, ""); if (-1 !== a && a < b.length) throw "Invalid '=' found in base-64 string"; for (d = 0; d < b.length; d += 4) { m = b.substr(d, 4); for (f = g = 0; f < m.length; f += 1) a = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(m[f]), g |= a << 18 - 6 * f; for (f = 0; f < m.length - 1; f += 1) e[c >> 2] |= (g >>> 16 - 8 * f & 255) << 24 - c % 4 * 8, c += 1 } return { value: e, binLen: 8 * c } } function z(b, e) { var c = "", a = 4 * b.length, d, f; for (d = 0; d < a; d += 1) f = b[d >>> 2] >>> 8 * (3 - d % 4), c += "0123456789abcdef".charAt(f >>> 4 & 15) + "0123456789abcdef".charAt(f & 15); return e.outputUpper ? c.toUpperCase() : c } function A(b, e) { var c = "", a = 4 * b.length, d, f, g; for (d = 0; d < a; d += 3) for (g = (b[d >>> 2] >>> 8 * (3 - d % 4) & 255) << 16 | (b[d + 1 >>> 2] >>> 8 * (3 - (d + 1) % 4) & 255) << 8 | b[d + 2 >>> 2] >>> 8 * (3 - (d + 2) % 4) & 255, f = 0; 4 > f; f += 1) c = 8 * d + 6 * f <= 32 * b.length ? c + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g >>> 6 * (3 - f) & 63) : c + e.b64Pad; return c } function B(b) { var e = "", c = 4 * b.length, a, d; for (a = 0; a < c; a += 1) d = b[a >>> 2] >>> 8 * (3 - a % 4) & 255, e += String.fromCharCode(d); return e } function C(b) { var e = { outputUpper: !1, b64Pad: "=" }; try { b.hasOwnProperty("outputUpper") && (e.outputUpper = b.outputUpper), b.hasOwnProperty("b64Pad") && (e.b64Pad = b.b64Pad) } catch (c) {} if ("boolean" !== typeof e.outputUpper) throw "Invalid outputUpper formatting option"; if ("string" !== typeof e.b64Pad) throw "Invalid b64Pad formatting option"; return e } function q(b, e) { return b << e | b >>> 32 - e } function r(b, e) { var c = (b & 65535) + (e & 65535); return ((b >>> 16) + (e >>> 16) + (c >>> 16) & 65535) << 16 | c & 65535 } function t(b, e, c, a, d) { var f = (b & 65535) + (e & 65535) + (c & 65535) + (a & 65535) + (d & 65535); return ((b >>> 16) + (e >>> 16) + (c >>> 16) + (a >>> 16) + (d >>> 16) + (f >>> 16) & 65535) << 16 | f & 65535 } function s(b, e) { var c = [], a, d, f, g, m, p, u, k, s, h = [1732584193, 4023233417, 2562383102, 271733878, 3285377520]; b[e >>> 5] |= 128 << 24 - e % 32; b[(e + 65 >>> 9 << 4) + 15] = e; s = b.length; for (u = 0; u < s; u += 16) { a = h[0]; d = h[1]; f = h[2]; g = h[3]; m = h[4]; for (k = 0; 80 > k; k += 1) c[k] = 16 > k ? b[k + u] : q(c[k - 3] ^ c[k - 8] ^ c[k - 14] ^ c[k - 16], 1), p = 20 > k ? t(q(a, 5), d & f ^ ~d & g, m, 1518500249, c[k]) : 40 > k ? t(q(a, 5), d ^ f ^ g, m, 1859775393, c[k]) : 60 > k ? t(q(a, 5), d & f ^ d & g ^ f & g, m, 2400959708, c[k]) : t(q(a, 5), d ^ f ^ g, m, 3395469782, c[k]), m = g, g = f, f = q(d, 30), d = a, a = p; h[0] = r(a, h[0]); h[1] = r(d, h[1]); h[2] = r(f, h[2]); h[3] = r(g, h[3]); h[4] = r(m, h[4]) } return h } function wxconfig(data) {