Browse Source

登录

master
zhizhi wu 6 years ago
parent
commit
fc0b3d06c3
  1. 41
      cloudutil/src/main/java/com/ccsens/cloudutil/feign/HealthFeignClient.java
  2. 80
      health/src/main/java/com/ccsens/health/api/WeixinController.java
  3. 16
      health/src/main/java/com/ccsens/health/bean/dto/EmployeeDto.java
  4. 11
      health/src/main/java/com/ccsens/health/service/IWeiXinService.java
  5. 29
      health/src/main/java/com/ccsens/health/service/WeiXinService.java
  6. 6
      tall/src/main/java/com/ccsens/tall/bean/dto/UserDto.java
  7. 2
      tall/src/main/java/com/ccsens/tall/service/IUserService.java
  8. 96
      tall/src/main/java/com/ccsens/tall/service/UserService.java
  9. 5
      tall/src/main/java/com/ccsens/tall/web/UserController.java
  10. 1
      tall/src/main/resources/application-test.yml
  11. 2
      util/home
  12. 5
      util/src/main/java/com/ccsens/util/CodeEnum.java
  13. 5
      util/src/main/java/com/ccsens/util/PropUtil.java
  14. 6
      util/src/main/java/com/ccsens/util/WebConstant.java
  15. 89
      util/src/main/java/com/ccsens/util/enterprisewx/WeiXinConstant.java
  16. 49
      util/src/main/java/com/ccsens/util/enterprisewx/vo/WeiXinVo.java

41
cloudutil/src/main/java/com/ccsens/cloudutil/feign/HealthFeignClient.java

@ -0,0 +1,41 @@
package com.ccsens.cloudutil.feign;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "health", path = "", fallbackFactory = HealthFeignClientFallBack.class)
public interface HealthFeignClient {
/**
* 获取suiteAccessToken
* @param suiteId
* @return
*/
@GetMapping("getSuiteAccessToken")
String getSuiteAccessToken(@RequestParam(name = "suiteId") String suiteId);
}
@Slf4j
@Component
class HealthFeignClientFallBack implements FallbackFactory<HealthFeignClient> {
@Override
public HealthFeignClient create(Throwable throwable) {
String msg = throwable == null ? "" : throwable.getMessage();
if (!StringUtils.isEmpty(msg)) {
log.error(msg);
}
return new HealthFeignClient() {
@Override
public String getSuiteAccessToken(String suiteId) {
return null;
}
};
}
}

80
health/src/main/java/com/ccsens/health/api/WeixinController.java

@ -4,10 +4,14 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ccsens.health.bean.dto.EmployeeDto;
import com.ccsens.health.bean.po.HealthAuth;
import com.ccsens.health.persist.dao.EmployeeDao;
import com.ccsens.health.service.IConstantService; import com.ccsens.health.service.IConstantService;
import com.ccsens.health.service.IWeiXinService; import com.ccsens.health.service.IWeiXinService;
import com.ccsens.util.HttpsUtil; import com.ccsens.util.HttpsUtil;
import com.ccsens.util.JacksonUtil; import com.ccsens.util.JacksonUtil;
import com.ccsens.util.JsonResponse;
import com.ccsens.util.RestTemplateUtil; import com.ccsens.util.RestTemplateUtil;
import com.ccsens.util.enterprisewx.AesException; import com.ccsens.util.enterprisewx.AesException;
import com.ccsens.util.enterprisewx.WXBizMsgCrypt; import com.ccsens.util.enterprisewx.WXBizMsgCrypt;
@ -15,16 +19,11 @@ import com.ccsens.util.enterprisewx.WeiXinConstant;
import com.ccsens.util.enterprisewx.dto.MessageDto; import com.ccsens.util.enterprisewx.dto.MessageDto;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author wu * @author wu
@ -84,9 +83,8 @@ public class WeixinController {
* 数据回调URL post * 数据回调URL post
*/ */
@PostMapping("userChangeNotice") @PostMapping("userChangeNotice")
public String userChangeNoticePost(HttpServletRequest request, MessageDto dto) throws Exception{ public String userChangeNoticePost(MessageDto dto, @RequestBody String body) throws Exception{
log.info("数据回调请求参数:{}", dto); log.info("数据回调请求参数:{}", dto);
String body = getBody(request);
String xmlStr = JacksonUtil.xmlToJson(body); String xmlStr = JacksonUtil.xmlToJson(body);
log.info("数据回到xml转换:{}", xmlStr); log.info("数据回到xml转换:{}", xmlStr);
JSONObject jsonObject = JSONObject.parseObject(xmlStr); JSONObject jsonObject = JSONObject.parseObject(xmlStr);
@ -99,11 +97,9 @@ public class WeixinController {
* 指令回调URL * 指令回调URL
*/ */
@PostMapping("authorizationChangeNotice") @PostMapping("authorizationChangeNotice")
public String authorizationChangeNotice(HttpServletRequest request, MessageDto dto) throws Exception{ public String authorizationChangeNotice(MessageDto dto, @RequestBody String body) throws Exception{
log.info("指令回调请求参数:{}", dto); log.info("指令回调请求参数:{}, body:{}", dto, body);
String listString = getBody(request); String xmlStr = JacksonUtil.xmlToJson(body);
log.info("指令回调body:{}", listString);
String xmlStr = JacksonUtil.xmlToJson(listString);
log.info("指令回到xml转换:{}", xmlStr); log.info("指令回到xml转换:{}", xmlStr);
JSONObject jsonObject = JSONObject.parseObject(xmlStr); JSONObject jsonObject = JSONObject.parseObject(xmlStr);
log.info("jsonObject:{}", jsonObject); log.info("jsonObject:{}", jsonObject);
@ -119,13 +115,27 @@ public class WeixinController {
MessageDto.Ticket ticket = JSONObject.parseObject(jsonStr, MessageDto.Ticket.class); MessageDto.Ticket ticket = JSONObject.parseObject(jsonStr, MessageDto.Ticket.class);
constantService.saveConstant(WeiXinConstant.getSuiteTicket(ticket.getSuiteId()), ticket.getSuiteTicket()); constantService.saveConstant(WeiXinConstant.getSuiteTicket(ticket.getSuiteId()), ticket.getSuiteTicket());
//获取第三方应用凭证 //获取第三方应用凭证
new Thread(new Runnable() {
@Override
public void run() {
getSuiteAccessToken(ticket.getSuiteId(),ticket.getSuiteTicket()); getSuiteAccessToken(ticket.getSuiteId(),ticket.getSuiteTicket());
}
}).start();
break; break;
case "create_auth" : case "create_auth" :
MessageDto.Grant grant = JSONObject.parseObject(jsonStr, MessageDto.Grant.class); MessageDto.Grant grant = JSONObject.parseObject(jsonStr, MessageDto.Grant.class);
constantService.saveConstant(WeiXinConstant.getTempAuthCodeKey(grant.getSuiteId()), grant.getAuthCode()); constantService.saveConstant(WeiXinConstant.getTempAuthCodeKey(grant.getSuiteId()), grant.getAuthCode());
//获取永久授权 //获取永久授权
log.info("grant:{}", grant);
new Thread(new Runnable() {
@Override
public void run() {
getPermanentCode(grant.getSuiteId(), grant.getAuthCode()); getPermanentCode(grant.getSuiteId(), grant.getAuthCode());
}
}).start();
break; break;
case "change_auth" : case "change_auth" :
//TODO 变更授权通知 //TODO 变更授权通知
@ -135,6 +145,7 @@ public class WeixinController {
break; break;
//TODO 成员变更和部门变更通知 //TODO 成员变更和部门变更通知
} }
log.info("-----------------------------------------------------");
return "success"; return "success";
} }
@ -148,21 +159,6 @@ public class WeixinController {
weiXinService.getSuiteToken(suite_id, suite_ticket); weiXinService.getSuiteToken(suite_id, suite_ticket);
} }
/**
* 读取body
* @param request
* @return
* @throws IOException
*/
private String getBody(HttpServletRequest request) throws IOException {
BufferedReader br = request.getReader();
String str = "";
String listString = "";
while ((str = br.readLine()) != null) {
listString += str;
}
return listString;
}
/** /**
* 获取永久授权码 * 获取永久授权码
@ -172,9 +168,9 @@ public class WeixinController {
public void getPermanentCode(String suiteId, String authCode){ public void getPermanentCode(String suiteId, String authCode){
String suiteTicket = constantService.getByKey(WeiXinConstant.getSuiteTicket(suiteId)); String suiteTicket = constantService.getByKey(WeiXinConstant.getSuiteTicket(suiteId));
String suiteToken = weiXinService.getSuiteToken(suiteId, suiteTicket); String suiteToken = weiXinService.getSuiteToken(suiteId, suiteTicket);
String accessToken = weiXinService.savePermanentCode(authCode, suiteToken); HealthAuth auth = weiXinService.savePermanentCode(authCode, suiteToken);
if (StrUtil.isNotBlank(accessToken)) { if (auth != null) {
weiXinService.initDepartment(accessToken); weiXinService.initDepartment(auth.getAccessToken());
} }
} }
@ -189,4 +185,26 @@ public class WeixinController {
log.info("解析结果:{}", verifyURL); log.info("解析结果:{}", verifyURL);
return verifyURL; return verifyURL;
} }
/**
* 获取第三方应用凭证suiteAccessToken
* @param suiteId
* @return
*/
@GetMapping("getSuiteAccessToken")
public String getSuiteAccessToken(String suiteId) {
String suiteTicket = constantService.getByKey(WeiXinConstant.getSuiteTicket(suiteId));
return weiXinService.getSuiteToken(suiteId, suiteTicket);
}
/**
* 获取第三方应用凭证suiteAccessToken
* @param bind
* @return
*/
@GetMapping("bindUser")
public JsonResponse bindUser(@RequestBody EmployeeDto.Bind bind) {
weiXinService.bindUser(bind);
return JsonResponse.newInstance().ok();
}
} }

16
health/src/main/java/com/ccsens/health/bean/dto/EmployeeDto.java

@ -0,0 +1,16 @@
package com.ccsens.health.bean.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel("员工信息")
public class EmployeeDto {
@Data
@ApiModel("绑定用户")
public static class Bind{
private Long tallUserId;
private String userid;
}
}

11
health/src/main/java/com/ccsens/health/service/IWeiXinService.java

@ -1,5 +1,8 @@
package com.ccsens.health.service; package com.ccsens.health.service;
import com.ccsens.health.bean.dto.EmployeeDto;
import com.ccsens.health.bean.po.HealthAuth;
/** /**
* 企业微信相关业务 * 企业微信相关业务
*/ */
@ -9,7 +12,7 @@ public interface IWeiXinService {
* 保存永久授权 * 保存永久授权
* @param authCode 微信返回永久授权字符串 * @param authCode 微信返回永久授权字符串
*/ */
String savePermanentCode(String authCode, String suiteAccessToken); HealthAuth savePermanentCode(String authCode, String suiteAccessToken);
/** /**
* 获取第三方应用凭证 * 获取第三方应用凭证
@ -32,4 +35,10 @@ public interface IWeiXinService {
* @param accessToken * @param accessToken
*/ */
void initDepartment(String accessToken); void initDepartment(String accessToken);
/**
* 用户绑定
* @param bind
*/
void bindUser(EmployeeDto.Bind bind);
} }

29
health/src/main/java/com/ccsens/health/service/WeiXinService.java

@ -5,15 +5,18 @@ import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ccsens.health.bean.dto.EmployeeDto;
import com.ccsens.health.bean.po.*; import com.ccsens.health.bean.po.*;
import com.ccsens.health.persist.dao.DepartmentDao; import com.ccsens.health.persist.dao.DepartmentDao;
import com.ccsens.health.persist.dao.DepartmentEmployeeDao; import com.ccsens.health.persist.dao.DepartmentEmployeeDao;
import com.ccsens.health.persist.dao.EmployeeDao; import com.ccsens.health.persist.dao.EmployeeDao;
import com.ccsens.health.persist.mapper.HealthAuthAgentMapper; import com.ccsens.health.persist.mapper.HealthAuthAgentMapper;
import com.ccsens.health.persist.mapper.HealthAuthMapper; import com.ccsens.health.persist.mapper.HealthAuthMapper;
import com.ccsens.util.CodeEnum;
import com.ccsens.util.RedisUtil; import com.ccsens.util.RedisUtil;
import com.ccsens.util.RestTemplateUtil; import com.ccsens.util.RestTemplateUtil;
import com.ccsens.util.enterprisewx.WeiXinConstant; import com.ccsens.util.enterprisewx.WeiXinConstant;
import com.ccsens.util.exception.BaseException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -75,6 +78,25 @@ public class WeiXinService implements IWeiXinService {
return accessToken; return accessToken;
} }
@Override
public void bindUser(EmployeeDto.Bind bind) {
log.info("用户绑定:{}", bind);
EmployeeExample example = new EmployeeExample();
example.createCriteria().andUseridEqualTo(bind.getUserid());
List<Employee> employees = employeeDao.selectByExample(example);
log.info("有无用户信息");
if (CollectionUtil.isEmpty(employees)) {
throw new BaseException(CodeEnum.PARAM_ERROR);
}
Employee employee = employees.get(0);
if (employee.getTallUserId() == null || employee.getTallUserId() == 0) {
Employee bindEmployee = new Employee();
bindEmployee.setId(employee.getId());
bindEmployee.setTallUserId(bind.getTallUserId());
employeeDao.updateByPrimaryKeySelective(bindEmployee);
}
}
@Override @Override
public String getSuiteToken(String suiteId, String suiteTicket) { public String getSuiteToken(String suiteId, String suiteTicket) {
log.info("获取suiteToken, suiteId:{}, suiteTicket:{}", suiteId, suiteTicket); log.info("获取suiteToken, suiteId:{}, suiteTicket:{}", suiteId, suiteTicket);
@ -108,15 +130,16 @@ public class WeiXinService implements IWeiXinService {
} }
@Override @Override
public String savePermanentCode(String authCode, String suiteAccessToken) { public HealthAuth savePermanentCode(String authCode, String suiteAccessToken) {
//授权成功通知 //授权成功通知
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
params.put("auth_code", authCode); params.put("auth_code", authCode);
String url = WeiXinConstant.GET_PERMANENT_CODE + " ?suite_access_token=" + suiteAccessToken; String url = WeiXinConstant.GET_PERMANENT_CODE + " ?suite_access_token=" + suiteAccessToken;
log.info("获取永久授权参数, auth_code:{}, suite:{}", authCode, suiteAccessToken);
String result = RestTemplateUtil.postBody(url, params); String result = RestTemplateUtil.postBody(url, params);
log.info("获取永久授权返回:{}", result); log.info("获取永久授权返回:{}", result);
JSONObject json = JSONObject.parseObject(result); JSONObject json = JSONObject.parseObject(result);
if (json.getInteger(WeiXinConstant.ERR_CODE).intValue() != 0) { if (json.getInteger(WeiXinConstant.ERR_CODE) !=null && json.getIntValue(WeiXinConstant.ERR_CODE) != 0) {
log.error("获取永久授权码异常:{}", result); log.error("获取永久授权码异常:{}", result);
//TODO 异常如何处理 //TODO 异常如何处理
return null; return null;
@ -128,7 +151,7 @@ public class WeiXinService implements IWeiXinService {
if (agent != null) { if (agent != null) {
healthAuthAgentMapper.insertSelective(agent); healthAuthAgentMapper.insertSelective(agent);
} }
return json.getString("access_token"); return auth;
} }
@Override @Override

6
tall/src/main/java/com/ccsens/tall/bean/dto/UserDto.java

@ -24,14 +24,16 @@ public class UserDto {
@ApiModelProperty("用户凭据|密码") @ApiModelProperty("用户凭据|密码")
private String credential; private String credential;
} }
@ApiModelProperty("登录客户端:0-wxmp,1-H5,2-Android,3-IOS") @ApiModelProperty("登录客户端:0-wxmp,1-H5,2-Android,3-IOS,4-WxEnterprise")
@NotNull(message = "client is required.") @NotNull(message = "client is required.")
private Integer client; private Integer client;
@ApiModelProperty("登录类型:0-wxmp,1-phone,2-email,3-accounts,4-OAUTH2_Wx,5-Wx_H5,6-OAUTH2_WeiBo") @ApiModelProperty("登录类型:0-wxmp,1-phone,2-email,3-accounts,4-OAUTH2_Wx,5-Wx_H5,6-OAUTH2_WeiBo, 7-Wx_Enterprise")
@NotNull(message = "type is required.") @NotNull(message = "type is required.")
private Integer type; private Integer type;
@ApiModelProperty("登录信息") @ApiModelProperty("登录信息")
private Data data; private Data data;
@ApiModelProperty("通知消息")
private String redirect;
} }
@Data @Data

2
tall/src/main/java/com/ccsens/tall/service/IUserService.java

@ -14,7 +14,7 @@ import java.util.Map;
public interface IUserService { public interface IUserService {
UserVo.UserSign signin(WebConstant.CLIENT_TYPE clientType, WebConstant.IDENTIFY_TYPE identifyType, UserVo.UserSign signin(WebConstant.CLIENT_TYPE clientType, WebConstant.IDENTIFY_TYPE identifyType,
String identifier, String credential, String clientIp) throws Exception; String identifier, String credential, String clientIp, String redirect) throws Exception;
UserVo.TokenBean generateToken(WebConstant.CLIENT_TYPE client_type, Object subject, Map<String, Object> payLoads) throws Exception; UserVo.TokenBean generateToken(WebConstant.CLIENT_TYPE client_type, Object subject, Map<String, Object> payLoads) throws Exception;

96
tall/src/main/java/com/ccsens/tall/service/UserService.java

@ -7,6 +7,7 @@ import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ccsens.cloudutil.feign.HealthFeignClient;
import com.ccsens.tall.bean.dto.ProjectDto; import com.ccsens.tall.bean.dto.ProjectDto;
import com.ccsens.tall.bean.dto.UserDto; import com.ccsens.tall.bean.dto.UserDto;
import com.ccsens.tall.bean.po.*; import com.ccsens.tall.bean.po.*;
@ -15,10 +16,13 @@ import com.ccsens.tall.exception.SmsException;
import com.ccsens.tall.persist.dao.*; import com.ccsens.tall.persist.dao.*;
import com.ccsens.util.*; import com.ccsens.util.*;
import com.ccsens.util.bean.wx.po.WxOauth2UserInfo; import com.ccsens.util.bean.wx.po.WxOauth2UserInfo;
import com.ccsens.util.enterprisewx.WeiXinConstant;
import com.ccsens.util.enterprisewx.vo.WeiXinVo;
import com.ccsens.util.exception.BaseException; import com.ccsens.util.exception.BaseException;
import com.ccsens.util.wx.WxGzhUtil; import com.ccsens.util.wx.WxGzhUtil;
import com.ccsens.util.wx.WxXcxUtil; import com.ccsens.util.wx.WxXcxUtil;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -28,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.xhtmlrenderer.css.parser.property.PrimitivePropertyBuilders; import org.xhtmlrenderer.css.parser.property.PrimitivePropertyBuilders;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -57,6 +62,8 @@ public class UserService implements IUserService {
private SysProjectDao sysProjectDao; private SysProjectDao sysProjectDao;
@Autowired @Autowired
private UserAttentionDao userAttentionDao; private UserAttentionDao userAttentionDao;
@Autowired
private HealthFeignClient healthFeignClient;
/** /**
@ -64,10 +71,10 @@ public class UserService implements IUserService {
*/ */
@Override @Override
public UserVo.UserSign signin(WebConstant.CLIENT_TYPE clientType, WebConstant.IDENTIFY_TYPE identifyType, public UserVo.UserSign signin(WebConstant.CLIENT_TYPE clientType, WebConstant.IDENTIFY_TYPE identifyType,
String identifier, String credential, String clientIp) throws Exception { String identifier, String credential, String clientIp,String redirect) throws Exception {
UserVo.UserSign userSignVo = null; UserVo.UserSign userSignVo = null;
//1.登陆 //1.登陆
userSignVo = __signin(identifyType, identifier, credential); userSignVo = __signin(identifyType, identifier, credential, redirect);
if (ObjectUtil.isNotNull(userSignVo) && ObjectUtil.isNotNull(userSignVo.getAuthId())) { if (ObjectUtil.isNotNull(userSignVo) && ObjectUtil.isNotNull(userSignVo.getAuthId())) {
//2.添加登陆记录 //2.添加登陆记录
__addSigninRecord(clientType, clientIp, userSignVo.getAuthId()); __addSigninRecord(clientType, clientIp, userSignVo.getAuthId());
@ -76,8 +83,10 @@ public class UserService implements IUserService {
} }
private UserVo.UserSign __signin(WebConstant.IDENTIFY_TYPE identifyType, private UserVo.UserSign __signin(WebConstant.IDENTIFY_TYPE identifyType,
String identifier, String credential) throws Exception { String identifier, String credential, String redirect) throws Exception {
switch (identifyType) { switch (identifyType) {
case WxEnterprise:
return wxEnterpriseLogin(identifier, credential, redirect);
case Wxmp: case Wxmp:
credential = credential == null ? "old" : credential; credential = credential == null ? "old" : credential;
return wxmplogin(identifier,credential); return wxmplogin(identifier,credential);
@ -100,6 +109,33 @@ public class UserService implements IUserService {
return null; return null;
} }
/**
* 企业登录
* @param identifier
* @param credential
* @return
*/
private UserVo.UserSign wxEnterpriseLogin(String identifier, String credential, String redirect) {
log.info("企业微信登录:{},{}, {}");
String suiteId = WeiXinConstant.SuiteId.getValue(credential);
if (StrUtil.isBlank(suiteId) || StrUtil.isBlank(identifier)) {
throw new BaseException(CodeEnum.PARAM_ERROR);
}
String suiteAccessToken = healthFeignClient.getSuiteAccessToken(suiteId);
WeiXinVo.UserInfo userInfo = WeiXinConstant.getUserInfo(identifier, suiteAccessToken);
log.info("用户信息");
if (userInfo == null) {
throw new BaseException(CodeEnum.PARAM_ERROR);
}
WxEnterpriseParam param = new WxEnterpriseParam();
param.setRedirect(redirect);
param.setSuiteAccessToken(suiteAccessToken);
param.setUserTicket(userInfo.getUser_ticket());
UserVo.UserSign userSignVo = getUserSign(userInfo.getUserId(), null, (byte) WebConstant.IDENTIFY_TYPE.WxEnterprise.value, param);
return userSignVo;
}
/** /**
* 微信网页登陆 * 微信网页登陆
* *
@ -348,19 +384,36 @@ public class UserService implements IUserService {
* 微信小程序 * 微信小程序
*/ */
private UserVo.UserSign wxmplogin(String code,String gameType) throws Exception { private UserVo.UserSign wxmplogin(String code,String gameType) throws Exception {
UserVo.UserSign userSignVo = null;
//0.获取openid //0.获取openid
WxXcxUtil.WechatUser wechatUser = WxXcxUtil.getUserInfo(code,gameType); WxXcxUtil.WechatUser wechatUser = WxXcxUtil.getUserInfo(code,gameType);
String openId = wechatUser.openid; String openId = wechatUser.openid;
String unionId = wechatUser.unionid; String unionId = wechatUser.unionid;
log.info("小程序登录,openid:{} ,unionId:{}", openId, unionId); log.info("小程序登录,openid:{} ,unionId:{}", openId, unionId);
//1.查找对应账户,不存在则注册 UserVo.UserSign userSignVo = getUserSign(openId, unionId, (byte) WebConstant.IDENTIFY_TYPE.Wxmp.value,null);
return userSignVo;
}
@Data
private static class WxEnterpriseParam{
private String suiteAccessToken;
private String userTicket;
private String redirect;
}
/**
*
* @param openId
* @param unionId
* @return
*/
private UserVo.UserSign getUserSign(String openId, String unionId,
byte identifyType, WxEnterpriseParam param) {
UserVo.UserSign userSignVo;//1.查找对应账户,不存在则注册
List<SysAuth> authList = null; List<SysAuth> authList = null;
SysAuth theAuth = null; SysAuth theAuth = null;
if(ObjectUtil.isNotNull(openId)) { if(ObjectUtil.isNotNull(openId)) {
SysAuthExample authExample = new SysAuthExample(); SysAuthExample authExample = new SysAuthExample();
authExample.createCriteria().andIdentifyTypeEqualTo((byte) WebConstant.IDENTIFY_TYPE.Wxmp.value) authExample.createCriteria().andIdentifyTypeEqualTo(identifyType)
.andIdentifierEqualTo(openId); .andIdentifierEqualTo(openId);
authList = authDao.selectByExample(authExample); authList = authDao.selectByExample(authExample);
} }
@ -372,25 +425,31 @@ public class UserService implements IUserService {
sysAuthList = authDao.selectByExample(sysAuthExample); sysAuthList = authDao.selectByExample(sysAuthExample);
} }
if (CollectionUtil.isNotEmpty(sysAuthList)) { if (CollectionUtil.isNotEmpty(sysAuthList)) {
// SysAuth sysAuth = sysAuthList.get(0); if (identifyType == WebConstant.IDENTIFY_TYPE.Wxmp.value) {
//添加认证方式 //添加认证方式
theAuth = new SysAuth(); theAuth = new SysAuth();
theAuth.setId(snowflake.nextId()); theAuth.setId(snowflake.nextId());
theAuth.setUserId(sysAuthList.get(0).getUserId()); theAuth.setUserId(sysAuthList.get(0).getUserId());
theAuth.setIdentifyType((byte) WebConstant.IDENTIFY_TYPE.Wxmp.value); theAuth.setIdentifyType(identifyType);
theAuth.setIdentifier(openId); theAuth.setIdentifier(openId);
theAuth.setCredential(unionId); theAuth.setCredential(unionId);
authDao.insertSelective(theAuth); authDao.insertSelective(theAuth);
} else {
theAuth = sysAuthList.get(0);
}
} else { } else {
//新建用户并保存微信信息 //新建用户并保存微信信息
SysUser user = new SysUser(); SysUser user = new SysUser();
user.setId(snowflake.nextId()); user.setId(snowflake.nextId());
//企业微信获取详细用户信息,并绑定用户信息
getUserDetail(identifyType, param, user);
userDao.insertSelective(user); userDao.insertSelective(user);
//添加认证方式 //添加认证方式
theAuth = new SysAuth(); theAuth = new SysAuth();
theAuth.setId(snowflake.nextId()); theAuth.setId(snowflake.nextId());
theAuth.setUserId(user.getId()); theAuth.setUserId(user.getId());
theAuth.setIdentifyType((byte) WebConstant.IDENTIFY_TYPE.Wxmp.value); theAuth.setIdentifyType(identifyType);
theAuth.setIdentifier(openId); theAuth.setIdentifier(openId);
theAuth.setCredential(unionId); theAuth.setCredential(unionId);
authDao.insertSelective(theAuth); authDao.insertSelective(theAuth);
@ -416,6 +475,23 @@ public class UserService implements IUserService {
return userSignVo; return userSignVo;
} }
private void getUserDetail(byte identifyType, WxEnterpriseParam param, SysUser user) {
if (identifyType == WebConstant.IDENTIFY_TYPE.Wxmp.value) {
WeiXinVo.UserDetail userDetail = WeiXinConstant.getUserDetail(param.getSuiteAccessToken(), param.getUserTicket());
if (userDetail != null) {
user.setNickname(userDetail.getName());
user.setGender(userDetail.getGender());
user.setAvatarUrl(userDetail.getAvatar());
}
Map<String, Object> map = new HashMap<>();
map.put("tallUserId", user.getId());
map.put("userid", userDetail.getUserid());
String s = RestTemplateUtil.postBody(WeiXinConstant.getBindUrl(param.getRedirect()), map);
log.info("{}绑定关系结果:{}", s);
//TODO 绑定失败如何处理
}
}
/** /**
* 微信登陆后天添加用户和认证方式 * 微信登陆后天添加用户和认证方式
* *

5
tall/src/main/java/com/ccsens/tall/web/UserController.java

@ -52,16 +52,19 @@ public class UserController {
//1.验证参数 //1.验证参数
switch (clientType) { switch (clientType) {
case Wxmp: case Wxmp:
case H5: case H5:
case Android: case Android:
case IOS: case IOS:
case WxEnterprise:
break; break;
default: default:
throw new UserLoginException(-1, String.format("Not supported client type: %1$d(%2$s)", throw new UserLoginException(-1, String.format("Not supported client type: %1$d(%2$s)",
clientType.value, clientType)); clientType.value, clientType));
} }
switch (identify_type) { switch (identify_type) {
case WxEnterprise:
case Wxmp: case Wxmp:
case OAUTH2_Wx: case OAUTH2_Wx:
case Wx_H5: case Wx_H5:
@ -86,7 +89,7 @@ public class UserController {
//2.调用业务方法(注册/添加登陆记录) //2.调用业务方法(注册/添加登陆记录)
UserVo.UserSign userSignVo = userService.signin( UserVo.UserSign userSignVo = userService.signin(
clientType, identify_type, identifier, credential, clientType, identify_type, identifier, credential,
ServletUtil.getClientIP(request)); ServletUtil.getClientIP(request), dto.getRedirect());
//3.生成token(access_token,refresh_token) //3.生成token(access_token,refresh_token)
if (ObjectUtil.isNotNull(userSignVo)) { if (ObjectUtil.isNotNull(userSignVo)) {

1
tall/src/main/resources/application-test.yml

@ -29,3 +29,4 @@ swagger:
eureka: eureka:
instance: instance:
ip-address: 49.233.89.188 ip-address: 49.233.89.188
gatewayUrl: https://test.tall.wiki/gateway/

2
util/home

@ -1 +1 @@
{"errcode":41030,"errmsg":"invalid page hint: [G0bX408102372]"} {"errcode":41030,"errmsg":"invalid page hint: [0r6Ija0174b464]"}

5
util/src/main/java/com/ccsens/util/CodeEnum.java

@ -94,8 +94,9 @@ public enum CodeEnum {
NOT_SIGN_FIELD(77,"签到的字段不可用",true), NOT_SIGN_FIELD(77,"签到的字段不可用",true),
ALREADY_SIGN(78,"您已经签到过了,请勿重复签到",true), ALREADY_SIGN(78,"您已经签到过了,请勿重复签到",true),
ALREADY_ATTENTION(79,"您已经关注了这个项目",true), ALREADY_ATTENTION(79,"您已经关注了这个项目",true),
NOT_EMPLOYEE(79,"未找到成员信息",true), NOT_EMPLOYEE(80,"未找到成员信息",true),
NOT_SITE(79,"未找到该场所",true) NOT_SITE(81,"未找到该场所",true),
LACK_CONFIG(82,"缺少配置",true),
; ;
public CodeEnum addMsg(String msg){ public CodeEnum addMsg(String msg){

5
util/src/main/java/com/ccsens/util/PropUtil.java

@ -16,7 +16,12 @@ public class PropUtil {
public static String imgDomain; public static String imgDomain;
public static String projectName; public static String projectName;
public static String contextPath; public static String contextPath;
public static String gatewayUrl;
@Value("${gatewayUrl:}")
public void setGatewayUrl(String gatewayUrl) {
PropUtil.gatewayUrl = gatewayUrl;
}
@Value("${file.path:}") @Value("${file.path:}")
public void setPath(String path) { public void setPath(String path) {
PropUtil.path = path; PropUtil.path = path;

6
util/src/main/java/com/ccsens/util/WebConstant.java

@ -146,7 +146,8 @@ public class WebConstant {
public enum CLIENT_TYPE { public enum CLIENT_TYPE {
Wxmp(0,"微信小程序"), H5(1,"网页"),Android(2 Wxmp(0,"微信小程序"), H5(1,"网页"),Android(2
,"安卓客户端"),IOS(3,"苹果客户端"); ,"安卓客户端"),IOS(3,"苹果客户端"),
WxEnterprise(4, "企业微信");
public int value; public int value;
public String phase; public String phase;
@ -170,7 +171,7 @@ public class WebConstant {
Wxmp(0,"微信小程序"), Phone(1,"电话") Wxmp(0,"微信小程序"), Phone(1,"电话")
, Email(2,"Email"), Account(3,"账号") , Email(2,"Email"), Account(3,"账号")
,OAUTH2_Wx(4,"微信公众号"),Wx_H5(5,"网页微信登陆") ,OAUTH2_Wx(4,"微信公众号"),Wx_H5(5,"网页微信登陆")
,OAUTH2_WeiBo(6,"微博"); ,OAUTH2_WeiBo(6,"微博"),WxEnterprise(7, "企业微信"),;
public int value; public int value;
public String phase; public String phase;
@ -188,6 +189,7 @@ public class WebConstant {
case 4: return OAUTH2_Wx; case 4: return OAUTH2_Wx;
case 5: return Wx_H5; case 5: return Wx_H5;
case 6: return OAUTH2_WeiBo; case 6: return OAUTH2_WeiBo;
case 7: return WxEnterprise;
default: return null; default: return null;
} }
} }

89
util/src/main/java/com/ccsens/util/enterprisewx/WeiXinConstant.java

@ -1,10 +1,22 @@
package com.ccsens.util.enterprisewx; package com.ccsens.util.enterprisewx;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ccsens.util.CodeEnum;
import com.ccsens.util.PropUtil;
import com.ccsens.util.RestTemplateUtil;
import com.ccsens.util.enterprisewx.vo.WeiXinVo;
import com.ccsens.util.exception.BaseException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author wu * @author wu
*/ */
@Slf4j
public class WeiXinConstant { public class WeiXinConstant {
public static final String token = "4CxIpRDBWHMiePP3x6muNe4hRj"; public static final String token = "4CxIpRDBWHMiePP3x6muNe4hRj";
@ -16,10 +28,33 @@ public class WeiXinConstant {
public static final String secret= "HyhFPrD_7gObsQdX1RTTH6nDeJNduVKGuaF62zqmgYs"; public static final String secret= "HyhFPrD_7gObsQdX1RTTH6nDeJNduVKGuaF62zqmgYs";
public static final String ERR_CODE = "errcode"; public static final String ERR_CODE = "errcode";
public static final String ERR_MSG = "errmsg"; public static final String ERR_MSG = "errmsg";
@Getter
public static enum SuiteId{
Health("health","wwb9ce2061d1cce110"),;
private String suiteType;
private String suiteValue;
private SuiteId(String suiteType, String suiteValue){
this.suiteType = suiteType;
this.suiteValue = suiteValue;
}
/**
* 根据类型获取value
* @param suiteType
* @return
*/
public static String getValue(String suiteType) {
switch (suiteType) {
case "health" : return Health.getSuiteValue();
default: return null;
}
}
}
/** /**
* 获取永久授权 * 获取永久授权
*/ */
@ -28,7 +63,8 @@ public class WeiXinConstant {
public static final String GET_CORP_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token"; public static final String GET_CORP_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token";
public static final String DEPARTMENT_LIST = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; public static final String DEPARTMENT_LIST = "https://qyapi.weixin.qq.com/cgi-bin/department/list";
public static final String USER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/user/list"; public static final String USER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/user/list";
public static final String USER_INFO_3RD = "https://qyapi.weixin.qq.com/cgi-bin/service/getuserinfo3rd";
public static final String USER_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/service/getuserdetail3rd";
/** /**
* 获取第三方凭证 * 获取第三方凭证
@ -75,7 +111,56 @@ public class WeiXinConstant {
* @return * @return
*/ */
public static boolean pageResult(JSONObject result) { public static boolean pageResult(JSONObject result) {
return result.getIntValue(ERR_CODE) == 0;
return result.getInteger(ERR_CODE) == null || result.getIntValue(ERR_CODE) == 0;
} }
/**
* 查询用户信息
* @param code
* @param suiteAccessToken
* @return
*/
public static WeiXinVo.UserInfo getUserInfo(String code, String suiteAccessToken) {
Map<String, Object> param = new HashMap<>();
param.put("suite_access_token", suiteAccessToken);
param.put("code", code);
WeiXinVo.UserInfo userInfo = (WeiXinVo.UserInfo) RestTemplateUtil.getForEntity(USER_INFO_3RD, param, WeiXinVo.UserInfo.class);
log.info("获取用户信息:{}", userInfo);
if (StrUtil.isNotBlank(userInfo.getErrcode()) && !"0".equals(userInfo.getErrcode())) {
return null;
}
return userInfo;
}
/**
* 获取用户详细信息
* @param suite_access_token
* @param user_ticket
* @return
*/
public static WeiXinVo.UserDetail getUserDetail(String suite_access_token, String user_ticket){
String url = USER_DETAIL + "?suite_access_token=" + suite_access_token;
Map<String, Object> param = new HashMap<>();
param.put("user_ticket", user_ticket);
String result = RestTemplateUtil.postBody(url, param);
log.info("获取用户详细信息返回:{}", result);
WeiXinVo.UserDetail userDetail = JSONObject.parseObject(result, WeiXinVo.UserDetail.class);
if (StrUtil.isNotBlank(userDetail.getErrcode()) && !"0".equals(userDetail.getErrcode())) {
return null;
}
return userDetail;
}
/**
* 获取绑定路径
* @param type
* @return
*/
public static String getBindUrl(String type){
if (StrUtil.isBlank(PropUtil.gatewayUrl)) {
throw new BaseException(CodeEnum.LACK_CONFIG);
}
return PropUtil.gatewayUrl + type + "/bindUser";
}
} }

49
util/src/main/java/com/ccsens/util/enterprisewx/vo/WeiXinVo.java

@ -0,0 +1,49 @@
package com.ccsens.util.enterprisewx.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("微信相关接口返回")
public class WeiXinVo {
@Data
@ApiModel("微信用戶信息")
public static class UserInfo{
@ApiModelProperty("返回码")
private String errcode;
@ApiModelProperty("对返回码的文本描述内容")
private String errmsg;
@ApiModelProperty("用户所属企业的corpid")
private String CorpId;
@ApiModelProperty("用户在企业内的UserID,如果该企业与第三方应用有授权关系时,返回明文UserId,否则返回密文UserId")
private String UserId;
@ApiModelProperty("手机设备号(由企业微信在安装时随机生成,删除重装会改变,升级不受影响)")
private String DeviceId;
@ApiModelProperty("成员票据,最大为512字节。")
private String user_ticket;
@ApiModelProperty("user_ticket的有效时间(秒),随user_ticket一起返回")
private String expires_in;
}
@Data
@ApiModel("用户详细信息")
public static class UserDetail{
@ApiModelProperty("返回码")
private String errcode;
@ApiModelProperty("对返回码的文本描述内容")
private String errmsg;
@ApiModelProperty("用户所属企业的corpid")
private String corpid;
@ApiModelProperty("成员UserID")
private String userid;
@ApiModelProperty("成员姓名,此字段从2019年12月30日起,对新创建第三方应用不再返回,2020年6月30日起,对所有历史第三方应用不再返回,第三方页面需要通过通讯录展示组件来展示名字")
private String name;
@ApiModelProperty("性别。0表示未定义,1表示男性,2表示女性")
private Byte gender;
@ApiModelProperty("头像url。仅在用户同意snsapi_privateinfo授权时返回")
private String avatar;
@ApiModelProperty("员工个人二维码(扫描可添加为外部联系人),仅在用户同意snsapi_privateinfo授权时返回")
private String qr_code;
}
}
Loading…
Cancel
Save