package com.ruoyi.auth.service;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
|
import com.ruoyi.auth.config.QywxInnerConfig;
|
import com.ruoyi.auth.utils.RestUtils;
|
import com.ruoyi.common.core.constant.Constants;
|
import com.ruoyi.common.core.exception.ServiceException;
|
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.system.api.model.AgentConfigVo;
|
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.lang3.ObjectUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.redis.cache.RedisCache;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.stereotype.Service;
|
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
import java.util.Calendar;
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.concurrent.TimeUnit;
|
|
@Service
|
public class QywxInnerService {
|
|
private final static Logger logger = LoggerFactory.getLogger("QywxInnerService");
|
|
@Autowired
|
private QywxInnerConfig qywxInnerConfig;
|
|
@Autowired
|
private StringRedisTemplate redisTemplate;
|
|
|
public String getAccessToken(){
|
|
String accessToken = redisTemplate.opsForValue().get(Constants.QY_WX_ACCESS_TOKEN_KEY);
|
if(!StringUtils.isEmpty(accessToken)){
|
return accessToken;
|
}
|
|
String corpId = qywxInnerConfig.getCorpId();
|
String agentSecret = qywxInnerConfig.getAgentSecret();
|
|
String accessTokenUrl = String.format(qywxInnerConfig.getAccessTokenUrl(), corpId, agentSecret);
|
JSONObject response = RestUtils.get(accessTokenUrl);
|
|
// 获取错误日志
|
if(response.containsKey(Constants.QY_WX_ERR_CODE) && response.getInteger(Constants.QY_WX_ERR_CODE) != 0){
|
logger.error(response.toString());
|
throw new ServiceException("获取企业微信ACCESS_TOKEN异常");
|
}
|
accessToken = response.getString(Constants.QY_WX_ACCESS_TOKEN);
|
Long expiresIn = response.getLong(Constants.QY_WX_EXPIRES_IN);
|
expiresIn = expiresIn - 100;
|
redisTemplate.opsForValue().set(Constants.QY_WX_ACCESS_TOKEN_KEY, accessToken, expiresIn, TimeUnit.SECONDS);
|
|
return accessToken;
|
}
|
|
|
//********************************** H5应用 Oauth *************************//
|
/**
|
* 构造网页授权链接
|
* @param oauthRedirectUrl
|
* @return
|
*/
|
public String getOauthUrl(String oauthRedirectUrl){
|
// 应用授权作用域。
|
// snsapi_base:静默授权,可获取成员的基础信息(UserId与DeviceId);
|
// snsapi_userinfo:静默授权,可获取成员的详细信息,但不包含手机、邮箱等敏感信息;
|
// snsapi_privateinfo:手动授权,可获取成员的详细信息,包含手机、邮箱等敏感信息(已不再支持获取手机号/邮箱)。
|
String corpId = qywxInnerConfig.getCorpId();
|
String state = qywxInnerConfig.getAuthorizeState();
|
String agentId = qywxInnerConfig.getAgentId();
|
|
// 构造网页授权链接 redirect_uri
|
return String.format(qywxInnerConfig.getOauthUrl(), corpId, oauthRedirectUrl, agentId, state);
|
}
|
|
/**
|
* 获取访问用户身份
|
* 获取访问用户敏感信息
|
* @param code
|
* @return
|
*/
|
public JSONObject getOauthUser(String code) {
|
String accessToken = getAccessToken();
|
|
// 获取访问用户身份
|
String getOauthUrl = String.format(qywxInnerConfig.getOauthUserUrl(), accessToken, code);
|
JSONObject response = RestUtils.get(getOauthUrl);
|
if(response.containsKey(Constants.QY_WX_ERR_CODE) && response.getInteger(Constants.QY_WX_ERR_CODE) != 0){
|
logger.error(response.toString());
|
throw new ServiceException("获取企业微信信息异常");
|
}
|
logger.info("----------------userinfo-------------");
|
logger.info(response.toString());
|
|
//获取通讯录用户详情get
|
String userId = response.getString(Constants.QY_WX_USER_ID);
|
// 成员票据,最大为512字节,有效期为1800s。 scope为snsapi_privateinfo,获取访问用户敏感信息
|
String userTicket = response.getString(Constants.QY_WX_USER_TICKET);
|
|
// 获取用户详情 包含部门信息
|
// String url = String.format(qywxInnerConfig.getUserDetailUrl(),accessToken,userId);
|
// 获取访问用户敏感信息
|
String url = String.format(qywxInnerConfig.getUserDetailUrlAuth(), accessToken);
|
JSONObject json = new JSONObject();
|
json.put(Constants.QY_WX_USER_TICKET, userTicket);
|
JSONObject detailResponse = RestUtils.post(url, json);
|
//获取错误日志
|
if(detailResponse.containsKey(Constants.QY_WX_ERR_CODE) && detailResponse.getInteger(Constants.QY_WX_ERR_CODE) != 0){
|
logger.error(detailResponse.toString());
|
throw new ServiceException("获取企业微信信息异常");
|
}
|
logger.info("----------------userinfo detail -------------");
|
logger.info(detailResponse.toString());
|
|
return detailResponse;
|
}
|
|
|
|
public AgentConfigVo getAgentConfig(String url) {
|
|
AgentConfigVo agentConfigVo = new AgentConfigVo();
|
agentConfigVo.setAgentid(qywxInnerConfig.getAgentId());
|
agentConfigVo.setCorpid(qywxInnerConfig.getCorpId());
|
|
//临时票据
|
String ticket = getJsApiTicket();
|
if (StringUtils.isEmpty(ticket)) {
|
throw new ServiceException("获取票据异常");
|
}
|
//当前时间戳 转成秒
|
long timestamp = System.currentTimeMillis() / 1000;
|
//随机字符串
|
String nonceStr = Constants.QY_WX_NONCE_STR;
|
String signature = getSignature(ticket, nonceStr, timestamp, url);
|
agentConfigVo.setTimestamp(String.valueOf(timestamp));
|
agentConfigVo.setNonceStr(nonceStr);
|
agentConfigVo.setSignature(signature);
|
|
return agentConfigVo;
|
}
|
|
|
private String getSignature(String ticket, String nonceStr, long timestamp, String url) {
|
String unEncryptStrBase = "jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s";
|
try {
|
String unEncryptStr = String.format(unEncryptStrBase, ticket, nonceStr, timestamp, url);
|
|
logger.info("----------------unEncryptStr-------------");
|
logger.info(unEncryptStr);
|
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
// 调用digest方法,进行加密操作
|
byte[] cipherBytes = digest.digest(unEncryptStr.getBytes());
|
String encryptStr = Hex.encodeHexString(cipherBytes);
|
logger.info("----------------getSignature-------------");
|
logger.info(encryptStr);
|
return encryptStr;
|
} catch (NoSuchAlgorithmException e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
|
/**
|
* 获取ticket
|
* @paran type
|
* @return
|
*/
|
public String getJsApiTicket() {
|
String accessToken = getAccessToken();
|
String ticket = redisTemplate.opsForValue().get(Constants.QY_WX_TICKET_KEY);
|
if(!StringUtils.isEmpty(ticket)){
|
return ticket;
|
}
|
String url = String.format(qywxInnerConfig.getJsapiTicketAgentUrl(), accessToken);
|
|
JSONObject response = RestUtils.get(url);
|
if(response.containsKey(Constants.QY_WX_ERR_CODE) && response.getInteger(Constants.QY_WX_ERR_CODE) != 0){
|
logger.error(response.toString());
|
throw new ServiceException("获取企业微信信息异常");
|
}
|
|
ticket = response.getString(Constants.QY_WX_TICKET);
|
Long expiresIn = response.getLong(Constants.QY_WX_EXPIRES_IN);
|
expiresIn = expiresIn - 100;
|
redisTemplate.opsForValue().set(Constants.QY_WX_TICKET_KEY, ticket, expiresIn, TimeUnit.SECONDS);
|
|
return ticket;
|
}
|
}
|