企业微信接入自有应用实现免登录

coding

公司要将移动端审批流程接入企业微信,员工通过企业微信的自建审批应用就可以在微信端审批单据,要审批单据就先得让企业微信跟用户绑定起来,实现无感自动登录系统内。由于企业的员工已经被手动的从微信拉入企业微信内,这样就不可以通过企业微信的创建人员接口将人员推到微信内。只能在用户第一次登录审批系统的时候去微信获取用户ID(userId)并与审批系统的人员关联起来。绑定好后就可以实现自动登录。

企业微信API:https://work.weixin.qq.com/api/doc#90001/90143/91201

员工点击应用后自动登录步骤如下:

1.拦截用户是否登录

在过滤器或者拦截器内检查用户是否登录,如果没有登录跳转到微信获取用户的身份信息

企业微信API地址:https://work.weixin.qq.com/api/doc#90001/90143/91120

获取企业微信授权信息URL:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&agentid=AGENTID&state=STATE#wechat_redirec

页面跳转到企业微信后企业微信处理完成后,页面将重新跳转至 redirect_uri参数指定的回调地址并带上参数code=CODE&state=STATE,企业可根据code参数获得员工的userid。code长度最大为512字节。

public static final String OAUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect";

Integer serverPort = request.getServerPort();

String port = (null != serverPort && serverPort == 80) ? "" : ":" + serverPort.toString();

String url = "http://" + request.getServerName() // 服务器地址

+ port // 端口号

+ request.getContextPath(); // 项目名称

url = url + "/weixin/auth/weixinLogin/oauthLogin.html";

try{

url = URLEncoder.encode(url, "utf-8");

}catch (UnsupportedEncodingException e){

e.printStackTrace();

}

String weixinUrl = String.format(OAUTH_CODE_URL, "企业ID", url, "state"");

response.sendRedirect(weixinUrl);

2.获取用户信息并登录

微信回调接收到CODE值并用CODE去交换真实的用户信息,如果用户与系统绑定就表示登录成功,登录成功后将用户信息放入SESSION中。这样就可以实现自动登录审批系统了。

/**

* 微信回调接口

* @return

*/

public String oauthLogin(){

try{

Map<String, Object> returnMap = WeixinUtil.getUserInfo(code, Constants.APPROVAL);

if (null != returnMap){

//得到微信用户ID

String userid = MapUtils.getString(returnMap, "UserId");

if (!StringUtil.isRealEmpty(userid)){

//用户与微信ID绑定实体

UserWx userWx = userWxManager.findByWXID(userid);

if (userWx != null){

if (StringUtil.isRealEmpty(userWx.getAvatar())){

WxUser wxUser = WeixinUtil.getWxUser(userid, Constants.APPROVAL);

if (null != wxUser && !StringUtil.isRealEmpty(wxUser.getAvatar())){

// +64取小头像 ;+0取大头像

userWx.setAvatar(wxUser.getAvatar());

userWxManager.save(userWx);

}

}

//登录成功,将用户信息放入SESSION等后续操作

.......

return null;

}else{

//显示未绑定的逻辑

return customMethod("unbind");

}

}else{

return customMethod("error");

}

}else{

return customMethod("error");

}

}catch (Exception e){

return customMethod("error");

}

}

WeixinUtil的代码如下:

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.ConnectException;

import java.net.URL;

import java.sql.Timestamp;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSocketFactory;

import javax.net.ssl.TrustManager;

import org.apache.commons.collections.MapUtils;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;

import cn.boxbank.WxUser;

public class WeixinUtil

{

private static Log log = LogFactory.getLog(WeixinUtil.class);

/**

* 发起https请求并获取结果

*

* @param requestUrl 请求地址

* @param requestMethod 请求方式(GET、POST)

* @param outputStr 提交的数据

* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)

*/

public static Map<String, Object> HttpRequest(String requestUrl, String requestMethod, String outputStr)

{

// log.error("发起https请求并获取结果 :"+requestUrl+","+requestMethod+","+outputStr);

Map<String, Object> map = new HashMap<String, Object>();

StringBuffer buffer = new StringBuffer();

try

{

// 创建SSLContext对象,并使用我们指定的信任管理器初始化

TrustManager[] tm = { new EwX509TrustManager() };

SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");

sslContext.init(null, tm, new java.security.SecureRandom());

// 从上述SSLContext对象中得到SSLSocketFactory对象

SSLSocketFactory ssf = sslContext.getSocketFactory();

URL url = new URL(requestUrl);

HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();

httpUrlConn.setSSLSocketFactory(ssf);

httpUrlConn.setDoOutput(true);

httpUrlConn.setDoInput(true);

httpUrlConn.setUseCaches(false);

httpUrlConn.setConnectTimeout(60 * 1000);

httpUrlConn.setReadTimeout(60 * 1000);

// 设置请求方式(GET/POST)

httpUrlConn.setRequestMethod(requestMethod);

httpUrlConn.connect();

// if ("GET".equalsIgnoreCase(requestMethod))

// 当有数据需要提交时

if (null != outputStr)

{

OutputStream outputStream = httpUrlConn.getOutputStream();

// 注意编码格式,防止中文乱码

outputStream.write(outputStr.getBytes("UTF-8"));

outputStream.close();

}

// 将返回的输入流转换成字符串

InputStream inputStream = httpUrlConn.getInputStream();

InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");

BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

String str = null;

while ((str = bufferedReader.readLine()) != null)

{

buffer.append(str);

}

bufferedReader.close();

inputStreamReader.close();

// 释放资源

inputStream.close();

inputStream = null;

httpUrlConn.disconnect();

// 返回map

// map = JsonUtil.json2Map(buffer.toString(), Map.class, String.class, Object.class);

map = (Map<String, Object>) JSON.parseObject(buffer.toString(), Map.class);

}

catch (ConnectException ce)

{

System.out.println("Connection Timed Out......");

}

catch (Exception e)

{

String result = String.format("Https Request Error:%s", e);

System.out.println(result);

}

return map;

}

/**

* 根据code调微信接口获取USERID

*

* @param code

* @return

*/

public static Map<String, Object> getUserInfo(String code, String agentFlag)

{

String OAUTH_GETUSERINFO_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s";

String url = String.format(OAUTH_GETUSERINFO_URL, getAccessToken(agentFlag), code);

Map<String, Object> result = HttpRequest(url, "GET", null);

return result;

}

/**

* 从配置参数中获取

* @param agentFlag

* @return

*/

public static String getAccessToken(String agentFlag)

{

//这里是获取应用的ACCESS_TOKEN,可以将获取ACCESS_TOKEN放到定时线程内,每2个小时去重新获取一次。

//从数据库或者缓存中拿出应用的ACCESS_TOKEN

......

}

/**

* 通过userid 从微信获取用户

*

* @param userid

* @return

*/

public static WxUser getWxUser(String userid, String agentFlag)

{

String GET_USER_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s";

WxUser user = null;

String url = String.format(Constants.GET_USER_URL, getAccessToken(agentFlag), userid);

Map<String, Object> returnMap = HttpRequest(url, "GET", null);

int errcode = MapUtils.getIntValue(returnMap, "errcode");

if (errcode == 0)

{

user = JSON.toJavaObject((JSON) JSON.toJSON(returnMap), WxUser.class);

}

return user;

}

/**

* 调用微信接口获取accessToken

*

* @param cropid 企业号ID

* @param cropsecret 企业号管理组对应的secret

* @return AccessToken

*/

public static void getAccessToken(String cropid, String cropsecret)

{

String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";

// 添加URL中的cropid和cropsecret的值

String url = String.format(ACCESS_TOKEN_URL, cropid, cropsecret);

// 根据url通过https请求获取accesstoken

Map<String, Object> returnMap = WeixinUtil.HttpRequest(url, "GET", null);

if (null != returnMap && returnMap.size() > 0)

{

// access_token

String access_token = MapUtils.getString(returnMap, "access_token");

// accessToken有效时间expires_in:7200秒

Integer expires_in = MapUtils.getInteger(returnMap, "expires_in");

//可将取到的ACCESS_TOKEN存入数据库或者缓存中。每2个小时更新一次

........

}

else

{

log.info("accesstoken获取失败");

}

}

/**

* 微信接口返回代码转换信息

*

* @param errorcode

* @return

*/

public static String convertErrorCode2Msg(int errorcode)

{

String errmsg = "";

switch (errorcode)

{

case -1:

errmsg = "系统繁忙 ";

break;

case 0:

errmsg = "请求成功 ";

break;

case 40001:

errmsg = "获取access_token时Secret错误,或者access_token无效 ";

break;

case 40002:

errmsg = "不合法的凭证类型";

break;

case 40003:

errmsg = "不合法的UserID";

break;

case 40004:

errmsg = "不合法的媒体文件类型 ";

break;

case 40005:

errmsg = "不合法的文件类型 ";

break;

case 40006:

errmsg = "不合法的文件大小";

break;

case 40007:

errmsg = "不合法的媒体文件id";

break;

case 40008:

errmsg = "不合法的消息类型 ";

break;

case 40013:

errmsg = "不合法的corpid ";

break;

case 40014:

errmsg = "不合法的access_token";

break;

case 40015:

errmsg = "不合法的菜单类型";

break;

case 40016:

errmsg = "不合法的按钮个数";

break;

case 40017:

errmsg = "不合法的按钮类型";

break;

case 40018:

errmsg = "不合法的按钮名字长度";

break;

case 40019:

errmsg = "不合法的按钮KEY长度";

break;

case 40020:

errmsg = "不合法的按钮URL长度 ";

break;

case 40021:

errmsg = "不合法的菜单版本号 ";

break;

case 40022:

errmsg = "不合法的子菜单级数";

break;

case 40023:

errmsg = "不合法的子菜单按钮个数";

break;

case 40024:

errmsg = "不合法的子菜单按钮类型";

break;

case 40025:

errmsg = "不合法的子菜单按钮名字长度";

break;

case 40026:

errmsg = "不合法的子菜单按钮KEY长度";

break;

case 40027:

errmsg = "不合法的子菜单按钮URL长度";

break;

case 40028:

errmsg = "不合法的自定义菜单使用员工";

break;

case 40029:

errmsg = "不合法的oauth_code";

break;

case 40031:

errmsg = "不合法的UserID列表";

break;

case 40032:

errmsg = "不合法的UserID列表长度";

break;

case 40033:

errmsg = "不合法的请求字符,不能包含\\uxxxx格式的字符 ";

break;

case 40035:

errmsg = "不合法的参数 ";

break;

case 40038:

errmsg = "不合法的请求格式 ";

break;

case 40039:

errmsg = "不合法的URL长度";

break;

case 40040:

errmsg = "不合法的插件token";

break;

case 40041:

errmsg = "不合法的插件id";

break;

case 40042:

errmsg = "不合法的插件会话";

break;

case 40048:

errmsg = "url中包含不合法domain";

break;

case 40054:

errmsg = "不合法的子菜单url域名";

break;

case 40055:

errmsg = "不合法的按钮url域名 ";

break;

case 40056:

errmsg = "不合法的agentid";

break;

case 40057:

errmsg = "不合法的callbackurl";

break;

case 40058:

errmsg = "不合法的红包参数 ";

break;

case 40059:

errmsg = "不合法的上报地理位置标志位 ";

break;

case 40060:

errmsg = "设置上报地理位置标志位时没有设置callbackurl";

break;

case 40061:

errmsg = "设置应用头像失败";

break;

case 40062:

errmsg = "不合法的应用模式";

break;

case 40063:

errmsg = "红包参数为空";

break;

case 40064:

errmsg = "管理组名字已存在";

break;

case 40065:

errmsg = "不合法的管理组名字长度";

break;

case 40066:

errmsg = "不合法的部门列表";

break;

case 40067:

errmsg = "标题长度不合法 ";

break;

case 40068:

errmsg = "不合法的标签ID";

break;

case 40069:

errmsg = "不合法的标签ID列表";

break;

case 40070:

errmsg = "列表中所有标签(用户)ID都不合法 ";

break;

case 40071:

errmsg = "不合法的标签名字,标签名字已经存在 ";

break;

case 40072:

errmsg = "不合法的标签名字长度";

break;

case 40073:

errmsg = "不合法的openid";

break;

case 40074:

errmsg = "news消息不支持指定为高保密消息";

break;

case 41001:

errmsg = "缺少access_token参数 ";

break;

case 41002:

errmsg = "缺少corpid参数";

break;

case 41003:

errmsg = "缺少refresh_token参数";

break;

case 41004:

errmsg = "缺少secret参数";

break;

case 41005:

errmsg = "缺少多媒体文件数据";

break;

case 41006:

errmsg = "缺少media_id参数";

break;

case 41007:

errmsg = "缺少子菜单数据";

break;

case 41008:

errmsg = "缺少oauth code";

break;

case 41009:

errmsg = "缺少UserID";

break;

case 41010:

errmsg = "缺少url";

break;

case 41011:

errmsg = "缺少agentid";

break;

case 41012:

errmsg = "缺少应用头像mediaid";

break;

case 41013:

errmsg = "缺少应用名字";

break;

case 41014:

errmsg = "缺少应用描述";

break;

case 41015:

errmsg = "缺少Content";

break;

case 41016:

errmsg = "缺少标题";

break;

case 41017:

errmsg = "缺少标签ID";

break;

case 41018:

errmsg = "缺少标签名字 ";

break;

case 42001:

errmsg = "access_token超时 ";

break;

case 42002:

errmsg = "refresh_token超时";

break;

case 42003:

errmsg = "oauth_code超时 ";

break;

case 42004:

errmsg = "插件token超时";

break;

case 43001:

errmsg = "需要GET请求";

break;

case 43002:

errmsg = "需要POST请求";

break;

case 43003:

errmsg = "需要HTTPS";

break;

case 43004:

errmsg = "需要接收者关注";

break;

case 43005:

errmsg = "需要好友关系";

break;

case 43006:

errmsg = "需要订阅";

break;

case 43007:

errmsg = "需要授权";

break;

case 43008:

errmsg = "需要支付授权";

break;

case 43009:

errmsg = "需要员工已关注";

break;

case 43010:

errmsg = "需要处于回调模式";

break;

case 43011:

errmsg = "需要企业授权";

break;

case 44001:

errmsg = "多媒体文件为空";

break;

case 44002:

errmsg = "POST的数据包为空";

break;

case 44003:

errmsg = "图文消息内容为空";

break;

case 44004:

errmsg = "文本消息内容为空";

break;

case 45001:

errmsg = "多媒体文件大小超过限制";

break;

case 45002:

errmsg = "消息内容超过限制";

break;

case 45003:

errmsg = "标题字段超过限制";

break;

case 45004:

errmsg = "描述字段超过限制";

break;

case 45005:

errmsg = "链接字段超过限制";

break;

case 45006:

errmsg = "图片链接字段超过限制";

break;

case 45007:

errmsg = "语音播放时间超过限制";

break;

case 45008:

errmsg = "图文消息超过限制";

break;

case 45009:

errmsg = "接口调用超过限制";

break;

case 45010:

errmsg = "创建菜单个数超过限制";

break;

case 45015:

errmsg = "回复时间超过限制";

break;

case 45016:

errmsg = "系统分组,不允许修改";

break;

case 45017:

errmsg = "分组名字过长";

break;

case 45018:

errmsg = "分组数量超过上限";

break;

case 45024:

errmsg = "账号数量超过上限";

break;

case 46001:

errmsg = "不存在媒体数据";

break;

case 46002:

errmsg = "不存在的菜单版本";

break;

case 46003:

errmsg = "不存在的菜单数据";

break;

case 46004:

errmsg = "不存在的员工";

break;

case 47001:

errmsg = "解析JSON/XML内容错误";

break;

case 48002:

errmsg = "Api禁用";

break;

case 50001:

errmsg = "redirect_uri未授权";

break;

case 50002:

errmsg = "员工不在权限范围";

break;

case 50003:

errmsg = "应用已停用";

break;

case 50004:

errmsg = "员工状态不正确(未关注状态) ";

break;

case 50005:

errmsg = "企业已禁用";

break;

case 60001:

errmsg = "部门长度不符合限制";

break;

case 60002:

errmsg = "部门层级深度超过限制";

break;

case 60003:

errmsg = "部门不存在";

break;

case 60004:

errmsg = "父亲部门不存在";

break;

case 60005:

errmsg = "不允许删除有成员的部门";

break;

case 60006:

errmsg = "不允许删除有子部门的部门";

break;

case 60007:

errmsg = "不允许删除根部门";

break;

case 60008:

errmsg = "部门名称已存在";

break;

case 60009:

errmsg = "部门名称含有非法字符";

break;

case 60010:

errmsg = "部门存在循环关系";

break;

case 60011:

errmsg = "管理员权限不足,(user/department/agent)无权限";

break;

case 60012:

errmsg = "不允许删除默认应用";

break;

case 60013:

errmsg = "不允许关闭应用";

break;

case 60014:

errmsg = "不允许开启应用";

break;

case 60015:

errmsg = "不允许修改默认应用可见范围";

break;

case 60016:

errmsg = "不允许删除存在成员的标签";

break;

case 60017:

errmsg = "不允许设置企业";

break;

case 60102:

errmsg = "UserID已存在";

break;

case 60103:

errmsg = "手机号码不合法";

break;

case 60104:

errmsg = "手机号码已存在";

break;

case 60105:

errmsg = "邮箱不合法";

break;

case 60106:

errmsg = "邮箱已存在";

break;

case 60107:

errmsg = "微信号不合法";

break;

case 60108:

errmsg = "微信号已存在";

break;

case 60109:

errmsg = "QQ号已存在";

break;

case 60110:

errmsg = "部门个数超出限制";

break;

case 60111:

errmsg = "UserID不存在";

break;

case 60112:

errmsg = "成员姓名不合法";

break;

case 60113:

errmsg = "身份认证信息(微信号/手机/邮箱)不能同时为空 ";

break;

case 60114:

errmsg = "性别不合法";

break;

default:

errmsg = "没有此错误码! ";

break;

}

return errmsg;

}

}

WxUser类的结构如下,省get\set

public class WxUser

{

// 必填, 成员UserID。对应管理端的帐号,企业内必须唯一。不区分大小写,长度为1~64个字节

private String userid;

// 必填,成员名称。长度为1~64个字节

private String name;

// 必填,成员所属部门id列表,不超过20个

private String[] department;

private String deptId;

// 职位信息。长度为0~64个字节

private String position;

// 手机号码。企业内必须唯一,mobile/weixinid/email三者不能同时为空

private String mobile;

// 性别。1表示男性,2表示女性

private String gender;

// 邮箱。长度为0~64个字节。企业内必须唯一

private String email;

// 微信号。企业内必须唯一。(注意:是微信号,不是微信的名字)

private String weixinid;

// 成员头像的mediaid,通过多媒体接口上传图片获得的mediaid

private String avatar_mediaid;

private String avatar;

private String status;

}

  

以上是 企业微信接入自有应用实现免登录 的全部内容, 来源链接: utcz.com/z/509493.html

回到顶部