forked from luyan/epmet-cloud-lingshan
				
			
				 59 changed files with 1492 additions and 22 deletions
			
			
		| @ -0,0 +1,21 @@ | |||
| package com.epmet.constant; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/19 上午10:26 | |||
|  */ | |||
| public interface SsoConstant { | |||
| 
 | |||
|     /** | |||
|      * 酒城e通appId | |||
|      */ | |||
|     String WINE_CITY_E_OPEN_APP_ID = "64929543"; | |||
| 
 | |||
|     String USER_INFO_IS_NULL = "【jcetApiService.getUserInfoByTicket(formDTO.getTicket()】结果为空......"; | |||
| 
 | |||
|     String INSERT_UPDATE_USER_FAILURE = "新增或更新user_weChat失败......"; | |||
| 
 | |||
|     String USER_ID_IS_NULL = "userId为空,生成token失败......"; | |||
|     String CUSTOMER_ID_IS_NULL = "customerId为空,缓存放置token失败......"; | |||
| 
 | |||
| } | |||
| @ -0,0 +1,53 @@ | |||
| package com.epmet.controller; | |||
| 
 | |||
| import com.epmet.commons.thirdplat.apiservice.jcet.JcetApiService; | |||
| import com.epmet.commons.thirdplat.bean.ThirdPlatUserInfo; | |||
| import com.epmet.commons.tools.utils.Result; | |||
| import com.epmet.commons.tools.validator.ValidatorUtils; | |||
| import com.epmet.dto.form.SsoLoginFormDTO; | |||
| import com.epmet.dto.result.SsoLoginResultDTO; | |||
| import com.epmet.service.SsoService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/18 下午4:33 | |||
|  */ | |||
| @RestController | |||
| @RequestMapping("sso") | |||
| public class SsoController { | |||
| 
 | |||
|     @Autowired | |||
|     private SsoService ssoService; | |||
| 
 | |||
|     @Autowired | |||
|     private JcetApiService jcetApiService; | |||
| 
 | |||
|     /** | |||
|      * @Description  0、入口:得到token | |||
|      * @Param formDTO | |||
|      * @author zxc | |||
|      * @date 2021/1/18 下午4:59 | |||
|      */ | |||
|     @PostMapping("resi/login") | |||
|     public Result<SsoLoginResultDTO> ssoLogin(@RequestBody SsoLoginFormDTO formDTO){ | |||
|         ValidatorUtils.validateEntity(formDTO, SsoLoginFormDTO.SsoLoginForm.class); | |||
|         return new Result<SsoLoginResultDTO>().ok(ssoService.ssoLogin(formDTO)); | |||
|     } | |||
| 
 | |||
|     @PostMapping("test") | |||
|     public Result<ThirdPlatUserInfo> testssoLogin(){ | |||
|         ThirdPlatUserInfo userInfoByTicket = null; | |||
|         try { | |||
|             userInfoByTicket = jcetApiService.getUserInfoByTicket("ssoTicket-vYtMRuXAQZri3wpA2vyq5D8n3Q9oO7ui"); | |||
|         } catch (Exception e) { | |||
|             e.printStackTrace(); | |||
|         } | |||
|         return new Result<ThirdPlatUserInfo>().ok(userInfoByTicket); | |||
|     } | |||
| 
 | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| package com.epmet.dto.form; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| import javax.validation.constraints.NotBlank; | |||
| import java.io.Serializable; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/18 下午4:43 | |||
|  */ | |||
| @Data | |||
| public class SsoLoginFormDTO implements Serializable { | |||
| 
 | |||
|     private static final long serialVersionUID = -6543952487970013031L; | |||
| 
 | |||
|     public interface SsoLoginForm{} | |||
| 
 | |||
|     /** | |||
|      *  sso票据,有效期为300秒 | |||
|      */ | |||
|     @NotBlank(message = "sso票据不能为空",groups = SsoLoginForm.class) | |||
|     private String ticket; | |||
| 
 | |||
|     /** | |||
|      * 三方平台应用AppId | |||
|      */ | |||
|     @NotBlank(message = "三方平台应用AppId不能为空",groups = SsoLoginForm.class) | |||
|     private String appId; | |||
| 
 | |||
|     /** | |||
|      * app类型 resi;居民段,work:工作端 | |||
|      */ | |||
|     @NotBlank(message = "app不能为空",groups = SsoLoginForm.class) | |||
|     private String app; | |||
| 
 | |||
|     @NotBlank(message = "client不能为空",groups = SsoLoginForm.class) | |||
|     private String client; | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| package com.epmet.dto.result; | |||
| 
 | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| 
 | |||
| import java.io.Serializable; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/18 下午4:45 | |||
|  */ | |||
| @Data | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| public class SsoLoginResultDTO implements Serializable { | |||
| 
 | |||
|     private static final long serialVersionUID = 3491079788196180035L; | |||
| 
 | |||
|     private String token = ""; | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| package com.epmet.redis; | |||
| 
 | |||
| import cn.hutool.core.bean.BeanUtil; | |||
| import com.epmet.commons.tools.redis.RedisKeys; | |||
| import com.epmet.commons.tools.redis.RedisUtils; | |||
| import com.epmet.commons.tools.security.dto.TokenDto; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| 
 | |||
| import java.util.Map; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/18 下午5:09 | |||
|  */ | |||
| @Component | |||
| public class SsoRedis { | |||
| 
 | |||
|     @Autowired | |||
|     private RedisUtils redisUtils; | |||
| 
 | |||
|     /** | |||
|      * @Description  token放入缓存 | |||
|      * @Param user | |||
|      * @Param expire | |||
|      * @author zxc | |||
|      * @date 2021/1/18 下午5:10 | |||
|      */ | |||
|     public void set(TokenDto user, long expire) { | |||
|         if (user == null) { | |||
|             return; | |||
|         } | |||
|         String key = RedisKeys.getCpUserKey(user.getApp(), user.getClient(), user.getUserId()); | |||
|         //bean to map
 | |||
|         Map<String, Object> map = BeanUtil.beanToMap(user, false, true); | |||
|         redisUtils.hMSet(key, map, expire); | |||
|     } | |||
| 
 | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| package com.epmet.service; | |||
| 
 | |||
| import com.epmet.dto.form.SsoLoginFormDTO; | |||
| import com.epmet.dto.result.SsoLoginResultDTO; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/18 下午4:34 | |||
|  */ | |||
| public interface SsoService { | |||
| 
 | |||
|     /** | |||
|      * @Description  0、入口:得到token | |||
|      * @Param formDTO | |||
|      * @author zxc | |||
|      * @date 2021/1/18 下午4:59 | |||
|      */ | |||
|     SsoLoginResultDTO ssoLogin(SsoLoginFormDTO formDTO); | |||
| 
 | |||
| } | |||
| @ -0,0 +1,185 @@ | |||
| package com.epmet.service.impl; | |||
| 
 | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.epmet.commons.thirdplat.apiservice.AbstractApiService; | |||
| import com.epmet.commons.thirdplat.bean.ThirdPlatUserInfo; | |||
| import com.epmet.commons.tools.exception.EpmetErrorCode; | |||
| import com.epmet.commons.tools.exception.RenException; | |||
| import com.epmet.commons.tools.security.dto.TokenDto; | |||
| import com.epmet.commons.tools.utils.*; | |||
| import com.epmet.dto.PaCustomerDTO; | |||
| import com.epmet.dto.UserDTO; | |||
| import com.epmet.dto.form.ApiServiceFormDTO; | |||
| import com.epmet.dto.form.SsoLoginFormDTO; | |||
| import com.epmet.dto.form.UserInfoFormDTO; | |||
| import com.epmet.dto.result.SsoLoginResultDTO; | |||
| import com.epmet.dto.result.ThirdplatApiserviceResultDTO; | |||
| import com.epmet.feign.EpmetUserOpenFeignClient; | |||
| import com.epmet.feign.OperCrmOpenFeignClient; | |||
| import com.epmet.jwt.JwtTokenProperties; | |||
| import com.epmet.jwt.JwtTokenUtils; | |||
| import com.epmet.redis.SsoRedis; | |||
| import com.epmet.service.SsoService; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| 
 | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/18 下午4:35 | |||
|  */ | |||
| @Service | |||
| @Slf4j | |||
| public class SsoServiceImpl implements SsoService { | |||
| 
 | |||
|     Logger logger = LoggerFactory.getLogger(getClass()); | |||
| 
 | |||
|     @Autowired | |||
|     private SsoRedis ssoRedis; | |||
| 
 | |||
|     @Autowired | |||
|     private JwtTokenUtils jwtTokenUtils; | |||
| 
 | |||
|     @Autowired | |||
|     private JwtTokenProperties jwtTokenProperties; | |||
| 
 | |||
|     @Autowired | |||
|     private EpmetUserOpenFeignClient epmetUserOpenFeignClient; | |||
| 
 | |||
|     @Autowired | |||
|     private OperCrmOpenFeignClient operCrmOpenFeignClient; | |||
| 
 | |||
|     /** | |||
|      * @Description  0、入口:得到token | |||
|      * @Param formDTO | |||
|      * @author zxc | |||
|      * @date 2021/1/18 下午4:59 | |||
|      */ | |||
|     @Override | |||
|     public SsoLoginResultDTO ssoLogin(SsoLoginFormDTO formDTO) { | |||
|         String customerId = getCustomerId(formDTO.getAppId()); | |||
|         String userId = ""; | |||
| 
 | |||
|         Result<ThirdplatApiserviceResultDTO> apiServiceResult = operCrmOpenFeignClient.getApiServiceByCustomerId(new ApiServiceFormDTO(customerId)); | |||
|         if (!apiServiceResult.success()) { | |||
|             throw new RenException("【SSO登录】调用OperCrm获取ApiService接口失败:", apiServiceResult.getInternalMsg()); | |||
|         } | |||
| 
 | |||
|         if (apiServiceResult.getData() == null || StringUtils.isBlank(apiServiceResult.getData().getApiServiceName())) { | |||
|             throw new RenException("【SSO登录】调用OperCrm获取ApiService,查询到的结果为空:", apiServiceResult.toString()); | |||
|         } | |||
| 
 | |||
|         ThirdPlatUserInfo userInfo; | |||
|         try { | |||
|             AbstractApiService apiService = (AbstractApiService) SpringContextUtils.getBean(apiServiceResult.getData().getApiServiceName()); | |||
|             userInfo = apiService.getUserInfoByTicket(formDTO.getTicket()); | |||
|         } catch (Exception e) { | |||
|             throw new RenException(e.getMessage()); | |||
|         } | |||
| 
 | |||
|         if (null == userInfo){ | |||
|             throw new RenException(EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getCode(), | |||
|                     "【SSO登录】调用第三方平台查询用户信息失败,用户信息为空"); | |||
|         } | |||
|         UserInfoFormDTO userInfoFormDTO = new UserInfoFormDTO(); | |||
|         userInfoFormDTO.setApp(formDTO.getApp()); | |||
|         userInfoFormDTO.setUid(userInfo.getOpenId()); | |||
|         userInfoFormDTO.setName(userInfo.getName()); | |||
|         userInfoFormDTO.setMobile(userInfo.getMobile()); | |||
| 
 | |||
|         Result<UserDTO> userDTOResult = epmetUserOpenFeignClient.saveUserInfo(userInfoFormDTO); | |||
|         if (!userDTOResult.success()){ | |||
|             throw new RenException("【SSO登录】新增或更新user_weChat失败"); | |||
|         } | |||
|         userId = userDTOResult.getData().getId(); | |||
| 
 | |||
|         if (StringUtils.isBlank(userId)){ | |||
|             throw new RenException("【SSO登录】userId为空,生成token失败"); | |||
|         } | |||
|         //生成业务token
 | |||
|         String token = this.generateToken(formDTO.getApp(),formDTO.getClient(), userId); | |||
|         //存放Redis
 | |||
| 
 | |||
|         if (StringUtils.isBlank(customerId)){ | |||
|             throw new RenException("【SSO登录】customerId为空,缓存放置token失败"); | |||
|         } | |||
|         this.disposeTokenDto(formDTO, userId, token, customerId); | |||
|         return new SsoLoginResultDTO(token); | |||
|     } | |||
| 
 | |||
|     /** | |||
|      * @Description  token放缓存 | |||
|      * @Param formDTO | |||
|      * @Param userId | |||
|      * @Param token | |||
|      * @Param customerId | |||
|      * @author zxc | |||
|      * @date 2021/1/18 下午5:32 | |||
|      */ | |||
|     public void disposeTokenDto(SsoLoginFormDTO formDTO, String userId, String token, String customerId){ | |||
|         int expire = jwtTokenProperties.getExpire(); | |||
|         TokenDto tokenDto = new TokenDto(); | |||
|         tokenDto.setCustomerId(customerId); | |||
|         tokenDto.setApp(formDTO.getApp()); | |||
|         tokenDto.setClient(formDTO.getClient()); | |||
|         tokenDto.setUserId(userId); | |||
|         tokenDto.setToken(token); | |||
|         tokenDto.setUpdateTime(System.currentTimeMillis()); | |||
|         tokenDto.setExpireTime(jwtTokenUtils.getExpiration(token).getTime()); | |||
|         ssoRedis.set(tokenDto, expire); | |||
|         log.info("截止时间:" + DateUtils.format(jwtTokenUtils.getExpiration(token), "yyyy-MM-dd HH:mm:ss")); | |||
|     } | |||
| 
 | |||
|     /** | |||
|      * @Description  居民端登陆生成业务token的key | |||
|      * @Param app | |||
|      * @Param client | |||
|      * @Param userId | |||
|      * @author zxc | |||
|      * @date 2021/1/18 下午5:14 | |||
|      */ | |||
|     private String generateToken(String app,String client, String userId) { | |||
|         Map<String, Object> map = new HashMap<>(16); | |||
|         map.put("app", app); | |||
|         map.put("client", client); | |||
|         map.put("userId", userId); | |||
|         String token = jwtTokenUtils.createToken(map); | |||
|         log.info("app:" + app + ";client:" + client + ";userId:" + userId + ";生成token[" + token + "]"); | |||
|         return token; | |||
|     } | |||
| 
 | |||
|     /** | |||
|      * @Description  获取customerId | |||
|      * @Param appId | |||
|      * @author zxc | |||
|      * @date 2021/1/19 下午1:47 | |||
|      */ | |||
|     public String getCustomerId(String appId){ | |||
|         JSONObject jsonObject = new JSONObject(); | |||
|         String customerMsgUrl = "https://epmet-cloud.elinkservice.cn/api/third/customermp/getcustomermsg/"; | |||
|         String data = HttpClientManager.getInstance().sendPostByJSON(customerMsgUrl + appId, JSON.toJSONString(jsonObject)).getData(); | |||
|         log.info("调用third服务,根据appId查询客户信息:httpclient->url:" + customerMsgUrl + ",结果->" + data); | |||
|         JSONObject toResult = JSON.parseObject(data); | |||
|         Result mapToResult = ConvertUtils.mapToEntity(toResult, Result.class); | |||
|         if (null != toResult.get("code")) { | |||
|             mapToResult.setCode(((Integer) toResult.get("code")).intValue()); | |||
|         } | |||
|         if (!mapToResult.success()) { | |||
|             log.error(String.format("根据appId查询客户信息失败,对应appId->" + appId)); | |||
|             throw new RenException(mapToResult.getMsg()); | |||
|         } | |||
|         Object publicCustomerResultDTO = mapToResult.getData(); | |||
|         JSONObject json = JSON.parseObject(publicCustomerResultDTO.toString()); | |||
|         Map<String, Object> map = (Map) json.get("customer"); | |||
|         PaCustomerDTO customer = ConvertUtils.mapToEntity(map, PaCustomerDTO.class); | |||
|         log.info("小程序登陆third服务获取客户用户信息PaCustomerDTO->" + customer); | |||
|         return customer.getId(); | |||
|     } | |||
| } | |||
| @ -0,0 +1,22 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | |||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
|     <parent> | |||
|         <artifactId>epmet-commons</artifactId> | |||
|         <groupId>com.epmet</groupId> | |||
|         <version>2.0.0</version> | |||
|     </parent> | |||
|     <modelVersion>4.0.0</modelVersion> | |||
| 
 | |||
|     <artifactId>epmet-commons-thirdplat</artifactId> | |||
| 
 | |||
|     <dependencies> | |||
|         <dependency> | |||
|             <groupId>com.epmet</groupId> | |||
|             <artifactId>epmet-commons-tools</artifactId> | |||
|             <version>2.0.0</version> | |||
|         </dependency> | |||
|     </dependencies> | |||
| 
 | |||
| </project> | |||
| @ -0,0 +1,36 @@ | |||
| package com.epmet.commons.thirdplat; | |||
| 
 | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.epmet.commons.thirdplat.dto.form.jcet.SsoTicketFormDTO; | |||
| import com.epmet.commons.thirdplat.dto.form.jcet.SsoTokenFormDTO; | |||
| import com.epmet.commons.thirdplat.encrypt.SignUtils; | |||
| 
 | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| 
 | |||
| public class DemoApp { | |||
| 
 | |||
|     private static String appid = "soXDEoM1"; | |||
|     private static String appsecret = "V7ea0KnlYt7eSyzc"; | |||
| 
 | |||
|     public static void main(String[] args) throws UnsupportedEncodingException { | |||
| 
 | |||
|         //SsoToken ssoToken = new SsoToken();
 | |||
|         //ssoToken.setSsoToken("wxz");
 | |||
| 
 | |||
|         SsoTicketFormDTO ssoTicket = new SsoTicketFormDTO(); | |||
|         ssoTicket.setSsoTicket("wxz"); | |||
| 
 | |||
|         int bodyLength = JSON.toJSONString(ssoTicket).getBytes("utf-8").length; | |||
| 
 | |||
|         Map<String, Object> headers = new HashMap(); | |||
|         long timestamp = System.currentTimeMillis(); | |||
|         headers.put("openTimestamp", String.valueOf(timestamp)); | |||
|         headers.put("openAppId", appid); | |||
|         String encryptContent = appid + timestamp + bodyLength; | |||
|         headers.put("openSign", SignUtils.generate(encryptContent, appsecret)); | |||
|         System.out.println(headers); | |||
|     } | |||
| 
 | |||
| } | |||
| @ -0,0 +1,45 @@ | |||
| package com.epmet.commons.thirdplat.apiservice; | |||
| 
 | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.epmet.commons.thirdplat.bean.ThirdPlatUserInfo; | |||
| import com.epmet.commons.thirdplat.dto.result.jcet.JcetResult; | |||
| import com.epmet.commons.thirdplat.properties.ThirdplatProps; | |||
| import com.epmet.commons.tools.exception.EpmetErrorCode; | |||
| import com.epmet.commons.tools.exception.RenException; | |||
| import com.epmet.commons.tools.utils.Result; | |||
| 
 | |||
| public abstract class AbstractApiService { | |||
| 
 | |||
|     protected ThirdplatProps thirdplatProps; | |||
| 
 | |||
|     /** | |||
|      * 通过ticket查询用户信息 | |||
|      * @param ticket | |||
|      * @return | |||
|      * @throws Exception | |||
|      */ | |||
|     public abstract ThirdPlatUserInfo getUserInfoByTicket(String ticket) throws Exception; | |||
| 
 | |||
|     /** | |||
|      * @Description 解析请求结果 | |||
|      * @return | |||
|      * @author wxz | |||
|      * @date 2021.01.19 09:53 | |||
|     */ | |||
|     protected <R> R parseResult(Result<String> thResult, Class<R> resultType) { | |||
|         if (!thResult.success()) { | |||
|             throw new RenException(EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getCode(), | |||
|                     EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getMsg().concat(":").concat(thResult.getInternalMsg())); | |||
|         } | |||
| 
 | |||
|         JcetResult jcetResult = JSON.parseObject(thResult.getData(), JcetResult.class); | |||
|         if (!jcetResult.isSuccess()) { | |||
|             throw new RenException(EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getCode(), | |||
|                     jcetResult.getMsg().concat(",错误码:") + jcetResult.getCode()); | |||
|         } | |||
| 
 | |||
|         JSONObject jo = (JSONObject) jcetResult.getData(); | |||
|         return jo.toJavaObject(resultType); | |||
|     } | |||
| } | |||
| @ -0,0 +1,98 @@ | |||
| package com.epmet.commons.thirdplat.apiservice.jcet; | |||
| 
 | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.epmet.commons.thirdplat.apiservice.AbstractApiService; | |||
| import com.epmet.commons.thirdplat.bean.ThirdPlatUserInfo; | |||
| import com.epmet.commons.thirdplat.constants.JcetConstants; | |||
| import com.epmet.commons.thirdplat.dto.form.jcet.SsoTicketFormDTO; | |||
| import com.epmet.commons.thirdplat.dto.result.jcet.JcetUserInfoResultDTO; | |||
| import com.epmet.commons.thirdplat.encrypt.SignUtils; | |||
| import com.epmet.commons.thirdplat.properties.JcetThirdplatProps; | |||
| import com.epmet.commons.thirdplat.properties.ThirdplatProps; | |||
| import com.epmet.commons.tools.utils.HttpClientManager; | |||
| import com.epmet.commons.tools.utils.Result; | |||
| 
 | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| 
 | |||
| public class JcetApiService extends AbstractApiService { | |||
| 
 | |||
|     private JcetThirdplatProps jcetThirdplatProps; | |||
| 
 | |||
|     public JcetApiService(ThirdplatProps props) { | |||
|         this.thirdplatProps = props; | |||
|         jcetThirdplatProps = props.getJcet(); | |||
|     } | |||
| 
 | |||
|     /** | |||
|      * @return | |||
|      * @Description 通过第三方平台ticket获取用户信息 | |||
|      * @author wxz | |||
|      * @date 2021.01.19 10:26 | |||
|      */ | |||
|     public ThirdPlatUserInfo getUserInfoByTicket(String ticket) throws UnsupportedEncodingException { | |||
|         SsoTicketFormDTO ssoTicket = new SsoTicketFormDTO(); | |||
|         ssoTicket.setSsoTicket(ticket); | |||
| 
 | |||
|         String domain = jcetThirdplatProps.getDomain(); | |||
|         Result<String> result = HttpClientManager.getInstance().sendPost( | |||
|                 domain.concat(JcetConstants.URL_GET_USER_BY_TICKET), | |||
|                 domain.startsWith("https://"), | |||
|                 JSON.toJSONString(ssoTicket), | |||
|                 getHeaders(ssoTicket)); | |||
| 
 | |||
|         JcetUserInfoResultDTO resultDTO = parseResult(result, JcetUserInfoResultDTO.class); | |||
| 
 | |||
|         ThirdPlatUserInfo userInfo = new ThirdPlatUserInfo(); | |||
|         userInfo.setOpenId(resultDTO.getId()); | |||
|         userInfo.setName(resultDTO.getName()); | |||
|         userInfo.setMobile(resultDTO.getMobile()); | |||
|         return userInfo; | |||
|     } | |||
| 
 | |||
|     /** | |||
|      * @return | |||
|      * @Description 通过token获取用户信息 | |||
|      * @author wxz | |||
|      * @date 2021.01.19 10:28 | |||
|      */ | |||
|     //public JcetUserInfoResultDTO getUserInfoByToken(String token) throws UnsupportedEncodingException {
 | |||
|     //    SsoTokenFormDTO ssoToken = new SsoTokenFormDTO();
 | |||
|     //    ssoToken.setSsoToken(token);
 | |||
|     //
 | |||
|     //    HashMap<String, Object> paramMap = new HashMap<>();
 | |||
|     //    paramMap.put(JcetConstants.PLAT_TOKEN_NAME, token);
 | |||
|     //
 | |||
|     //    String domain = jcetThirdplatProps.getDomain();
 | |||
|     //
 | |||
|     //    Result<String> result = HttpClientManager.getInstance().sendGet(
 | |||
|     //            domain.concat(JcetConstants.URL_GET_USER_BY_TOKEN),
 | |||
|     //            domain.startsWith("https://"),
 | |||
|     //            paramMap,
 | |||
|     //            getHeaders(ssoToken));
 | |||
|     //
 | |||
|     //    JcetUserInfoResultDTO resultDTO = parseResult(result, JcetUserInfoResultDTO.class);
 | |||
|     //    return resultDTO;
 | |||
|     //}
 | |||
| 
 | |||
|     /** | |||
|      * 获取请求所需要的头信息 | |||
|      * | |||
|      * @param contentObject | |||
|      * @return | |||
|      * @throws UnsupportedEncodingException | |||
|      */ | |||
|     private Map<String, String> getHeaders(Object contentObject) throws UnsupportedEncodingException { | |||
|         int bodyLength = JSON.toJSONString(contentObject).getBytes("utf-8").length; | |||
| 
 | |||
|         Map<String, String> headers = new HashMap(); | |||
|         long timestamp = System.currentTimeMillis(); | |||
|         headers.put(JcetConstants.PLAT_HEADER_OPEN_TIMESTAMP, String.valueOf(timestamp)); | |||
|         headers.put(JcetConstants.PLAT_HEADER_OPEN_APP_ID, jcetThirdplatProps.getAppkey()); | |||
|         String encryptContent = jcetThirdplatProps.getAppkey() + timestamp + bodyLength; | |||
|         headers.put(JcetConstants.PLAT_HEADER_OPEN_SIGN, SignUtils.generate(encryptContent, jcetThirdplatProps.getAppsecret())); | |||
|         return headers; | |||
|     } | |||
| 
 | |||
| } | |||
| @ -0,0 +1,10 @@ | |||
| package com.epmet.commons.thirdplat.bean; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| @Data | |||
| public class ThirdPlatUserInfo { | |||
|     private String openId; | |||
|     private String name; | |||
|     private String mobile; | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package com.epmet.commons.thirdplat.config; | |||
| 
 | |||
| import com.epmet.commons.thirdplat.apiservice.jcet.JcetApiService; | |||
| import com.epmet.commons.thirdplat.constants.ApiServiceBeansConstants; | |||
| import com.epmet.commons.thirdplat.properties.ThirdplatProps; | |||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| 
 | |||
| /** | |||
|  * 第三方平台的相关配置 | |||
|  */ | |||
| @Configuration | |||
| @EnableConfigurationProperties(ThirdplatProps.class) | |||
| public class ThirdplatConfig { | |||
| 
 | |||
|     /** | |||
|      * @Description 酒城e通的apiService,这个name需要注册进数据库,使用的时候去数据库根据客户id找对应的apiService出来用 | |||
|      * @return | |||
|      * @author wxz | |||
|      * @date 2021.01.20 13:50 | |||
|     */ | |||
|     @Bean(name = ApiServiceBeansConstants.JCET_API_SERVICE) | |||
|     public JcetApiService JcetApiService(ThirdplatProps props) { | |||
|         return new JcetApiService(props); | |||
|     } | |||
| 
 | |||
| } | |||
| @ -0,0 +1,9 @@ | |||
| package com.epmet.commons.thirdplat.constants; | |||
| 
 | |||
| /** | |||
|  * ApiService常量 | |||
|  */ | |||
| public interface ApiServiceBeansConstants { | |||
|     // 酒城e通apiService
 | |||
|     String JCET_API_SERVICE = "jcetApiService"; | |||
| } | |||
| @ -0,0 +1,14 @@ | |||
| package com.epmet.commons.thirdplat.constants; | |||
| 
 | |||
| public interface JcetConstants { | |||
| 
 | |||
|     String URL_GET_USER_BY_TICKET = "/openapi-cgw/openapi-login/sso/getUserInfoByTicket"; | |||
|     String URL_GET_USER_BY_TOKEN = "/openapi-cgw/openapi-login/sso/getUserInfoByToken"; | |||
| 
 | |||
|     String PLAT_TICKET_NAME = "ssoTicket"; | |||
|     String PLAT_TOKEN_NAME = "ssoToken"; | |||
| 
 | |||
|     String PLAT_HEADER_OPEN_TIMESTAMP = "openTimestamp"; | |||
|     String PLAT_HEADER_OPEN_APP_ID = "openAppId"; | |||
|     String PLAT_HEADER_OPEN_SIGN = "openSign"; | |||
| } | |||
| @ -0,0 +1,8 @@ | |||
| package com.epmet.commons.thirdplat.dto.form.jcet; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| @Data | |||
| public class SsoTicketFormDTO { | |||
|     private String ssoTicket; | |||
| } | |||
| @ -0,0 +1,8 @@ | |||
| package com.epmet.commons.thirdplat.dto.form.jcet; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| @Data | |||
| public class SsoTokenFormDTO { | |||
|     private String ssoToken; | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.epmet.commons.thirdplat.dto.result.jcet; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| @Data | |||
| public class JcetResult { | |||
| 
 | |||
|     private boolean success; | |||
|     private String msg; | |||
|     private Object data; | |||
|     private int code; | |||
| 
 | |||
| } | |||
| @ -0,0 +1,29 @@ | |||
| package com.epmet.commons.thirdplat.dto.result.jcet; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| @Data | |||
| public class JcetUserInfoResultDTO { | |||
|     private String id; | |||
|     /** | |||
|      * 用户名称 | |||
|      */ | |||
|     private String userName; | |||
|     /** | |||
|      * 手机号码 | |||
|      */ | |||
|     private String mobile; | |||
|     /** | |||
|      * 姓名 | |||
|      */ | |||
|     private String name; | |||
|     /** | |||
|      * 邮箱 | |||
|      */ | |||
|     private String email; | |||
| 
 | |||
|     /** | |||
|      * sessionId,用于维持在线状态 | |||
|      */ | |||
|     private String oaSessionId; | |||
| } | |||
| @ -0,0 +1,51 @@ | |||
| package com.epmet.commons.thirdplat.encrypt; | |||
| 
 | |||
| 
 | |||
| import com.epmet.commons.tools.exception.RenException; | |||
| 
 | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.nio.charset.Charset; | |||
| import java.security.MessageDigest; | |||
| import java.security.NoSuchAlgorithmException; | |||
| 
 | |||
| public class EncryptUtils { | |||
|     private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | |||
|     /** | |||
|      * 32位 MD5加密 | |||
|      * | |||
|      * @param s | |||
|      * @return | |||
|      */ | |||
|     public static String md5Hex(String s) throws UnsupportedEncodingException { | |||
|         byte[] result = digest("MD5", s.getBytes(Charset.defaultCharset())); | |||
|         return hex(result); | |||
|     } | |||
|     /** | |||
|      * 32 位 sha256加密 | |||
|      * | |||
|      * @param s | |||
|      * @return | |||
|      */ | |||
|     public static String sha256(String s) { | |||
|         byte[] result = digest("SHA-256", s.getBytes(Charset.defaultCharset())); | |||
|         return hex(result); | |||
|     } | |||
|     private static byte[] digest(String algorithm, byte[] data) { | |||
|         try { | |||
|             MessageDigest digest = MessageDigest.getInstance(algorithm); | |||
|             digest.update(data, 0, data.length); | |||
|             return digest.digest(); | |||
|         } catch (NoSuchAlgorithmException e) { | |||
|             throw new RenException(algorithm + " error", e); | |||
|         } | |||
|     } | |||
|     private static String hex(byte[] data) { | |||
|         char[] result = new char[data.length * 2]; | |||
|         int c = 0; | |||
|         for (byte b : data) { | |||
|             result[c++] = HEX_DIGITS[(b >> 4) & 0xf]; | |||
|             result[c++] = HEX_DIGITS[b & 0xf]; | |||
|         } | |||
|         return new String(result); | |||
|     } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| package com.epmet.commons.thirdplat.encrypt; | |||
| 
 | |||
| import java.io.UnsupportedEncodingException; | |||
| 
 | |||
| public class SignUtils { | |||
|     public static String generate(String content, String secret) throws UnsupportedEncodingException { | |||
|         String sign = EncryptUtils.sha256(content); | |||
|         sign = EncryptUtils.md5Hex(sign + secret); | |||
|         return sign; | |||
|     } | |||
| 
 | |||
|     public static void main(String[] args) { | |||
|         System.out.println(777); | |||
|     } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.epmet.commons.thirdplat.properties; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| /** | |||
|  * 酒城e通三方平台配置 | |||
|  */ | |||
| @Data | |||
| public class JcetThirdplatProps { | |||
|     private String domain; | |||
|     private String appkey; | |||
|     private String appsecret; | |||
| } | |||
| @ -0,0 +1,12 @@ | |||
| package com.epmet.commons.thirdplat.properties; | |||
| 
 | |||
| import lombok.Data; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| 
 | |||
| @Data | |||
| @ConfigurationProperties(prefix = "thirdplat") | |||
| public class ThirdplatProps { | |||
| 
 | |||
|     private JcetThirdplatProps jcet; | |||
| 
 | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| package com.epmet.dto.form; | |||
| 
 | |||
| import com.epmet.commons.tools.dto.form.PageFormDTO; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| 
 | |||
| import javax.validation.constraints.NotBlank; | |||
| 
 | |||
| @Data | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| public class ApiServiceFormDTO { | |||
| 
 | |||
|     public interface GetByCustomerId extends PageFormDTO.AddUserShowGroup {} | |||
| 
 | |||
|     @NotBlank(message = "客户ID不能为空", groups = { GetByCustomerId.class }) | |||
|     private String customerId; | |||
| 
 | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| package com.epmet.dto.result; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| @Data | |||
| public class ThirdplatApiserviceResultDTO { | |||
|     /** | |||
|      * 客户id | |||
|      */ | |||
|     private String customerId; | |||
| 
 | |||
|     /** | |||
|      * aipService名称 | |||
|      */ | |||
|     private String apiServiceName; | |||
| } | |||
| @ -0,0 +1,36 @@ | |||
| /** | |||
|  * Copyright 2018 人人开源 https://www.renren.io
 | |||
|  * <p> | |||
|  * This program is free software: you can redistribute it and/or modify | |||
|  * it under the terms of the GNU General Public License as published by | |||
|  * the Free Software Foundation, either version 3 of the License, or | |||
|  * (at your option) any later version. | |||
|  * <p> | |||
|  * This program is distributed in the hope that it will be useful, | |||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |||
|  * GNU General Public License for more details. | |||
|  * <p> | |||
|  * You should have received a copy of the GNU General Public License | |||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |||
|  */ | |||
| 
 | |||
| package com.epmet.dao; | |||
| 
 | |||
| import com.epmet.commons.mybatis.dao.BaseDao; | |||
| import com.epmet.dto.result.ThirdplatApiserviceResultDTO; | |||
| import com.epmet.entity.CustomerThirdplatApiserviceEntity; | |||
| import org.apache.ibatis.annotations.Mapper; | |||
| import org.apache.ibatis.annotations.Param; | |||
| 
 | |||
| /** | |||
|  * 客户所属的第三方平台的apiService列表 | |||
|  * | |||
|  * @author generator generator@elink-cn.com | |||
|  * @since v1.0.0 2021-01-20 | |||
|  */ | |||
| @Mapper | |||
| public interface CustomerThirdplatApiserviceDao extends BaseDao<CustomerThirdplatApiserviceEntity> { | |||
| 
 | |||
|     ThirdplatApiserviceResultDTO getByCustomerId(@Param("customerId") String customerId); | |||
| } | |||
| @ -0,0 +1,51 @@ | |||
| /** | |||
|  * Copyright 2018 人人开源 https://www.renren.io
 | |||
|  * <p> | |||
|  * This program is free software: you can redistribute it and/or modify | |||
|  * it under the terms of the GNU General Public License as published by | |||
|  * the Free Software Foundation, either version 3 of the License, or | |||
|  * (at your option) any later version. | |||
|  * <p> | |||
|  * This program is distributed in the hope that it will be useful, | |||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |||
|  * GNU General Public License for more details. | |||
|  * <p> | |||
|  * You should have received a copy of the GNU General Public License | |||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |||
|  */ | |||
| 
 | |||
| 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; | |||
| 
 | |||
| /** | |||
|  * 客户所属的第三方平台的apiService列表 | |||
|  * | |||
|  * @author generator generator@elink-cn.com | |||
|  * @since v1.0.0 2021-01-20 | |||
|  */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper=false) | |||
| @TableName("customer_thirdplat_apiservice") | |||
| public class CustomerThirdplatApiserviceEntity extends BaseEpmetEntity { | |||
| 
 | |||
| 	private static final long serialVersionUID = 1L; | |||
| 
 | |||
|     /** | |||
|      * 客户id | |||
|      */ | |||
| 	private String customerId; | |||
| 
 | |||
|     /** | |||
|      * aipService名称 | |||
|      */ | |||
| 	private String apiServiceName; | |||
| 
 | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| package com.epmet.service; | |||
| 
 | |||
| import com.epmet.dto.result.ThirdplatApiserviceResultDTO; | |||
| import com.epmet.entity.CustomerThirdplatApiserviceEntity; | |||
| 
 | |||
| public interface CustomerThirdplatApiServiceService { | |||
| 
 | |||
|     /** | |||
|      * @Description 根据客户id查询客户第三方平台的ApiService | |||
|      * @return | |||
|      * @author wxz | |||
|      * @date 2021.01.20 15:47 | |||
|     */ | |||
|     ThirdplatApiserviceResultDTO getByCustomerId(String customerId); | |||
| 
 | |||
| } | |||
| @ -0,0 +1,42 @@ | |||
| package com.epmet.service.impl; | |||
| 
 | |||
| import cn.hutool.core.bean.BeanUtil; | |||
| import com.epmet.commons.tools.redis.RedisKeys; | |||
| import com.epmet.commons.tools.redis.RedisUtils; | |||
| import com.epmet.dao.CustomerThirdplatApiserviceDao; | |||
| import com.epmet.dto.result.ThirdplatApiserviceResultDTO; | |||
| import com.epmet.entity.CustomerThirdplatApiserviceEntity; | |||
| import com.epmet.service.CustomerThirdplatApiServiceService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.util.CollectionUtils; | |||
| 
 | |||
| import java.util.Map; | |||
| 
 | |||
| @Service | |||
| public class CustomerThirdplatApiServiceServiceImpl implements CustomerThirdplatApiServiceService { | |||
| 
 | |||
|     @Autowired | |||
|     private RedisUtils redisUtils; | |||
| 
 | |||
|     @Autowired | |||
|     private CustomerThirdplatApiserviceDao thirdplatApiserviceDao; | |||
| 
 | |||
|     @Override | |||
|     public ThirdplatApiserviceResultDTO getByCustomerId(String customerId) { | |||
|         ThirdplatApiserviceResultDTO apiService = null; | |||
| 
 | |||
|         // 查redis,存redis
 | |||
|         Map<String, Object> apiServiceMap = redisUtils.hGetAll(RedisKeys.getCustomerApiServiceKey(customerId)); | |||
|         if (!CollectionUtils.isEmpty(apiServiceMap)) { | |||
|             apiService = BeanUtil.mapToBean(apiServiceMap, ThirdplatApiserviceResultDTO.class, true); | |||
|         } | |||
| 
 | |||
|         if (apiService == null) { | |||
|             apiService = thirdplatApiserviceDao.getByCustomerId(customerId); | |||
|             redisUtils.hMSet(RedisKeys.getCustomerApiServiceKey(customerId), BeanUtil.beanToMap(apiService)); | |||
|         } | |||
| 
 | |||
|         return apiService; | |||
|     } | |||
| } | |||
| @ -0,0 +1,14 @@ | |||
| create table customer_thirdplat_apiservice | |||
| ( | |||
|     `ID`               varchar(64) NOT NULL COMMENT '唯一标识', | |||
|     `CUSTOMER_ID`      varchar(64) not null comment '客户id', | |||
|     `API_SERVICE_NAME` varchar(64) not null comment 'aipService名称', | |||
|     `DEL_FLAG`         int(11)     NOT NULL COMMENT '删除标识:0.未删除 1.已删除', | |||
|     `REVISION`         int(11)     NOT NULL COMMENT '乐观锁', | |||
|     `CREATED_BY`       varchar(32) NOT NULL COMMENT '创建人', | |||
|     `CREATED_TIME`     datetime    NOT NULL COMMENT '创建时间', | |||
|     `UPDATED_BY`       varchar(32) NOT NULL COMMENT '更新人', | |||
|     `UPDATED_TIME`     datetime    NOT NULL COMMENT '更新时间' | |||
| ) ENGINE = InnoDB | |||
|   DEFAULT CHARSET = utf8mb4 | |||
|   collate utf8mb4_general_ci COMMENT ='客户所属的第三方平台的apiService列表'; | |||
| @ -0,0 +1,33 @@ | |||
| <?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.CustomerThirdplatApiserviceDao"> | |||
| 
 | |||
|     <resultMap type="com.epmet.entity.CustomerThirdplatApiserviceEntity" id="customerThirdplatApiserviceMap"> | |||
|         <result property="id" column="ID"/> | |||
|         <result property="customerId" column="CUSTOMER_ID"/> | |||
|         <result property="apiServiceName" column="API_SERVICE_NAME"/> | |||
|         <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> | |||
| 
 | |||
|     <select id="getByCustomerId" resultType="com.epmet.dto.result.ThirdplatApiserviceResultDTO"> | |||
|         select id, | |||
|                customer_id, | |||
|                api_service_name, | |||
|                del_flag, | |||
|                revision, | |||
|                created_by, | |||
|                created_time, | |||
|                updated_by, | |||
|                updated_time | |||
|         from customer_thirdplat_apiservice cta | |||
|         where cta.CUSTOMER_ID = #{customerId} | |||
|     </select> | |||
| 
 | |||
| 
 | |||
| </mapper> | |||
| @ -0,0 +1,40 @@ | |||
| package com.epmet.dto.form; | |||
| 
 | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| 
 | |||
| import javax.validation.constraints.NotBlank; | |||
| import java.io.Serializable; | |||
| 
 | |||
| /** | |||
|  * @Author zxc | |||
|  * @DateTime 2021/1/19 上午10:31 | |||
|  */ | |||
| @Data | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| public class UserInfoFormDTO implements Serializable { | |||
| 
 | |||
|     private static final long serialVersionUID = 3394557656494741201L; | |||
| 
 | |||
|     public interface UserInfoForm{} | |||
| 
 | |||
|     /** | |||
|      * 工作端:WORK、居民端:resi、运营端:oper | |||
|      */ | |||
|     @NotBlank(message = "app类型不能为空",groups = {UserInfoForm.class}) | |||
|     private String app; | |||
| 
 | |||
|     /** | |||
|      * UID 用户唯一标识  即wx_open_id | |||
|      */ | |||
|     @NotBlank(message = "UID不能为空",groups = {UserInfoForm.class}) | |||
|     private String uid; | |||
| 
 | |||
|     private String name; | |||
|     private String mobile; | |||
|     private String account; | |||
| 
 | |||
|     private String userId; | |||
| } | |||
					Loading…
					
					
				
		Reference in new issue