在开发企业微信扫码Web应用时,你可能遇到只能通过企微API获取用户ID(user_id),而头像、电话等敏感信息无法直接通过扫码API获取的问题。这是由企业微信API的更新策略导致的。从2022年6月20号开始,企微API对于某些字段的返回策略进行了调整,不再默认返回头像、性别、手机等敏感信息。为了获取这些详细信息,我们需要通过OAuth2授权流程来获取用户的授权。
如果通过OAuth2获取用户详细,那么就不能跳转到@wecom-jssdk提供的扫码页面或者嵌入企微API生成的二维码。这需要自己构建登录二维码。
OAuth2授权URL的格式如下,将这个链接文字构建为二维码,用以客户手机扫码。
open.weixin.qq.com/connect/oau…
前端可以使用qrious.js库构造二维码。也可以在后端渲染。
前端代码示例:
async function refreshqrcode(){
try{
res=await fetch('/qregain');
if(res.ok){
const { state } = await res.json();
//state的内容由后端生成,可以包含用来识别客户端的信息和其他内容,微信auth服务器会原样转发
url='https://open.weixin.qq.com/connect/oauth2/authorize?';
qrtext=url+'appid={{data.appid}}&redirect_uri='+encodeURIComponent('{{data.redirect_uri}}')+'&response_type=code&scope=snsapi_privateinfo&state='+state+'&agentid={{data.agentid}}#wechat_redirect';
//双大括号是Jinja模板中表示插入变量的方式,js用`${}`
//scope=snsapi_privateinfo表示获取用户敏感信息
qrElement.parentNode.style.opacity='1.0';
//设置二维码img元素的父元素透明度为1.0,失效时=0.2
var qr = new QRious({
element: qrElement,
size:300,
value: qrtext
});//qriors.js库的用法
}
else{
consoloe.log(res.status);
}
}catch(error){
console.log('err');
}
}
在渲染二维码成功后,紧接着向后端发起一个HTTP请求waitForAuthCode,等待扫码的结果。这一步的作用是:企微手机端扫码后,实际上是手机向open.weixin.qq.com发起认证请求,微信认证服务器生成authcode成功后,它会重定向到redirect_uri指向的服务器,也就是我们自己的应用服务器。应用服务器的对于这一重定向的响应会回到手机端。可以把这个页面响应设计成一个让客户确认的页面。
应用服务器已经在这一步获得了authcode,可以在设定的超时范围内将authcode响应给前端的waitForAuthCode。前端:
async function waitForAuthCode() {
try {
const response = await fetch('/waitauthcode');
if (response.ok) {
const { authCode } = await response.json();
scanover=true;
window.location.href = 'https://example.com/signin?code='+authCode;
//取得authcode后,请求登录验证
}
}catch (error) {
//超时,刷新二维码
console.error('Error waiting for auth code:', error);
refreshqrcode();
}
}
后端以Flask为例:
import queue
@app.route('/waitauthcode')
def _check_code(*args):
"""
微信auth服务器返回的authcode进入以客户uid命名的队列globals()[uid]
"""
uid=request.cookies.get('uid')
q=globals()[uid]
try:
code=q.get(timeout=60) #取得authcode
return jsonify({'authCode': auth_code})
except:
q=None #超时的处理
return jsonify({'error': 'Timeout waiting for auth code'}), 408
前端带code和state参数向应用服务器发起登录请求。服务器收到请求后, 请求获取用户身份。注意:auth code只能使用一次,所以后端必须有控制逻辑。
请求方式: GET(HTTPS)
请求地址: qyapi.weixin.qq.com/cgi-bin/aut…
参数说明:
参数 | 必须 | 说明 |
---|---|---|
access_token | 是 | 调用接口凭证 |
code | 是 | 通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。 |
正确返回:
{
"errcode": 0,
"errmsg": "ok",
"userid":"USERID",
"user_ticket": "USER_TICKET"
}
获取用户敏感信息:
请求方式: POST(HTTPS)
请求地址: qyapi.weixin.qq.com/cgi-bin/aut…
请求包体:
{
"user_ticket": "USER_TICKET"
}
正确的返回结果:
{
"avatar": "https://wework.qpic.cn/wwpic3az/63*****9/0",
"email": "someone@mail.qq.com",
"errcode": 0,
"errmsg": "ok",
"gender": "0",
"mobile": "1********00",
"name": "\u****\u****",
"qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=vcac*****d",
"userid": "001"
}
最后,附上顺序图:编辑