16 changed files with 519 additions and 0 deletions
@ -0,0 +1,28 @@ |
|||
package com.epmet.sdt; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 山东通返回结果封装 |
|||
*/ |
|||
@Data |
|||
public class SdtBaseResult { |
|||
|
|||
/** |
|||
* 成功状态码 |
|||
*/ |
|||
public static final Integer SUCCESS_CODE = 0; |
|||
|
|||
private Integer errcode; |
|||
private String errmsg; |
|||
|
|||
/** |
|||
* 请求是否成功 |
|||
* @author wxz |
|||
* @date 2022/11/2 22:43 |
|||
* @return boolean |
|||
*/ |
|||
public boolean success() { |
|||
return (errcode != null && errcode == SUCCESS_CODE) ? true : false; |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
package com.epmet.sdt; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 获取山东通AccessToken接口的返回Result |
|||
*/ |
|||
@Data |
|||
public class SdtGetAccessTokenResult extends SdtBaseResult { |
|||
private String access_token; |
|||
private Long expires_in; |
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.epmet.sdt; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 返回了挺多属性,但是我只取手机号 |
|||
* @ClassName SdtStaffInfoResult |
|||
* @Description TODO |
|||
* @Author wangxianzhang |
|||
* @Date 2022/11/3 10:58 |
|||
*/ |
|||
@Data |
|||
public class SdtStaffDetailResult extends SdtBaseResult { |
|||
private String userid; |
|||
private String name; |
|||
private String mobile; |
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.epmet.sdt; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName SdtStaffInfoResult |
|||
* @Description TODO |
|||
* @Author wangxianzhang |
|||
* @Date 2022/11/3 10:58 |
|||
*/ |
|||
@Data |
|||
public class SdtStaffInfoResult extends SdtBaseResult { |
|||
private String UserId; |
|||
private String DeviceId; |
|||
private String user_ticket; |
|||
private String expires_in; |
|||
} |
@ -0,0 +1,47 @@ |
|||
package com.epmet.controller; |
|||
|
|||
import com.epmet.commons.tools.utils.EpmetRequestHolder; |
|||
import com.epmet.commons.tools.utils.Result; |
|||
import com.epmet.service.SdtService; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
/** |
|||
* 山东通controller |
|||
*/ |
|||
@RestController |
|||
@RequestMapping("sdt") |
|||
public class SdtController { |
|||
|
|||
@Autowired |
|||
private SdtService sdtService; |
|||
|
|||
/** |
|||
* 刷新山东通token |
|||
* @author wxz |
|||
* @date 2022/11/2 22:11 |
|||
* @return Result |
|||
*/ |
|||
@GetMapping("refreshAccessToken") |
|||
public Result refreshAccessToken() { |
|||
sdtService.refreshAccessToken(null); |
|||
return new Result(); |
|||
} |
|||
|
|||
/** |
|||
* 查询山东通AccesToken |
|||
* @author wxz |
|||
* @date 2022/11/3 10:12 |
|||
* |
|||
* * @return Result<String> |
|||
*/ |
|||
@GetMapping("getCachedAccessToken") |
|||
public Result<String> getCachedAccessToken(@RequestParam("customerId") String customerId) { |
|||
String cachedAccessToken = sdtService.getCachedAccessToken(EpmetRequestHolder.getLoginUserCustomerId()); |
|||
return new Result<String>().ok(cachedAccessToken); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package com.epmet.dao; |
|||
|
|||
import com.epmet.commons.mybatis.dao.BaseDao; |
|||
import com.epmet.entity.SdtAppInfoEntity; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
/** |
|||
* 接入山东通app信息 |
|||
* |
|||
* @author generator generator@elink-cn.com |
|||
* @since v1.0.0 2022-11-02 |
|||
*/ |
|||
@Mapper |
|||
public interface SdtAppInfoDao extends BaseDao<SdtAppInfoEntity> { |
|||
|
|||
} |
@ -0,0 +1,54 @@ |
|||
package com.epmet.entity; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
|
|||
import com.epmet.commons.mybatis.entity.BaseEpmetEntity; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* 接入山东通app信息 |
|||
* |
|||
* @author generator generator@elink-cn.com |
|||
* @since v1.0.0 2022-11-02 |
|||
*/ |
|||
@Data |
|||
@EqualsAndHashCode(callSuper=false) |
|||
@TableName("sdt_app_info") |
|||
public class SdtAppInfoEntity extends BaseEpmetEntity { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 客户ID |
|||
*/ |
|||
private String customerId; |
|||
|
|||
/** |
|||
* 组织ID |
|||
*/ |
|||
private String corpId; |
|||
|
|||
/** |
|||
* 秘钥 |
|||
*/ |
|||
private String corpSecret; |
|||
|
|||
/** |
|||
* api地址 |
|||
*/ |
|||
private String apiAddress; |
|||
|
|||
/** |
|||
* 接口调用凭证 |
|||
*/ |
|||
private String accessToken; |
|||
|
|||
/** |
|||
* 何时过期 |
|||
*/ |
|||
private Date expiresAt; |
|||
|
|||
} |
@ -0,0 +1,35 @@ |
|||
package com.epmet.service; |
|||
|
|||
import com.zaxxer.hikari.util.FastList; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName SdtService |
|||
* @Description 山东通相关service |
|||
* @Author wangxianzhang |
|||
* @Date 2022/11/2 22:02 |
|||
*/ |
|||
public interface SdtService { |
|||
|
|||
/** |
|||
* 获取accessToken的url地址 |
|||
* /cgi-bin/gettoken?corpid=id&corpsecret=secrect |
|||
*/ |
|||
String API_GET_ACCESS_TOKEN_URL = "/cgi-bin/gettoken"; |
|||
|
|||
/** |
|||
* 刷新token |
|||
* @author wxz |
|||
* @date 2022/11/2 22:50 |
|||
*/ |
|||
void refreshAccessToken(String customerId); |
|||
|
|||
/** |
|||
* 获取缓存的AccessToken |
|||
* @author wxz |
|||
* @date 2022/11/2 22:56 |
|||
* |
|||
* * @return String |
|||
*/ |
|||
String getCachedAccessToken(String customerId); |
|||
} |
@ -0,0 +1,156 @@ |
|||
package com.epmet.service.impl; |
|||
|
|||
import com.alibaba.fastjson.JSON; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.epmet.commons.tools.redis.RedisKeys; |
|||
import com.epmet.commons.tools.redis.RedisUtils; |
|||
import com.epmet.commons.tools.utils.HttpClientManager; |
|||
import com.epmet.commons.tools.utils.Result; |
|||
import com.epmet.dao.SdtAppInfoDao; |
|||
import com.epmet.entity.SdtAppInfoEntity; |
|||
import com.epmet.sdt.SdtGetAccessTokenResult; |
|||
import com.epmet.service.SdtService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.*; |
|||
|
|||
/** |
|||
* @ClassName SdtServiceImpl |
|||
* @Description 山东通相关service |
|||
* @Author wangxianzhang |
|||
* @Date 2022/11/2 22:03 |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class SdtServiceImpl implements SdtService { |
|||
|
|||
@Autowired |
|||
private SdtAppInfoDao sdtAppInfoDao; |
|||
|
|||
@Autowired |
|||
private RedisUtils redisUtils; |
|||
|
|||
/** |
|||
* 刷新accessToken |
|||
* @author wxz |
|||
* @date 2022/11/2 22:53 |
|||
*/ |
|||
@Override |
|||
public void refreshAccessToken(String customerId) { |
|||
List<SdtAppInfoEntity> appInfos; |
|||
|
|||
if (StringUtils.isBlank(customerId)) { |
|||
// 没传递customerId,刷新所有
|
|||
appInfos = sdtAppInfoDao.selectList(new QueryWrapper<>()); |
|||
} else { |
|||
// 传递了customerId,只刷新该客户的
|
|||
LambdaQueryWrapper<SdtAppInfoEntity> query = new LambdaQueryWrapper<>(); |
|||
query.eq(SdtAppInfoEntity::getCustomerId, customerId); |
|||
appInfos = sdtAppInfoDao.selectList(query); |
|||
} |
|||
|
|||
appInfos.stream().forEach(app -> { |
|||
Date now = new Date(); |
|||
String apiAddress = app.getApiAddress(); |
|||
String customerIdInner = app.getCustomerId(); |
|||
|
|||
HashMap<String, Object> params = new HashMap<>(); |
|||
params.put("corpid", app.getCorpId()); |
|||
params.put("corpsecret", app.getCorpSecret()); |
|||
Result<String> stringResult = HttpClientManager.getInstance().sendGet(apiAddress + API_GET_ACCESS_TOKEN_URL, params); |
|||
if (!stringResult.success()) { |
|||
// 请求有问题
|
|||
log.error("【山东通】刷新accessToken出现异常:{}", stringResult.getMsg()); |
|||
return; |
|||
} |
|||
|
|||
SdtGetAccessTokenResult sdtResult = JSON.parseObject(stringResult.getMsg(), SdtGetAccessTokenResult.class); |
|||
if (!sdtResult.success()) { |
|||
log.error("【山东通】刷新accessToken失败:{}", sdtResult.getErrmsg()); |
|||
return; |
|||
} |
|||
|
|||
String access_token = sdtResult.getAccess_token(); |
|||
Long expires_in = sdtResult.getExpires_in(); |
|||
|
|||
SdtAppInfoEntity updateEntity = new SdtAppInfoEntity(); |
|||
updateEntity.setId(app.getId()); |
|||
updateEntity.setAccessToken(access_token); |
|||
updateEntity.setExpiresAt(getExpireAt(now, expires_in)); |
|||
sdtAppInfoDao.updateById(updateEntity); |
|||
|
|||
// token刷新了以后,要刷新缓存中的token,这样下次才能获取到最新的token
|
|||
String key = RedisKeys.getOpenApiAccessTokenKey(customerIdInner); |
|||
|
|||
redisUtils.set(key, access_token, expires_in); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 计算过期时间 |
|||
* @author wxz |
|||
* @date 2022/11/2 23:22 |
|||
* * @param startTime |
|||
* @param expires_in |
|||
* * @return Date |
|||
*/ |
|||
private Date getExpireAt(Date startTime, Long expires_in) { |
|||
Calendar calendar = Calendar.getInstance(); |
|||
calendar.setTime(startTime); |
|||
calendar.add(Calendar.SECOND, expires_in.intValue()); |
|||
return calendar.getTime(); |
|||
} |
|||
|
|||
/** |
|||
* 还有多少秒过期 |
|||
* @author wxz |
|||
* @date 2022/11/3 10:08 |
|||
* * @param expireAt |
|||
* * @return Long |
|||
*/ |
|||
private Long getExpireIn(Date expireAt) { |
|||
return expireAt.getTime() - System.currentTimeMillis(); |
|||
} |
|||
|
|||
/** |
|||
* 获取缓存的AccessToken |
|||
* @author wxz |
|||
* @date 2022/11/2 22:56 |
|||
* |
|||
* * @return String |
|||
*/ |
|||
@Override |
|||
public String getCachedAccessToken(String customerId) { |
|||
String key = RedisKeys.getOpenApiAccessTokenKey(customerId); |
|||
String accessToken = redisUtils.getString(key); |
|||
if (StringUtils.isNotBlank(accessToken)) { |
|||
return accessToken; |
|||
} |
|||
|
|||
// db中查询
|
|||
LambdaQueryWrapper<SdtAppInfoEntity> query = new LambdaQueryWrapper<>(); |
|||
query.eq(SdtAppInfoEntity::getCustomerId, customerId); |
|||
SdtAppInfoEntity sdtAppInfoEntity = sdtAppInfoDao.selectOne(query); |
|||
|
|||
if (sdtAppInfoEntity == null) { |
|||
log.error("【查询山东通AccessToken】失败,原因:该客户id没有配置山东通相关信息"); |
|||
return null; |
|||
} |
|||
|
|||
accessToken = sdtAppInfoEntity.getAccessToken(); |
|||
Date expiresAt = sdtAppInfoEntity.getExpiresAt(); |
|||
|
|||
if (StringUtils.isNotBlank(accessToken)) { |
|||
redisUtils.set(key, accessToken, getExpireIn(expiresAt)); |
|||
return accessToken; |
|||
} else { |
|||
// 配置了appInfo,但是没有accessToken,刷新token,刷新缓存,然后重新从缓存中取
|
|||
refreshAccessToken(customerId); |
|||
return redisUtils.getString(key); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
create table sdt_app_info |
|||
( |
|||
`ID` varchar(64) NOT NULL COMMENT '主键', |
|||
`CUSTOMER_ID` varchar(64) NOT NULL COMMENT '客户ID', |
|||
`CORPID` varchar(32) not null comment '组织ID', |
|||
`CORPSECRET` varchar(64) not null comment '秘钥', |
|||
`ACCESS_TOKEN` varchar(512) not null comment '接口调用凭证', |
|||
`API_ADDRESS` varchar(128) not null comment 'api地址', |
|||
`EXPIRES_AT` datetime not null comment '何时过期', |
|||
`DEL_FLAG` int(11) NOT NULL COMMENT '删除标识:0.未删除 1.已删除', |
|||
`REVISION` int(11) NOT NULL COMMENT '乐观锁', |
|||
`CREATED_BY` varchar(64) NOT NULL COMMENT '创建人', |
|||
`CREATED_TIME` datetime NOT NULL COMMENT '创建时间', |
|||
`UPDATED_BY` varchar(64) NOT NULL COMMENT '更新人', |
|||
`UPDATED_TIME` datetime NOT NULL COMMENT '更新时间', |
|||
PRIMARY KEY (`ID`) |
|||
) ENGINE = InnoDB |
|||
DEFAULT CHARSET = utf8mb4 COMMENT ='接入山东通app信息'; |
|||
|
@ -0,0 +1,22 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
|
|||
<mapper namespace="com.epmet.dao.SdtAppInfoDao"> |
|||
|
|||
<resultMap type="com.epmet.entity.SdtAppInfoEntity" id="sdtAppInfoMap"> |
|||
<result property="id" column="ID"/> |
|||
<result property="customerId" column="CUSTOMER_ID"/> |
|||
<result property="corpId" column="CORP_ID"/> |
|||
<result property="corpSecret" column="CORP_SECRET"/> |
|||
<result property="accessToken" column="ACCESS_TOKEN"/> |
|||
<result property="expiresAt" column="EXPIRES_AT"/> |
|||
<result property="delFlag" column="DEL_FLAG"/> |
|||
<result property="revision" column="REVISION"/> |
|||
<result property="createdBy" column="CREATED_BY"/> |
|||
<result property="createdTime" column="CREATED_TIME"/> |
|||
<result property="updatedBy" column="UPDATED_BY"/> |
|||
<result property="updatedTime" column="UPDATED_TIME"/> |
|||
</resultMap> |
|||
|
|||
|
|||
</mapper> |
Loading…
Reference in new issue