企业微信开发服务端报错汇总


企业微信开发服务端报错汇总

  • 企业微信开发服务端报错汇总
  • 1 access_token问题
  • 1.1 access_token失效
  • 1.2 获取通讯录中某人信息发生错误
  • 1.2.1 有人能获取到用户信息、有人获取不到
  • 1.2.2 所有人都获取不到用户信息
  • 2 企业微信构造链接、code问题
  • 2.1 前端处理构造链接
  • 2.2 手动处理好构造链接



企业微信开发过程中会有一系列的问题。本文与大家一起分享一些企业微信开发过程中的错误和细节问题。


硬件上,务必保持网络畅通!能访问企业微信的接口,才有看下面内容的必要。软件问题,列举如下:

1 access_token问题

企业微信后端开发获取用户信息时必须对接企业微信,开发者初期一定会遇到的问题:
token失效、返回值不正确。获取access_token是调用企业微信API接口的第一步,相当于创建了一个登录凭证,其它的业务API接口,都需要依赖于access_token来鉴权调用者身份。可以用别人写好的企业微信工具,我推荐weixin-java-cp.jar:

com.github.binarywang
weixin-java-cp
${weixin-java-cp}

官方地址是:
https://developer.work.weixin.qq.com/document/path/91039

1.1 access_token失效

这个往往是因为缓存原因造成。企业微信官方明确的给出了,要缓存access_token。官方明确表示:不能频繁调用gettoken接口,否则会遭到频率拦截。这里有必要说一下:
在企业微信开发时,后端程序一定要打印调用access_token的请求日志,包括:请求、返回、解析。只有看日志和单步调试,我们才能知道错误到底在哪里,靠猜是没有意义的,这看起来是题外话。但是务必记住,只要涉及到多个系统对接的时候,一定要打日志,我开发过程中的经验是:几个系统对接的点,往往是出错最频繁的地方。言归正传,给大家看看获取access_token的代码:

/**
	 * 企业号,此方法是企业号获取access_token
	 * @param corpid
	 * @param secret
	 * @return
	 */
	public static TokenResponse token(String corpid, String secret) {
		//获取token如果存在,取出;不存在时重新获取
		String completeUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret="+ secret;
		try {
			String backJsonString = HttpRequest.sendGet(completeUrl, null);
			TokenResponse token = JSON.parseObject(backJsonString, TokenResponse.class);
			if (token.success()) {	
				return token;
			} else {
				logger.debug("accsesstoken获取失败,errcode:"+token.getErrCode()+",errmsg:"+token.getMessage());
				return null;
			}
		} catch (Exception e) {
			logger.debug("--------获取token报错message:" + e.getMessage());
			logger.debug("--------获取token报错cause" + e.getCause());
			e.printStackTrace();
			return null;
		}

	}

是获取access_token并且转换成为实体,实体情况,实体中的属性为:errcode、errmsg、access_token、expires_in,具体是:

https://developer.work.weixin.qq.com/document/path/91039 见下图:

springbootjava实现调用企业微信接口向指定用户发送消息 企业微信接口调用异常_java


这里使用的是redis缓存,在红色方框内:

springbootjava实现调用企业微信接口向指定用户发送消息 企业微信接口调用异常_微信开发_02


务必注意access_token被覆盖、过期的问题,缓存要加过期时间,redisUtils.set(key, token, 60 * 60); 获取access_token之前要判断缓存中是否存在。

这里说一下,一定要搞清楚,corpId、secret,如果这两个没错,要么是过期,要么是access_token缓存出了问题。过期情况的处理,这里就不赘述了。
还有,要注意缓存的key,千万别因为应用过多、造成缓存的key太多,造成混淆。

1.2 获取通讯录中某人信息发生错误

出现获取不到用户的情况,首先要考虑用户问题,别人的用户信息能不能获取到?

1.2.1 有人能获取到用户信息、有人获取不到

处理方式是:

/**
	 * 企业号,获取用户详细信息
	 * @param token
	 * @param userId
	 * @return
	 */
	public static WxCpUser getUserDetailByUserId(String token, String userId) {
		String completeUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=" + token + "&userid=" + userId;
		String backJsonString = HttpRequest.sendGet(completeUrl, null);
		JSONObject jsonObj = JSON.parseObject(backJsonString);
		if(jsonObj.getString("errcode").equals("0")) {
			WxCpUser userInfo = JSONObject.parseObject(backJsonString, WxCpUser.class);
			return userInfo;
		}else {
			logger.debug("获取用户详情失败,返回信息:" + backJsonString);
			return null;
		}
	}

但是出了错,这要分情况:

(1)access_token失效,缓存问题;返回1.1里面排查;

(2)有些人一直都可以获取到用户信息,有些人就是获取不到用户信息,那得去看企业微信通讯录

https://work.weixin.qq.com/wework_admin/frame#contacts

springbootjava实现调用企业微信接口向指定用户发送消息 企业微信接口调用异常_缓存_03


再看看自己的业务系统的数据信息,跟企业微信通讯录里面的成员详情-》账号到底是否一致!

1.2.2 所有人都获取不到用户信息

这种情况,大概率是access_token不对造成的!或者是2 企业微信构造链接、code问题里面说的,获取code方式有问题。

参考代码:

/**
	 * 企业号,获取用户详细信息
	 * @param token
	 * @param userId
	 * @return
	 */
	public static WxCpUser getUserDetailByUserId(String token, String userId) {
		String completeUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=" + token + "&userid=" + userId;
		String backJsonString = HttpRequest.sendGet(completeUrl, null);
		JSONObject jsonObj = JSON.parseObject(backJsonString);
		if(jsonObj.getString("errcode").equals("0")) {
			WxCpUser userInfo = JSONObject.parseObject(backJsonString, WxCpUser.class);
			return userInfo;
		}else {
			logger.debug("获取用户详情失败,返回信息:" + backJsonString);
			return null;
		}
	}

2 企业微信构造链接、code问题

这个问题非常厉害,处理起来,往往是前端难受、后端也难受。官方文档:
https://developer.work.weixin.qq.com/document/path/91022 前后端分离主流做法:要在hear中带token来访问后端接口。前后端分离的系统后端不用硬编码跳转页面;springmvc可以通过response重定向解决跳转和传参问题。前后端分离系统的处理方式、基于session实现mvc系统的方式是不一样的。所以我分为两类,总结问题如下:

2.1 前端处理构造链接

构造链接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE&agentid=AGENTID#wechat_redirect

按照微信官方要求,把参数检查好!这里有人会有疑惑:如果是vue项目前端的路由中带#会影响构造,如何解决?即REDIRECT_URI中带#号怎么办?

给个参考代码:

window.location.href = 
  `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}
&redirect_uri=${encodeURIComponent(window.location.href.split('#')[0])}
&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;

appid: 服务号/企业号的openid
redirect_uri: 当前前端域名,跳回微信会携带code,然后前端拿到code去后台

这种方式,在企业微信中配应用直接是应用的地址:

springbootjava实现调用企业微信接口向指定用户发送消息 企业微信接口调用异常_java_04


这种方式,前端做的比较复杂,思路是这个。如果有问题,好好检查参数!检查参数!

springbootjava实现调用企业微信接口向指定用户发送消息 企业微信接口调用异常_缓存_05


好了之后,记得把code、其他参数之类传到后端处理,后端代码在2.2 手动处理好构造链接中。

2.2 手动处理好构造链接

你也可以在企业微信中按照这么配应用:

springbootjava实现调用企业微信接口向指定用户发送消息 企业微信接口调用异常_缓存_06


如果你是运用了开头说的weixin-java-cp.jar可以参考我写的这篇博客:手把手教你企业微信开发(二) 这是前后端不分离的情况。当然,如果你是在接盘别人的代码,而且没法用weixin-java-cp.jar,那就在后端:

/**
	 * 企业号,通过code获取微信返回值
	 * @param corpCode 应用Id
	 * @param corpKey 应用的Secret
	 * @param code 用户获取的code
	 * @return
	 */
	public static QYAcessToken getQyUserIdAndAppId(String access_token , String code) {

		String completeUrlOpenid = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=" + access_token + "&code="+ code;
		try {
			String backJsonString = HttpRequest.sendGet(completeUrlOpenid, null);
			QYAcessToken responseEntity = JSON.parseObject(backJsonString, QYAcessToken.class);
			
			return responseEntity;
		} catch (Exception e) {
			logger.debug("返回xml有误  Xm:" + e.getMessage());
			return null;
		}
	}

暂时总结问题如上。如果你在企业微信开发过程中遇到了除了上面之外,不好解决的困难,可以联系我。我们一起讨论。