diff --git a/mallinkCApi/src/main/java/com/iformall/controller/WxUserGrantController.java b/mallinkCApi/src/main/java/com/iformall/controller/WxUserGrantController.java index 142382cc9..98671232b 100755 --- a/mallinkCApi/src/main/java/com/iformall/controller/WxUserGrantController.java +++ b/mallinkCApi/src/main/java/com/iformall/controller/WxUserGrantController.java @@ -643,7 +643,7 @@ public class WxUserGrantController extends BaseController { // 成长值 wxScoreRulesService.addScore(getTenantInfo(),EnumScoreType.WECHAT_PHONE, user); // 增加积分 - wxCUserService.addCredit(user, EnumScoreType.WECHAT_PHONE); + wxCUserBasicInfoService.addCredit(user.getUserId(),getTenantInfo(),EnumScoreType.WECHAT_PHONE); // 外部注券 memCouponFromDspService.couponOrderFromDsp(tenantEntity, phoneNoInfo.getPhoneNumber()); } diff --git a/mallinkService/src/main/java/com/iformall/domain/po/TtCUser.java b/mallinkService/src/main/java/com/iformall/domain/po/TtCUser.java new file mode 100644 index 000000000..768f9b826 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/domain/po/TtCUser.java @@ -0,0 +1,149 @@ +package com.iformall.domain.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.utils.Constant; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@TableName(value = "tt_c_user") +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class TtCUser extends BaseCUserEntity { + + @io.swagger.annotations.ApiModelProperty(value="openId",name="openId") + private String openId; + @io.swagger.annotations.ApiModelProperty(value="unionId",name="unionId") + private String unionId; + @io.swagger.annotations.ApiModelProperty(value="用户昵称",name="nickName") + private String nickName; + @io.swagger.annotations.ApiModelProperty(value="用户性别",name="gender") + private Integer gender; + @io.swagger.annotations.ApiModelProperty(value="用户头像地址",name="avatarUrl") + private String avatarUrl; + @io.swagger.annotations.ApiModelProperty(value="用户绑定的手机号",name="phone") + private String phone; + @io.swagger.annotations.ApiModelProperty(value="用户没有区号的手机号",name="purePhone") + private String purePhone; + @io.swagger.annotations.ApiModelProperty(value="用户所在城市",name="city") + private String city; + @io.swagger.annotations.ApiModelProperty(value="用户所在省份",name="province") + private String province; + @io.swagger.annotations.ApiModelProperty(value="用户所在语言",name="language") + private String language; + @io.swagger.annotations.ApiModelProperty(value="用户手机区号",name="countryCode") + private String countryCode; + @io.swagger.annotations.ApiModelProperty(value="用户注册IP",name="registerIp") + private String registerIp; + @io.swagger.annotations.ApiModelProperty(value="验证码手机",name="verifyCodePhone") + private String verifyCodePhone; + @io.swagger.annotations.ApiModelProperty(value="注册时记录用户扫码渠道,如朋友圈广告",name="qrcodeSource") + private String qrcodeSource; + @io.swagger.annotations.ApiModelProperty(value="二维码来源,小程序",name="scene") + private String scene; + @io.swagger.annotations.ApiModelProperty(value="渠道,小程序",name="sceneAddress") + private String sceneAddress; + @io.swagger.annotations.ApiModelProperty(value="session key for 微信小程序",name="sessionKey") + private String sessionKey; + @io.swagger.annotations.ApiModelProperty(value="成长值",name="score") + private Integer score; + @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate") + private Date updateDate; + @io.swagger.annotations.ApiModelProperty(value="上次活跃时间",name="activeTime") + private Date activeTime; + @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") + private Date createDate; + @io.swagger.annotations.ApiModelProperty(value="小程序的appId",name="appId") + private String appId; + /*经度**/ + @io.swagger.annotations.ApiModelProperty(value="经度",name="longitude") + private BigDecimal longitude; + /*纬度**/ + @io.swagger.annotations.ApiModelProperty(value="纬度",name="latitude") + private BigDecimal latitude; + /*登录次数**/ + @io.swagger.annotations.ApiModelProperty(value="登录次数",name="loginCount") + private Integer loginCount; + /*附加信息**/ + @io.swagger.annotations.ApiModelProperty(value="附加信息",name="extraInfo") + private String extraInfo; + /**是否关注公众号**/ + @io.swagger.annotations.ApiModelProperty(value="是否关注公众号",name="isSubscribe") + private Integer isSubscribe; + + @io.swagger.annotations.ApiModelProperty(value="微信开放平台appId",name="openAppId") + private String openAppId; + @io.swagger.annotations.ApiModelProperty(value="服务号openId",name="mpOpenId") + private String mpOpenId; + @io.swagger.annotations.ApiModelProperty(value="服务号appId",name="mpAppId") + private String mpAppId; + @io.swagger.annotations.ApiModelProperty(value="是否关注服务号",name="mpSubscribe") + private Integer mpSubscribe; + @io.swagger.annotations.ApiModelProperty(value="关注服务号时间",name="mpSubscribeTime") + private Date mpSubscribeTime; + @io.swagger.annotations.ApiModelProperty(value="关注服务号Scene",name="mpSubscribeScene") + private String mpSubscribeScene; + @io.swagger.annotations.ApiModelProperty(value="订阅号openId",name="subsOpenId") + private String subsOpenId; + @io.swagger.annotations.ApiModelProperty(value="订阅号appId",name="subsAppId") + private String subsAppId; + @io.swagger.annotations.ApiModelProperty(value="是否关注订阅号",name="subsSubscribe") + private Integer subsSubscribe; + @io.swagger.annotations.ApiModelProperty(value="关注订阅号时间",name="subsSubscribeTime") + private Date subsSubscribeTime; + @io.swagger.annotations.ApiModelProperty(value="关注订阅号Scene",name="subsSubscribeScene") + private String subsSubscribeScene; + + @io.swagger.annotations.ApiModelProperty(value="积分",name="credit") + private Integer credit; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value="渠道名称",name="channelName") + private String channelName; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value="渠道描述",name="sceneDescription") + protected String sceneDescription; + + @TableField(exist = false) + List sceneList; + + @TableField(exist = false) + protected Date startDate; + + @TableField(exist = false) + protected Date endDate; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value="操作人类型 枚举:EnumUserType",name="operatorType") + private Integer operatorType; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value="操作人ID",name="operatorId") + private Long operatorId; + + public String createToken(Date currentDate,String tenantId) { + if(StringUtils.isBlank(tenantId)){ + tenantId = "1"; + } + if (this.getExpireTime() == null || this.getExpireTime().getTime() - Constant.H_EXPIRE < currentDate.getTime()) + { + //生成一个token + this.setToken(UUID.randomUUID().toString()+":"+tenantId+Constant.TOKEN_TTC_END); + //过期时间 + this.setExpireTime(new Date(currentDate.getTime() + Constant.S_D_EXPIRE)); + } + return this.getToken(); + } +} diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java b/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java index 517852483..80f514074 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxCUser.java @@ -9,6 +9,7 @@ import com.iformall.utils.Constant; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; @@ -135,6 +136,9 @@ public class WxCUser extends BaseCUserEntity { private Long operatorId; public String createToken(Date currentDate,String tenantId) { + if(StringUtils.isBlank(tenantId)){ + tenantId = "1"; + } if (this.getExpireTime() == null || this.getExpireTime().getTime() - Constant.H_EXPIRE < currentDate.getTime()) { //生成一个token diff --git a/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/TtMaService.java b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/TtMaService.java new file mode 100644 index 000000000..e746739a0 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/TtMaService.java @@ -0,0 +1,122 @@ +package com.iformall.douyin.miniapp.api; + +import cn.binarywang.wx.miniapp.api.WxMaUserService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.config.WxMaConfig; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; + +/** + * @author Binary Wang + */ +public interface TtMaService { + /** + * 获取access_token. + */ + String GET_ACCESS_TOKEN_URL = "https://developer.toutiao.com/api/apps/token?grant_type=client_credential&appid=%s&secret=%s"; + + String JSCODE_TO_SESSION_URL = "https://developer.toutiao.com/api/apps/jscode2session"; + + /** + * 获取登录后的session信息. + * + * @param jsCode 登录时获取的 code + */ + WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException; + + /** + *
+   * 验证消息的确来自微信服务器.
+   * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
+   * 
+ */ + boolean checkSignature(String timestamp, String nonce, String signature); + + /** + *
+   * 获取access_token,本方法线程安全.
+   * 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
+   *
+   * 另:本service的所有方法都会在access_token过期是调用此方法
+   *
+   * 程序员在非必要情况下尽量不要主动调用此方法
+   *
+   * 详情请见: https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/server/interface-request-credential/get-access-token
+   * 
+ * + * @param forceRefresh 强制刷新 + */ + String getAccessToken(boolean forceRefresh) throws WxErrorException; + + /** + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求. + */ + String get(String url, String queryParam) throws WxErrorException; + + /** + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求. + */ + String post(String url, String postData) throws WxErrorException; + + /** + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求. + */ + String post(String url, Object obj) throws WxErrorException; + + /** + *
+   * Service没有实现某个API的时候,可以用这个,
+   * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
+   * 可以参考,{@link MediaUploadRequestExecutor}的实现方法
+   * 
+ */ + T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; + + /** + *
+   * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
+   * 默认:1000ms
+   * 
+ */ + void setRetrySleepMillis(int retrySleepMillis); + + /** + *
+   * 设置当微信系统响应系统繁忙时,最大重试次数.
+   * 默认:5次
+   * 
+ */ + void setMaxRetryTimes(int maxRetryTimes); + + /** + * 获取WxMaConfig 对象. + * + * @return WxMaConfig + */ + WxMaConfig getWxMaConfig(); + + /** + * 注入 {@link WxMaConfig} 的实现. + */ + void setWxMaConfig(WxMaConfig wxConfigProvider); + + /** + * 初始化http请求对象. + */ + void initHttp(); + + /** + * 请求http请求相关信息. + */ + RequestHttp getRequestHttp(); + + /** + * 返回用户相关接口方法的实现类对象,以方便调用其各个接口. + * + * @return TtMaUserService + */ + TtMaUserService getUserService(); + +} diff --git a/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/TtMaUserService.java b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/TtMaUserService.java new file mode 100644 index 000000000..42a81942e --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/TtMaUserService.java @@ -0,0 +1,54 @@ +package com.iformall.douyin.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.util.Map; + +/** + * 用户信息相关操作接口. + * + * @author Binary Wang + */ +public interface TtMaUserService { + + /** + * 获取登录后的session信息. + * + * @param jsCode 登录时获取的 code + * @return . + * @throws WxErrorException . + */ + WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException; + + /** + * 解密用户敏感数据. + * + * @param sessionKey 会话密钥 + * @param encryptedData 消息密文 + * @param ivStr 加密算法的初始向量 + */ + WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr); + + /** + * 解密用户手机号信息. + * + * @param sessionKey 会话密钥 + * @param encryptedData 消息密文 + * @param ivStr 加密算法的初始向量 + * @return . + */ + WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr); + + /** + * 验证用户信息完整性. + * + * @param sessionKey 会话密钥 + * @param rawData 微信用户基本信息 + * @param signature 数据签名 + * @return . + */ + boolean checkUserInfo(String sessionKey, String rawData, String signature); +} diff --git a/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/impl/TtMaServiceImpl.java b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/impl/TtMaServiceImpl.java new file mode 100644 index 000000000..d839ac29c --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/impl/TtMaServiceImpl.java @@ -0,0 +1,275 @@ +package com.iformall.douyin.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaUserService; +import cn.binarywang.wx.miniapp.api.impl.WxMaUserServiceImpl; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.config.WxMaConfig; +import com.google.common.base.Joiner; +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import com.iformall.douyin.miniapp.api.TtMaService; +import com.iformall.douyin.miniapp.api.TtMaUserService; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.WxType; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.DataUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import org.apache.http.HttpHost; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; + +import static cn.binarywang.wx.miniapp.constant.WxMaConstants.ErrorCode.*; + +/** + * @author + */ +@Slf4j +public class TtMaServiceImpl implements TtMaService, RequestHttp { + private static final JsonParser JSON_PARSER = new JsonParser(); + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + private WxMaConfig wxMaConfig; + + private TtMaUserService userService = new TtMaUserServiceImpl(this); + + private int retrySleepMillis = 1000; + private int maxRetryTimes = 5; + + protected static final Gson GSON = new Gson(); + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpType getRequestType() { + return HttpType.APACHE_HTTP; + } + + @Override + public void initHttp() { + WxMaConfig configStorage = this.getWxMaConfig(); + ApacheHttpClientBuilder apacheHttpClientBuilder = configStorage.getApacheHttpClientBuilder(); + if (null == apacheHttpClientBuilder) { + apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + } + + apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost()) + .httpProxyPort(configStorage.getHttpProxyPort()) + .httpProxyUsername(configStorage.getHttpProxyUsername()) + .httpProxyPassword(configStorage.getHttpProxyPassword()); + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + + @Override + public RequestHttp getRequestHttp() { + return this; + } + + @Override + public String getAccessToken(boolean forceRefresh) throws WxErrorException { + if (!this.getWxMaConfig().isAccessTokenExpired() && !forceRefresh) { + return this.getWxMaConfig().getAccessToken(); + } + + Lock lock = this.getWxMaConfig().getAccessTokenLock(); + lock.lock(); + try { + String url = String.format(this.GET_ACCESS_TOKEN_URL, this.getWxMaConfig().getAppid(), + this.getWxMaConfig().getSecret()); + try { + HttpGet httpGet = new HttpGet(url); + if (this.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); + httpGet.setConfig(config); + } + try (CloseableHttpResponse response = getRequestHttpClient().execute(httpGet)) { + String resultContent = new BasicResponseHandler().handleResponse(response); + WxError error = WxError.fromJson(resultContent, WxType.MiniApp); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); + this.getWxMaConfig().updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); + + return this.getWxMaConfig().getAccessToken(); + } finally { + httpGet.releaseConnection(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } finally { + lock.unlock(); + } + + } + + + + @Override + public WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException { + final WxMaConfig config = getWxMaConfig(); + Map params = new HashMap<>(8); + params.put("appid", config.getAppid()); + params.put("secret", config.getSecret()); + params.put("js_code", jsCode); + params.put("grant_type", "authorization_code"); + + String result = get(JSCODE_TO_SESSION_URL, Joiner.on("&").withKeyValueSeparator("=").join(params)); + return WxMaJscode2SessionResult.fromJson(result); + } + + @Override + public boolean checkSignature(String timestamp, String nonce, String signature) { + try { + return SHA1.gen(this.getWxMaConfig().getToken(), timestamp, nonce).equals(signature); + } catch (Exception e) { + log.error("Checking signature failed, and the reason is :" + e.getMessage()); + return false; + } + } + + @Override + public String get(String url, String queryParam) throws WxErrorException { + return execute(SimpleGetRequestExecutor.create(this), url, queryParam); + } + + @Override + public String post(String url, String postData) throws WxErrorException { + return execute(SimplePostRequestExecutor.create(this), url, postData); + } + + @Override + public String post(String url, Object obj) throws WxErrorException { + return this.execute(SimplePostRequestExecutor.create(this), url, WxGsonBuilder.create().toJson(obj)); + } + + /** + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 + */ + @Override + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + int retryTimes = 0; + do { + try { + return this.executeInternal(executor, uri, data); + } catch (WxErrorException e) { + if (retryTimes + 1 > this.maxRetryTimes) { + log.warn("重试达到最大次数【{}】", maxRetryTimes); + //最后一次重试失败后,直接抛出异常,不再等待 + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + WxError error = e.getError(); + // -1 系统繁忙, 1000ms后重试 + if (error.getErrorCode() == -1) { + int sleepMillis = this.retrySleepMillis * (1 << retryTimes); + try { + log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); + Thread.sleep(sleepMillis); + } catch (InterruptedException e1) { + Thread.currentThread().interrupt(); + } + } else { + throw e; + } + } + } while (retryTimes++ < this.maxRetryTimes); + + log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + private T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + E dataForLog = DataUtils.handleDataWithSecret(data); + + if (uri.contains("access_token=")) { + throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); + } + String accessToken = getAccessToken(false); + + String uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + accessToken; + + try { + T result = executor.execute(uriWithAccessToken, data, WxType.MiniApp); + log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); + return result; + } catch (WxErrorException e) { + WxError error = e.getError(); + /* + * 发生以下情况时尝试刷新access_token + */ + if (error.getErrorCode() == ERR_40001 + || error.getErrorCode() == ERR_42001 + || error.getErrorCode() == ERR_40014) { + // 强制设置WxMaConfig的access token过期了,这样在下一次请求里就会刷新access token + this.getWxMaConfig().expireAccessToken(); + if (this.getWxMaConfig().autoRefreshToken()) { + return this.execute(executor, uri, data); + } + } + + if (error.getErrorCode() != 0) { + log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); + throw new WxErrorException(error, e); + } + return null; + } catch (IOException e) { + log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public WxMaConfig getWxMaConfig() { + return this.wxMaConfig; + } + + @Override + public void setWxMaConfig(WxMaConfig wxConfigProvider) { + this.wxMaConfig = wxConfigProvider; + this.initHttp(); + } + + @Override + public void setRetrySleepMillis(int retrySleepMillis) { + this.retrySleepMillis = retrySleepMillis; + } + + @Override + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + @Override + public TtMaUserService getUserService() { + return this.userService; + } + +} diff --git a/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/impl/TtMaUserServiceImpl.java b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/impl/TtMaUserServiceImpl.java new file mode 100644 index 000000000..8ca0dbde9 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/douyin/miniapp/api/impl/TtMaUserServiceImpl.java @@ -0,0 +1,43 @@ +package com.iformall.douyin.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; +import com.iformall.douyin.miniapp.api.TtMaService; +import com.iformall.douyin.miniapp.api.TtMaUserService; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import org.apache.commons.codec.digest.DigestUtils; + +import java.util.Map; + +/** + * @author Binary Wang + */ +@AllArgsConstructor +public class TtMaUserServiceImpl implements TtMaUserService { + private TtMaService service; + + @Override + public WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException { + return service.jsCode2SessionInfo(jsCode); + } + + @Override + public WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr) { + return WxMaUserInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); + } + + @Override + public WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) { + return WxMaPhoneNumberInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); + } + + @Override + public boolean checkUserInfo(String sessionKey, String rawData, String signature) { + final String generatedSignature = DigestUtils.sha1Hex(rawData + sessionKey); + return generatedSignature.equals(signature); + } + +} diff --git a/mallinkService/src/main/java/com/iformall/mapper/TtCUserMapper.java b/mallinkService/src/main/java/com/iformall/mapper/TtCUserMapper.java new file mode 100644 index 000000000..8ec79a14f --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/mapper/TtCUserMapper.java @@ -0,0 +1,43 @@ +package com.iformall.mapper; + +import com.iformall.common.CommonMapper; +import com.iformall.domain.dto.WxCUserBasicInfoDto; +import com.iformall.domain.po.TtCUser; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.vo.UserCountVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TtCUserMapper extends CommonMapper { + + List findList(TtCUser record); + + TtCUser findByOpenId(TtCUser record); + + TtCUser findByUnionId(TtCUser record); + + TtCUser findByToken(@Param("token")String token,@Param("tenantId")String tenantId); + + TtCUser selectById(@Param("id")Long id,@Param("tenantId")String tenantId); + + long findCount(WxCUserBasicInfoDto dto); + + List findCountHistory(@Param("tenantEntitys")List tenantEntitys, @Param("basicDto")WxCUserBasicInfoDto dto); + + List listByChannel(@Param("tenantEntitys")List tenantEntitys, @Param("cUser")TtCUser record); + + long countByChannel(List tenantEntitys, TtCUser cUser); + + //List> checkCountByTenantOpenId(); + + void updateUserId(TtCUser user); + + void delForUserIdOnly(@Param("id")Long id, @Param("userId")Long userId,@Param("tenantId")String tenantId); + + List listOpenId(TtCUser record); + + void updateMsgCount(TtCUser user); + + void updateMsgCountDown(@Param("tenantId")String tenantId, @Param("openId")String openId); +} diff --git a/mallinkService/src/main/java/com/iformall/service/TtCUserService.java b/mallinkService/src/main/java/com/iformall/service/TtCUserService.java new file mode 100644 index 000000000..21791f2f4 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/TtCUserService.java @@ -0,0 +1,134 @@ +package com.iformall.service; + +import com.github.pagehelper.PageInfo; +import com.iformall.domain.dto.WxCUserBasicInfoDto; +import com.iformall.domain.po.TtCUser; +import com.iformall.domain.po.WxAuthorizerInfo; +import com.iformall.domain.po.WxCUserFrom; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.vo.UserCountVo; +import me.chanjar.weixin.mp.bean.result.WxMpUser; + +import java.util.List; + +public interface TtCUserService { + + /** + * 根据实体查询分页列表 + * + * @param record + * @param pageIndex + * @param pageSize + * @return + */ + PageInfo listAsPage(TtCUser record, Integer pageIndex, Integer pageSize); + + PageInfo listOpenIdAsPage(TtCUser record, Integer pageIndex, Integer pageSize); + + /** + * 根据Id获得实体 + * + * @param id + * @return + */ + TtCUser getById(Long id,String tenantId); + + /** + * 根据openId获得实体 + * + * @param record + * @return + */ + TtCUser getByOpenId(TtCUser record); + + /** + * 根据object获得实体 + * + * @param record + * @return + */ + TtCUser getByObject(TtCUser record); + + /** + * 保存或更新实体 + * + * @param record + */ + int saveOrUpdate(TtCUser record); + + /** + * updateScene + * + * @param record + */ + int updateScene(TtCUser record); + + /** + * updateLBS + * + * @param record + */ + int updateLBS(TtCUser record); + + /** + * updateExtInfo + * + * @param record + */ + int updateExtInfo(TtCUser record); + + /** + * 根据Id删除实体 + * + * @param id + */ + //void deleteById(Long id,String tenantId); + + /** + * 统计数量 + * @param dto + * @param tenantEntitys + * @return + */ + long findCount(WxCUserBasicInfoDto dto, List tenantEntitys); + + /** + * 统计数量 + * @param dto + * @param tenantEntitys + * @return + */ + List findCountHistory(WxCUserBasicInfoDto dto, List tenantEntitys); + + + /** + * 通过渠道获取会员信息 + * @param user + * @param tenantEntitys + * @param pageIndex + * @param pageSize + * @return + */ + PageInfo listByChannel(TtCUser user, List tenantEntitys, Integer pageIndex, Integer pageSize); + + long countByChannel(List tenantEntitys, TtCUser user); + + /** + * 登录后发消息 + * @param user + */ + void actionMsgAfterLogin(WxCUserFrom wxCUserFrom); + + /** + * 登录后处理 + * @param user + * @return + */ + int actionAfterLogin(TtCUser user); + + void updateUserId(TtCUser user); + + void delForUserIdOnly(Long id, Long userId, String tenantId); + + void updateMsgCount(TtCUser user); +} diff --git a/mallinkService/src/main/java/com/iformall/service/WxCUserBasicInfoService.java b/mallinkService/src/main/java/com/iformall/service/WxCUserBasicInfoService.java index aec3831b1..6ddbadcef 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCUserBasicInfoService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCUserBasicInfoService.java @@ -10,6 +10,7 @@ import com.iformall.domain.po.base.TenantEntity; import com.iformall.domain.vo.CUserBaseInfoT; import com.iformall.domain.vo.UserCountVo; import com.iformall.domain.vo.WxTagsGroupVo; +import com.iformall.enums.EnumScoreType; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -175,5 +176,7 @@ public interface WxCUserBasicInfoService { void updateQrCode(WxCUserBasicInfo wxCUserBasicInfo); WxCUserBasicInfo registerByPhone(TenantEntity tenantEntity, String phone); + + int addCredit(Long userId, TenantEntity tenantInfo, EnumScoreType wechatPhone); } diff --git a/mallinkService/src/main/java/com/iformall/service/WxCUserService.java b/mallinkService/src/main/java/com/iformall/service/WxCUserService.java index 72a0babec..ebbf5a22f 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCUserService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCUserService.java @@ -135,14 +135,6 @@ public interface WxCUserService { */ int actionAfterLogin(WxCUser user); - /** - * 积分 - * @param wxCUser - * @param enumScoreType - * @return - */ - int addCredit(WxCUser wxCUser, EnumScoreType enumScoreType); - void updateUserId(WxCUser user); void delForUserIdOnly(Long id, Long userId, String tenantId); diff --git a/mallinkService/src/main/java/com/iformall/service/cuser/CUserServiceFactory.java b/mallinkService/src/main/java/com/iformall/service/cuser/CUserServiceFactory.java index e181f97f3..71b4f29d0 100644 --- a/mallinkService/src/main/java/com/iformall/service/cuser/CUserServiceFactory.java +++ b/mallinkService/src/main/java/com/iformall/service/cuser/CUserServiceFactory.java @@ -3,6 +3,7 @@ package com.iformall.service.cuser; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import com.iformall.service.cuser.tt.TtCUserServiceAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -14,6 +15,9 @@ public class CUserServiceFactory { @Autowired WxCUserServiceAdapter wxCuserService; + + @Autowired + TtCUserServiceAdapter ttCuserService; private Map serviceMap ; @@ -27,6 +31,7 @@ public class CUserServiceFactory { } serviceMap = new ConcurrentHashMap(); serviceMap.put(EnumAppPlat.WX.getCode(), wxCuserService); + serviceMap.put(EnumAppPlat.TOUTIAO.getCode(), ttCuserService); return serviceMap; } } diff --git a/mallinkService/src/main/java/com/iformall/service/cuser/tt/TtCUserServiceAdapter.java b/mallinkService/src/main/java/com/iformall/service/cuser/tt/TtCUserServiceAdapter.java new file mode 100644 index 000000000..d2a79c80d --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/cuser/tt/TtCUserServiceAdapter.java @@ -0,0 +1,55 @@ +package com.iformall.service.cuser.tt; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.TtCUser; +import com.iformall.domain.po.WxCUser; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.TtCUserMapper; +import com.iformall.mapper.WxCUserMapper; +import com.iformall.service.cuser.CUserServiceApapter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TtCUserServiceAdapter implements CUserServiceApapter{ + + @Autowired + TtCUserMapper ttCUserMapper; + + private BaseCUserEntity generateBaseEntity(TtCUser ttCUser) { + BaseCUserEntity entity = new BaseCUserEntity(); + entity.setId(ttCUser.getId()); + entity.setExpireTime(ttCUser.getExpireTime()); + entity.setUserId(ttCUser.getUserId()); + entity.setToken(ttCUser.getToken()); + entity.updateTenantInfo(ttCUser); + entity.setRealUser(ttCUser); + return entity; + } + + @Override + public BaseCUserEntity getByToken(String token) { + if ((!StringUtils.isBlank(token))) { + String[] tokens = token.split(":"); + if (null == tokens || tokens.length != 3) { + throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), "TtCUserServiceAdapter token失效"); + } + TtCUser ttCUser = ttCUserMapper.findByToken(token,tokens[1]); + if (null == ttCUser) { + throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), "TtCUserServiceAdapter token失效"); + } + return generateBaseEntity(ttCUser); + }else { + throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), "TtCUserServiceAdapter token失效"); + } + } + + @Override + public BaseCUserEntity getByObj(Object cuser) { + TtCUser ttCUser = (TtCUser) cuser; + return generateBaseEntity(ttCUser); + } + +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/CUserTokenServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/CUserTokenServiceImpl.java index 9f732638b..92698a9ae 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/CUserTokenServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/CUserTokenServiceImpl.java @@ -36,6 +36,9 @@ public class CUserTokenServiceImpl implements CUserTokenService { if(token.endsWith(Constant.TOKEN_WXC_END)){ return EnumAppPlat.WX; } + if(token.endsWith(Constant.TOKEN_TTC_END)){ + return EnumAppPlat.TOUTIAO; + } throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), token+"token解析错误") ; } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/TtCUserServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/TtCUserServiceImpl.java new file mode 100644 index 000000000..d4d638054 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/impl/TtCUserServiceImpl.java @@ -0,0 +1,273 @@ +package com.iformall.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.iformall.common.IdWorker; +import com.iformall.domain.dto.WxCUserBasicInfoDto; +import com.iformall.domain.po.TtCUser; +import com.iformall.domain.po.WxCUserBasicInfo; +import com.iformall.domain.po.WxCUserFrom; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.po.msg.FmInsideCLoginMsg; +import com.iformall.domain.vo.UserCountVo; +import com.iformall.enums.*; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.TtCUserMapper; +import com.iformall.mq.MqBaseProducer; +import com.iformall.service.*; +import com.iformall.utils.Constant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +@Service +public class TtCUserServiceImpl implements TtCUserService { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private TtCUserMapper ttCUserMapper; + + @Autowired + private WxCUserBasicInfoService wxCUserBasicInfoService; + + @Autowired + private WxScoreRulesService wxScoreRulesService; + + @Autowired + private WxCUserTagsService wxCUserTagsService; + + @Autowired + private MqBaseProducer mqBaseProducer; + + @Autowired + @Qualifier("baseCUserTokenRedisTemplate") + RedisTemplate baseCUserTokenRedisTemplate; + + @Override + public PageInfo listAsPage(TtCUser record, Integer pageIndex, Integer pageSize) { + return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> ttCUserMapper.findList(record)); + } + + @Override + public PageInfo listOpenIdAsPage(TtCUser record, Integer pageIndex, Integer pageSize) { + return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> ttCUserMapper.listOpenId(record)); + } + + @Override + public TtCUser getById(Long id,String tenantId) { + return ttCUserMapper.selectById(id,tenantId); + } + + @Override + public TtCUser getByOpenId(TtCUser record) { + return ttCUserMapper.findByOpenId(record); + } + + @Override + public TtCUser getByObject(TtCUser record) { + return ttCUserMapper.selectOne(new QueryWrapper(record)); + } + + @Override + public int saveOrUpdate(TtCUser user) { + int ret = 0; + Date curr = new Date(); + if (user.getId() == null) { + // 检查用户是否已有同一微信开放平台账号 +// if(StringUtils.isNotBlank(user.getUnionId()) && StringUtils.isNotBlank(user.getOpenAppId())) { +// WxCUser oldUser = wxCUserMapper.findByUnionId(user); +// if(oldUser != null) { +// // 已有,更新 +// user.setId(oldUser.getId()); +// user.setLoginCount(oldUser.getLoginCount()==null?0:oldUser.getLoginCount() + 1); +// user.setUpdateDate(curr); +// user.updateTenantInfo(oldUser); +// // TODO 是否其他信息需要更新 +// ret = wxCUserMapper.updateById(user); +// return ret; +// } +// } + final IdWorker idWorker = IdWorker.get(); + user.setId(idWorker.nextId()); + user.setLoginCount(1); + user.setCreateDate(curr); + user.setUpdateDate(curr); + ret = ttCUserMapper.insert(user); + } else { + user.setUpdateDate(curr); + ret = ttCUserMapper.updateById(user); + } + + return ret; + } + + @Override + public int updateScene(TtCUser record) { + Date curr = new Date(); + TtCUser userL = new TtCUser(); + userL.setId(record.getId()); + userL.setScene(record.getScene()); + userL.setUpdateDate(curr); + int ret = ttCUserMapper.updateById(userL); + String key = Constant.tokenPrev + record.getToken(); + if(baseCUserTokenRedisTemplate.hasKey(key)){ + baseCUserTokenRedisTemplate.delete(key); + } + return ret; + } + + @Override + public int updateLBS(TtCUser record) { + Date curr = new Date(); + TtCUser userL = new TtCUser(); + userL.setId(record.getId()); + userL.setLongitude(record.getLongitude()); + userL.setLatitude(record.getLatitude()); + userL.setUpdateDate(curr); + int ret = ttCUserMapper.updateById(userL); + String key = Constant.tokenPrev + record.getToken(); + if(baseCUserTokenRedisTemplate.hasKey(key)){ + baseCUserTokenRedisTemplate.delete(key); + } + return ret; + } + + @Override + public int updateExtInfo(TtCUser record) { + Date curr = new Date(); + TtCUser userL = new TtCUser(); + userL.setId(record.getId()); + userL.setExtraInfo(record.getExtraInfo()); + userL.setUpdateDate(curr); + int ret = ttCUserMapper.updateById(userL); + String key = Constant.tokenPrev + record.getToken(); + if(baseCUserTokenRedisTemplate.hasKey(key)){ + baseCUserTokenRedisTemplate.delete(key); + } + return ret; + } + +// @Override +// public void deleteById(Long id,String tenantId) { +// wxCUserMapper.deleteById(id,tenantId); +// } + + @Override + public long findCount(WxCUserBasicInfoDto dto, List tenantEntitys) { + long count = 0l; + for (TenantEntity tenantEntity:tenantEntitys) { + dto.updateTenantInfo(tenantEntity); + long count1 = ttCUserMapper.findCount(dto); + count += count1; + } + return count; + } + + @Override + public List findCountHistory(WxCUserBasicInfoDto dto, List tenantEntitys) { + return ttCUserMapper.findCountHistory(tenantEntitys,dto); + } + + @Override + public PageInfo listByChannel(TtCUser user, List tenantEntitys, Integer pageIndex, Integer pageSize) { + return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> ttCUserMapper.listByChannel(tenantEntitys,user)); + } + + @Override + public long countByChannel(List tenantEntitys, TtCUser user) { + return ttCUserMapper.countByChannel(tenantEntitys, user); + } + + @Override + public void actionMsgAfterLogin(WxCUserFrom wxCUserFrom) { + wxCUserFrom.setCreateDate(new Date()); + FmInsideCLoginMsg loginMsg = new FmInsideCLoginMsg(); + loginMsg.updateTenantInfo(wxCUserFrom); + loginMsg.setMsgType(EnumMsgRecordType.INSIDE_C_LOGIN.getCode()); + loginMsg.setWxCUserFrom(wxCUserFrom); + mqBaseProducer.sendMessage(loginMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + } + + + @Override + public int actionAfterLogin(TtCUser user) { + int score = 0; + int credit = 0; + // 成长值 + try { + score = wxScoreRulesService.addScore(user,EnumScoreType.LOGIN, user); + } catch (MallinkException e) { + logger.error("c_user 成长值 " + e.getMessage()); + } catch (Exception e) { + logger.error("c_user 成长值 " + e.getMessage()); + } + // 积分 +// try { +// credit = addCredit(user, EnumScoreType.LOGIN); +// logger.info("user_id:" + user.getId() + " 登录新增积分:" + credit); +// } catch (MallinkException e) { +// logger.error("c_user 积分 " + e.getMessage()); +// } catch (Exception e) { +// logger.error("c_user 积分 " + e.getMessage()); +// } + + // 用户登陆后 更新最后一次活跃时间 + if (user.getUserId() != null) { + WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(user.getUserId(),user.getFinalTenantId()); + if (wxCUserBasicInfo != null) { + WxCUserBasicInfo basicInfo = new WxCUserBasicInfo(); + basicInfo.setId(wxCUserBasicInfo.getId()); + basicInfo.setFinalTenantId(user.getFinalTenantId()); + basicInfo.setActiveTime(new Date()); + int loingcount = 0; + try { + loingcount = Integer.parseInt(wxCUserBasicInfo.getLoginCount().toString()); + }catch(Exception e) { + } + basicInfo.setLoginCount(loingcount+1); + wxCUserBasicInfoService.update(basicInfo); + + wxCUserTagsService.triggerAssignTags(EnumAssignTagsTrigger.ASSIGN_TAGS_TRIGGER_LOGIN, user,user); + } +// WxCUser wxCUser = getById(user.getId(),user.getTenantId()); +// if (wxCUser != null) { +// WxCUser cUser = new WxCUser(); +// cUser.setId(user.getId()); +// cUser.setActiveTime(new Date()); +// cUser.setTenantId(user.getTenantId()); +// saveOrUpdate(cUser); +// } + + } + String key = Constant.tokenPrev + user.getToken(); + if(baseCUserTokenRedisTemplate.hasKey(key)){ + baseCUserTokenRedisTemplate.delete(key); + } + return score; + } + + @Override + public void updateUserId(TtCUser user) { + ttCUserMapper.updateUserId(user); + } + + @Override + public void delForUserIdOnly(Long id, Long userId, String tenantId) { + ttCUserMapper.delForUserIdOnly(id,userId,tenantId); + } + + @Override + public void updateMsgCount(TtCUser user) { + ttCUserMapper.updateMsgCount(user); + } + +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCUserBasicInfoServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCUserBasicInfoServiceImpl.java index d5cc3aabb..d9cac6379 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCUserBasicInfoServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCUserBasicInfoServiceImpl.java @@ -655,6 +655,24 @@ public class WxCUserBasicInfoServiceImpl implements WxCUserBasicInfoService,IExc } + @Override + public int addCredit(Long userId, TenantEntity tenantInfo, EnumScoreType enumScoreType) { + if(userId == null){ + return 0; + } + WxCreditHistory wxCreditHistory = new WxCreditHistory(); + wxCreditHistory.setCUserId(userId); + wxCreditHistory.setTenantId(tenantInfo.getFinalTenantId()); + wxCreditHistory.setFinalTenantId(tenantInfo.getFinalTenantId()); + wxCreditHistory.setCreateDate(new Date()); + wxCreditHistory.setCreditType(enumScoreType.getCode()); + wxCreditHistory.setChangePurpose(enumScoreType.getMessage()); + wxCreditHistory.setOperatorType(EnumUserType.CUSERBASIC.getCode()); + wxCreditHistory.setOperatorId(userId); + WxCreditHistory record = wxCreditHistoryService.saveOrUpdate(wxCreditHistory,tenantInfo.getTenantId()); + return record.getCreditAmount(); + } + @Override public WxCUserBasicInfo getById(Long id,String finalTenantId) { diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCUserServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCUserServiceImpl.java index 9bbcd3857..c1d7878de 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCUserServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCUserServiceImpl.java @@ -41,9 +41,6 @@ public class WxCUserServiceImpl implements WxCUserService { @Autowired private WxScoreRulesService wxScoreRulesService; - @Autowired - private WxCreditHistoryService wxCreditHistoryService; - @Autowired private WxCUserTagsService wxCUserTagsService; @@ -317,24 +314,6 @@ public class WxCUserServiceImpl implements WxCUserService { return score; } - @Override - public int addCredit(WxCUser user, EnumScoreType enumScoreType) { - if(user.getUserId() == null){ - return 0; - } - WxCreditHistory wxCreditHistory = new WxCreditHistory(); - wxCreditHistory.setCUserId(user.getUserId()); - wxCreditHistory.setTenantId(user.getFinalTenantId()); - wxCreditHistory.setFinalTenantId(user.getFinalTenantId()); - wxCreditHistory.setCreateDate(new Date()); - wxCreditHistory.setCreditType(enumScoreType.getCode()); - wxCreditHistory.setChangePurpose(enumScoreType.getMessage()); - wxCreditHistory.setOperatorType(EnumUserType.CUSERBASIC.getCode()); - wxCreditHistory.setOperatorId(user.getUserId()); - WxCreditHistory record = wxCreditHistoryService.saveOrUpdate(wxCreditHistory,user.getTenantId()); - return record.getCreditAmount(); - } - @Override public void updateUserId(WxCUser user) { wxCUserMapper.updateUserId(user); diff --git a/mallinkService/src/main/java/com/iformall/utils/Constant.java b/mallinkService/src/main/java/com/iformall/utils/Constant.java index fcd5304d7..216646818 100644 --- a/mallinkService/src/main/java/com/iformall/utils/Constant.java +++ b/mallinkService/src/main/java/com/iformall/utils/Constant.java @@ -39,6 +39,7 @@ public class Constant { public static final String tokenPrev = "weapp:token:"; public static final String TOKEN_WXC_END = ":wx-cuser"; + public static final String TOKEN_TTC_END = ":tt-cuser"; public static final String cuserQr = "weapp:cuser-qr:"; diff --git a/mallinkService/src/main/java/com/iformall/utils/MaUtil.java b/mallinkService/src/main/java/com/iformall/utils/MaUtil.java index a15d671a9..0f15e9d29 100644 --- a/mallinkService/src/main/java/com/iformall/utils/MaUtil.java +++ b/mallinkService/src/main/java/com/iformall/utils/MaUtil.java @@ -9,6 +9,8 @@ import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import com.iformall.common.FmHttpClientBuilder; import com.iformall.domain.po.WxAppinfo; import com.iformall.domain.po.WxPayAccount; +import com.iformall.douyin.miniapp.api.TtMaService; +import com.iformall.douyin.miniapp.api.impl.TtMaServiceImpl; import org.apache.commons.lang3.StringUtils; public class MaUtil { @@ -52,4 +54,21 @@ public class MaUtil { wxPayService.setConfig(config); return wxPayService; } + + static public TtMaService getTtappService(WxAppinfo appinfo) { + WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); + config.setAppid(appinfo.getAppId()); + config.setSecret(appinfo.getSecret()); + config.setToken(appinfo.getToken()); + config.setAesKey(appinfo.getAesKey()); + config.setMsgDataFormat(appinfo.getMsgDataFormat()); + if (StringUtils.isNotBlank(appinfo.getAccessToken())) { + config.setAccessToken(appinfo.getAccessToken()); + config.setExpiresTime(appinfo.getLastTokenTime().getTime()+appinfo.getExpiresIn()*1000); + } + config.setApacheHttpClientBuilder(FmHttpClientBuilder.get()); + TtMaService service = new TtMaServiceImpl(); + service.setWxMaConfig(config); + return service; + } } diff --git a/mallinkService/src/main/resources/mapper/TtCUserMapper.xml b/mallinkService/src/main/resources/mapper/TtCUserMapper.xml new file mode 100644 index 000000000..b3c954d07 --- /dev/null +++ b/mallinkService/src/main/resources/mapper/TtCUserMapper.xml @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `id`,`user_id`,`tenant_id`,`parent_tenant_id`,`open_id`,`union_id`,`nick_name`,`gender`,`avatar_url`,`phone`,`pure_phone`, + `city`,`province`,`language`,`country_code`,`register_ip`,`verify_code_phone`, + `qrcode_source`,`scene`,`scene_address`,`session_key`,`score`, + `update_date`,`create_date`,`app_id`,`token`,`expire_time`,`latitude`, `longitude`, + `login_count`, `extra_info`, `is_subscribe`, + `open_app_id`, + `mp_open_id`,`mp_app_id`,`mp_subscribe`,`mp_subscribe_time`,`mp_subscribe_scene`, + `subs_open_id`,`subs_app_id`,`subs_subscribe`,`subs_subscribe_time`,`subs_subscribe_scene`,`credit`,`active_time` + + + + where 1 = 1 + + + and `id` = #{id} + + + + and `user_id` = #{userId} + + + + and `tenant_id` = #{tenantId} + + + and `parent_tenant_id` = #{parentTenantId} + + + + and `open_id` = #{openId} + + + + and `union_id` = #{unionId} + + + + and `nick_name` like concat('%', #{nickName},'%') + + + + and `gender` = #{gender} + + + + and `avatar_url` like concat('%', #{avatarUrl},'%') + + + + and `phone` like concat('%', #{phone},'%') + + + + and `pure_phone` like concat('%', #{purePhone},'%') + + + + and `city` like concat('%', #{city},'%') + + + + and `province` like concat('%', #{province},'%') + + + + and `language` like concat('%', #{language},'%') + + + + and `country_code` like concat('%', #{countryCode},'%') + + + + and `register_ip` like concat('%', #{registerIp},'%') + + + + and `verify_code_phone` like concat('%', #{verifyCodePhone},'%') + + + + and `qrcode_source` like concat('%', #{qrcodeSource},'%') + + + + and `scene` like concat('%', #{scene},'%') + + + + and `scene_address` like concat('%', #{sceneAddress},'%') + + + + and `session_key` like concat('%', #{sessionKey},'%') + + + + and `score` = #{score} + + + + and `update_date` = #{updateDate} + + + + and `create_date` = #{createDate} + + + + and `app_id` like concat('%', #{appId},'%') + + + + and `token` like concat('%', #{token},'%') + + + + and `expire_time` = #{expireTime} + + + + and `latitude` = #{latitude} + + + + and `longitude` = #{longitude} + + + + and `login_count` = #{loginCount} + + + + and `extra_info` = #{extraInfo} + + + + and `is_subscribe` = #{isSubscribe} + + + + and `open_app_id` = #{openAppId} + + + + and `mp_open_id` = #{mpOpenId} + + + + and `mp_app_id` = #{mpAppId} + + + + and `subs_open_id` = #{subsOpenId} + + + + and `subs_app_id` = #{subsAppId} + + + + and `credit` = #{credit} + + + + and id in + + #{idItem} + + + order by ${sortColumns} + + + + + + + + + update tt_c_user set msg_count = msg_count+2 + where 1=1 + + and `id` = #{id} + + + and `open_id` = #{openId} + + + and `tenant_id` = #{tenantId} + + + and `parent_tenant_id` = #{parentTenantId} + + + + + update tt_c_user set msg_count = msg_count-1 + where msg_count > 0 + + and `tenant_id` = #{tenantId} + + and `open_id` = #{openId} + + + + + + + + + + + + + + + + + + + + + + + update tt_c_user set user_id=#{userId} + where id = #{id} + + + + update tt_c_user set update_date=now(), + token = null, + expire_time=now(), + tenant_id = IF(tenant_id is null ,null,CONCAT(tenant_id,"_del")), + parent_tenant_id = IF(parent_tenant_id is null ,null,CONCAT(parent_tenant_id,"_del")), + open_id = IF(open_id is null ,null,CONCAT(open_id,"_del")), + union_id = IF(union_id is null ,null,CONCAT(union_id,"_del")) + where user_id = #{userId} and tenant_id = #{tenantId} and id != #{id} + + + diff --git a/mallinkTTAdmin/pom.xml b/mallinkTTAdmin/pom.xml new file mode 100644 index 000000000..c096fcd56 --- /dev/null +++ b/mallinkTTAdmin/pom.xml @@ -0,0 +1,191 @@ + + + 4.0.0 + + + mallink + com.iformall + 1.0 + + + mallinkTTAdmin + + + 3.7.0.B + 3.7.0.B + + + + + com.iformall + mallinkService + 1.0 + + + com.iformall + mallinkVideo + 1.0 + + + commons-fileupload + commons-fileupload + 1.3.3 + + + + com.google.zxing + core + 3.3.3 + + + + com.github.axet + kaptcha + 0.0.9 + + + + org.flywaydb + flyway-core + 5.2.4 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + ZIP + + antlr, + cn.afterturn, + ch.qos.logback, + com.alibaba, + com.amazonaws, + com.baomidou, + com.mchange, + com.fasterxml.jackson.core, + com.fasterxml.jackson.dataformat, + com.fasterxml.jackson.datatype, + com.fasterxml.jackson.module, + com.fasterxml.uuid, + com.fasterxml, + com.github.axet, + com.github.jsqlparser, + com.github.pagehelper, + com.github.ulisesbocchio, + com.github.virtuald, + com.google.code.findbugs, + com.google.code.gson, + com.google.errorprone, + com.google.guava, + com.google.protobuf, + com.google.zxing, + com.jayway.jsonpath, + com.jhlabs, + com.puppycrawl.tools, + com.rabbitmq, + com.squareup.okhttp3, + com.squareup.okio, + com.sun, + com.sun.mail, + com.thoughtworks.xstream, + com.zaxxer, + commons-beanutils, + commons-cli, + commons-codec, + commons-collections, + commons-fileupload, + commons-io, + commons-logging, + io.lettuce, + io.netty, + io.projectreactor, + io.springfox, + io.swagger, + io.undertow, + javax.activation, + javax.annotation, + javax.mail, + javax.persistence, + javax.servlet, + javax.validation, + javax.xml.bind, + javax.xml.soap, + javax.xml.ws, + joda-time, + junit, + mysql, + net.bytebuddy, + net.minidev, + net.sf.dozer, + net.sf.saxon, + ognl, + org.antlr, + org.apache.commons, + org.apache.httpcomponents, + org.apache.logging.log4j, + org.apache.poi, + org.apache.poi.wso2, + org.apache.rocketmq, + org.apache.shiro, + org.apache.tomcat.embed, + org.apache.xmlbeans, + org.aspectj, + org.assertj, + org.bouncycastle, + org.checkerframework, + org.codehaus.mojo, + org.crazycake, + org.dom4j, + org.flowable, + org.flywaydb, + org.glassfish, + org.hibernate.validator, + org.jasypt, + org.javassist, + org.jboss.logging, + org.jboss.spec.javax.annotation, + org.jboss.spec.javax.websocket, + org.jboss.xnio, + org.jdom, + org.jodd, + org.jvnet.mimepull, + org.jvnet.staxex, + org.mapstruct, + org.mockito, + org.mybatis, + org.mybatis.generator, + org.mybatis.spring.boot, + org.ow2.asm, + org.projectlombok, + org.quartz-scheduler, + org.reactivestreams, + org.reflections, + org.rocketmq.spring.boot, + org.slf4j, + org.springframework, + org.springframework.amqp, + org.springframework.boot, + org.springframework.data, + org.springframework.retry, + org.springframework.ws, + org.yaml, + redis.clients, + software.amazon.ion, + tk.mybatis, + xmlpull, + xpp3 + + + + + + + \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/TTAdminApplication.java b/mallinkTTAdmin/src/main/java/com/iformall/TTAdminApplication.java new file mode 100644 index 000000000..941166e64 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/TTAdminApplication.java @@ -0,0 +1,76 @@ +package com.iformall; + +import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; +import org.mybatis.spring.annotation.MapperScan; +import org.rocketmq.starter.annotation.EnableRocketMQ; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableAsync; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * @author chenkx + * @date 2017-12-26 + */ +@SpringBootApplication +@MapperScan(basePackages = {"com.iformall.mapper"}) +@EnableSwagger2 +@EnableEncryptableProperties +@EnableAsync +@EnableRocketMQ +public class TTAdminApplication { + + @Value("${fm.exception}") + private boolean fmException; + + @Value("${fm.exception_emails}") + private String fmExceptionEmails; + + @Value("${fm.open}") + private boolean fmOpen; + + @Value("${fm.upload_dir}") + private String uploadDir; + + @Value("${fm.ocr_data}") + private String ocrData; + + @Value("${fm.videoType}") + private String videoType; + + @Bean + public boolean isFmException() { + return fmException; + } + + @Bean + public String fmExceptionEmails() { + return fmExceptionEmails; + } + + @Bean + public boolean isFmOpen() { + return fmOpen; + } + + @Bean + public String fmUploadDir() { + return uploadDir; + } + + @Bean + public String ocrData() { + return ocrData; + } + + @Bean + public String videoType() { + return videoType; + } + + public static void main(String[] args) { + SpringApplication.run(TTAdminApplication.class, args); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/annotation/SystemControllerLog.java b/mallinkTTAdmin/src/main/java/com/iformall/annotation/SystemControllerLog.java new file mode 100644 index 000000000..61821c134 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/annotation/SystemControllerLog.java @@ -0,0 +1,10 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SystemControllerLog { + String description() default ""; +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/annotation/SystemServiceLog.java b/mallinkTTAdmin/src/main/java/com/iformall/annotation/SystemServiceLog.java new file mode 100644 index 000000000..f2cd84adf --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/annotation/SystemServiceLog.java @@ -0,0 +1,10 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SystemServiceLog { + String description() default ""; +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/annotation/TenantIgnore.java b/mallinkTTAdmin/src/main/java/com/iformall/annotation/TenantIgnore.java new file mode 100644 index 000000000..2623b71e2 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/annotation/TenantIgnore.java @@ -0,0 +1,16 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +/** + * api接口,忽略Token验证 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:44 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TenantIgnore { + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/annotation/UserDataRuleAnnotation.java b/mallinkTTAdmin/src/main/java/com/iformall/annotation/UserDataRuleAnnotation.java new file mode 100644 index 000000000..f59938850 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/annotation/UserDataRuleAnnotation.java @@ -0,0 +1,14 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +/** + * @author gongbiao + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface UserDataRuleAnnotation { + + String value() default ""; +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/AwsProperty.java b/mallinkTTAdmin/src/main/java/com/iformall/config/AwsProperty.java new file mode 100644 index 000000000..0329f1d6d --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/AwsProperty.java @@ -0,0 +1,52 @@ +package com.iformall.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author Stormeye + */ +@Component +@ConfigurationProperties(prefix = "aws") +public class AwsProperty { + // AWS ACCESS KEY + private String access; + + private String secret; + + private String clientRegion; + + private String bucketName; + + public String getAccess() { + return access; + } + + public void setAccess(String access) { + this.access = access; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getClientRegion() { + return clientRegion; + } + + public void setClientRegion(String clientRegion) { + this.clientRegion = clientRegion; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/KaptchaConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/KaptchaConfig.java new file mode 100644 index 000000000..8d20c0893 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/KaptchaConfig.java @@ -0,0 +1,32 @@ +package com.iformall.config; + +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + + +/** + * 生成验证码配置 + * + * @author stormeye.wu + * @email wugq@mippoint.com + * @date 2017-04-20 19:22 + */ +@Configuration +public class KaptchaConfig { + + @Bean + public DefaultKaptcha producer() { + Properties properties = new Properties(); + properties.put("kaptcha.border", "no"); + properties.put("kaptcha.textproducer.font.color", "black"); + properties.put("kaptcha.textproducer.char.space", "5"); + Config config = new Config(properties); + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/MyBatisConfiguration.java b/mallinkTTAdmin/src/main/java/com/iformall/config/MyBatisConfiguration.java new file mode 100644 index 000000000..b3ae60fbd --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/MyBatisConfiguration.java @@ -0,0 +1,31 @@ +package com.iformall.config; + +import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; +import com.iformall.plugin.MyBatisItercepters; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@EnableTransactionManagement +@Configuration +public class MyBatisConfiguration extends BaseMyBatisConfiguration{ + + + @Bean + public MyBatisItercepters intercepters() { + return new MyBatisItercepters(); + } + + @Bean + public PaginationInterceptor paginationInterceptor() { + PaginationInterceptor page = new PaginationInterceptor(); + page.setDialectType("mysql"); + return page; + } + + @Bean + public OptimisticLockerInterceptor optimisticLockerInterceptor() { + return new OptimisticLockerInterceptor(); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/MyExecutorConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/MyExecutorConfig.java new file mode 100644 index 000000000..c60425e84 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/MyExecutorConfig.java @@ -0,0 +1,26 @@ +package com.iformall.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ThreadPoolExecutor; + +@Configuration +public class MyExecutorConfig { + /** + * 自定义异步线程池 + * + * @return + */ + @Bean + public AsyncTaskExecutor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setThreadNamePrefix("Anno-Executor"); + executor.setMaxPoolSize(100); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } +} + diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/RedisConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/RedisConfig.java new file mode 100644 index 000000000..f38bb2302 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/RedisConfig.java @@ -0,0 +1,347 @@ +package com.iformall.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.pagehelper.PageInfo; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.domain.vo.WxCouponCVo; +import com.iformall.domain.vo.WxCouponChannelVo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; +import java.util.*; + +/** + * Created by Stormeye on 2018/10/1. + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + //缓存管理器 + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + /* + //user信息缓存配置 + RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user"); + Map redisCacheConfigurationMap = new HashMap<>(); + redisCacheConfigurationMap.put("user", userCacheConfiguration); + //初始化一个RedisCacheWriter + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + // 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现 + // ClassLoader loader = this.getClass().getClassLoader(); + // JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader); + // RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer); + // RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); + RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); + //设置默认超过期时间是30秒 + defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); + //初始化RedisCacheManager + RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); + return cacheManager; + */ + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置 + config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置 + .disableCachingNullValues(); // 不缓存空值 + + // 设置一个初始化的缓存空间set集合 + Set cacheNames = new HashSet<>(); + cacheNames.add("my-redis-cache1"); + cacheNames.add("my-redis-cache2"); + + // 对每个缓存空间应用不同的配置 + Map configMap = new HashMap<>(); + configMap.put("my-redis-cache1", config); + configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120))); + + RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory) // 使用自定义的缓存配置初始化一个cacheManager + .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置 + .withInitialCacheConfigurations(configMap) + .build(); + return cacheManager; + } + + @Bean("pushLimitRedisTemplate") + public RedisTemplate getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(PushLimit.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("scoreRuleRedisTemplate") + public RedisTemplate getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxScoreRules.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("openRedisTemplate") + public RedisTemplate getWeChatOpen(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + // value值的序列化 + template.setValueSerializer(new StringRedisSerializer()); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("cuserTokenRedisTemplate") + public RedisTemplate getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCUser.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("baseCUserTokenRedisTemplate") + public RedisTemplate getBaseCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(BaseCUserEntity.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("mallRedisTemplate") + public RedisTemplate getMallRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxMall.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("subMallListRedisTemplate") + public RedisTemplate> getSubMallListRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate> template = new RedisTemplate>(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(List.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("couponChannelRedisTemplate") + public RedisTemplate> getCouponChannelRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate> template = new RedisTemplate<>(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(PageInfo.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("buserTokenRedisTemplate") + public RedisTemplate getBuserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxBuser.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("couponDetailRedisTemplate") + public RedisTemplate getCouponDetailRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCouponCVo.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("cUserBasicInfoRedisTemplate") + public RedisTemplate getCUserBasicInfoRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCUserBasicInfo.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("objectCommonRedisTemplate") + public RedisTemplate getObjectValueOperations(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + return template; + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/RestFilter.java b/mallinkTTAdmin/src/main/java/com/iformall/config/RestFilter.java new file mode 100644 index 000000000..4f9298433 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/RestFilter.java @@ -0,0 +1,58 @@ +package com.iformall.config; + +import java.io.IOException; +import java.util.Optional; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 前后端分离RESTful接口过滤器 + * + * @author xuguoqin + * + */ +public class RestFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = null; + if (request instanceof HttpServletRequest) { + req = (HttpServletRequest) request; + } + HttpServletResponse res = null; + if (response instanceof HttpServletResponse) { + res = (HttpServletResponse) response; + } + if (req != null && res != null) { + //设置允许传递的参数 + res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); + //设置允许带上cookie + res.setHeader("Access-Control-Allow-Credentials", "true"); + String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer")); + //设置允许的请求来源 + res.setHeader("Access-Control-Allow-Origin", origin); + //设置允许的请求方法 + res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS"); + } + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/RestTemplateConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/RestTemplateConfig.java new file mode 100644 index 000000000..560a77cb5 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/RestTemplateConfig.java @@ -0,0 +1,24 @@ +package com.iformall.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { + return new RestTemplate(factory); + } + + @Bean + public ClientHttpRequestFactory simpleClientHttpRequestFactory() { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setReadTimeout(5000);//ms + factory.setConnectTimeout(10000);//ms + return factory; + } +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/ShiroConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/ShiroConfig.java new file mode 100644 index 000000000..7e16e23c8 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/ShiroConfig.java @@ -0,0 +1,321 @@ +package com.iformall.config; + +import com.iformall.service.MallPermissionService; +import com.iformall.shiro.MyRetryLimitCredentialsMatcher; +import com.iformall.shiro.MyShiroRealm; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.crazycake.shiro.RedisCacheManager; +import org.crazycake.shiro.RedisManager; +import org.crazycake.shiro.RedisSessionDAO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * Created by yangqj on 2017/4/23. + */ +@Configuration +public class ShiroConfig { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private int port; + + @Value("${spring.redis.timeout}") + private int timeout; + + @Value("${spring.redis.expire}") + private int expire; + + @Value("${spring.redis.password}") + private String password; + + @Bean + public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + /** + * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean + * @return + */ +// @Bean +// public ShiroDialect shiroDialect() { +// return new ShiroDialect(); +// } + + /** + * ShiroFilterFactoryBean 处理拦截资源文件问题。 + * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在 + * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager + *

+ * Filter Chain定义说明 + * 1、一个URL可以配置多个Filter,使用逗号分隔 + * 2、当设置多个过滤器时,全部验证通过,才视为通过 + * 3、部分过滤器可指定参数,如perms,roles + */ + @Bean + public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { + System.out.println("ShiroConfiguration.shirFilter()"); + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + // 必须设置 SecurityManager + shiroFilterFactoryBean.setSecurityManager(securityManager); + Map filters = new LinkedHashMap(); + filters.put("token", new ShiroLoginFilter()); + filters.put("corsFilter", new RestFilter()); + //filters.put("authc", new MyFormAuthenticationFilter()); + shiroFilterFactoryBean.setFilters(filters); + // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 + shiroFilterFactoryBean.setLoginUrl("/#/"); + // 登录成功后要跳转的链接 + shiroFilterFactoryBean.setSuccessUrl("/usersPage"); + //未授权界面; + shiroFilterFactoryBean.setUnauthorizedUrl("/403"); + //拦截器. + Map filterChainDefinitionMap = new LinkedHashMap(); + + //filterChainDefinitionMap.put("/ue/**", "anon"); + //filterChainDefinitionMap.put("/config.json", "anon"); + // login + filterChainDefinitionMap.put("/doLogin/**", "anon"); + filterChainDefinitionMap.put("/bHidLogin/**", "anon"); + filterChainDefinitionMap.put("/sendLoginPhoneCode/**", "anon"); + filterChainDefinitionMap.put("/doLoginByPhone/**", "anon"); + filterChainDefinitionMap.put("/wechat/login", "anon"); // 微信第三方登录callback + filterChainDefinitionMap.put("/wechat/callback", "anon"); // 微信网页登录回调 + filterChainDefinitionMap.put("/wechat/weChatUserLogin", "anon"); // 微信第三方登录 + + // 验证码 + filterChainDefinitionMap.put("/captcha.jpg", "anon"); + // 官网 + filterChainDefinitionMap.put("/wxMallApply/add", "anon"); + // callback + filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); // 支付回调 + filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon"); + filterChainDefinitionMap.put("/wxMsgCallback/**", "anon"); + filterChainDefinitionMap.put("/user/sendvalidationcode", "anon"); + filterChainDefinitionMap.put("/user/updatepwd", "anon"); + filterChainDefinitionMap.put("/carCallback/**", "anon"); + filterChainDefinitionMap.put("/wxMallApply/sendvalidationcode", "anon"); + + // 补发消息 + filterChainDefinitionMap.put("/wxCoupon/updateStokeAndValidDate", "anon"); + + // static files + filterChainDefinitionMap.put("/css/**", "anon"); + filterChainDefinitionMap.put("/js/**", "anon"); + filterChainDefinitionMap.put("/img/**", "anon"); + filterChainDefinitionMap.put("/font-awesome/**", "anon"); + + //:这是一个坑呢,一不小心代码就不好使了; + // + //自定义加载权限资源关系 +// Map map = new HashMap<>(); +// List resourcesList = resourcesService.list(map); +// for(SysPermission resources:resourcesList){ +// +// if (StringUtil.isNotEmpty(resources.getUrl())) { +// String permission = "perms[" + resources.getUrl()+ "]"; +// filterChainDefinitionMap.put(resources.getUrl(),permission); +// } +// } + // swagger-ui + filterChainDefinitionMap.put("/swagger-ui.html", "anon"); + filterChainDefinitionMap.put("/v2/**", "anon"); + filterChainDefinitionMap.put("/swagger-resources/**", "anon"); + filterChainDefinitionMap.put("/webjars/**", "anon"); + + filterChainDefinitionMap.put("/version", "anon"); + filterChainDefinitionMap.put("/wxDeviceScreenAd/**", "anon"); +// filterChainDefinitionMap.put("/role/**", "corsFilter,token"); + //商场初始化init + filterChainDefinitionMap.put("/wxProjectConfig/**", "anon"); + + + //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 + filterChainDefinitionMap.put("/logout", "authc"); + + filterChainDefinitionMap.put("/**", "corsFilter,token,authc"); +// filterChainDefinitionMap.put("/**", "anon"); + + + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; + } + + + public static boolean isAjax(ServletRequest request) { + String header = ((HttpServletRequest) request).getHeader("X-Requested-With"); + if ("XMLHttpRequest".equalsIgnoreCase(header)) { + System.out.println("当前请求为Ajax请求"); + return Boolean.TRUE; + } + System.out.println("当前请求非Ajax请求"); + return Boolean.FALSE; + } + + @Bean + public SecurityManager securityManager() { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + //设置realm. + securityManager.setRealm(myShiroRealm()); + // 自定义缓存实现 使用redis + //securityManager.setCacheManager(cacheManager()); + // 自定义session管理 使用redis + securityManager.setSessionManager(sessionManager()); + return securityManager; + } + + @Bean + public MyShiroRealm myShiroRealm() { + MyShiroRealm myShiroRealm = new MyShiroRealm(); + myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); + return myShiroRealm; + } + + + /** + * 密码匹配凭证管理器 凭证匹配器 + * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 + * 所以我们需要修改下doGetAuthenticationInfo中的代码; + * ) + * + * @return + */ + public MyRetryLimitCredentialsMatcher hashedCredentialsMatcher() { + MyRetryLimitCredentialsMatcher hashedCredentialsMatcher = new MyRetryLimitCredentialsMatcher(); + + hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; + hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); + + return hashedCredentialsMatcher; + } + + + /** + * 开启shiro aop注解支持. + * 使用代理方式;所以需要开启代码支持; + * + * @param securityManager + * @return + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } + + /** + * 配置shiro redisManager + * 使用的是shiro-redis开源插件 + * + * @return + */ + public RedisManager redisManager() { + RedisManager redisManager = new RedisManager(); + redisManager.setHost(host); + redisManager.setPort(port); + //redisManager.setExpire(expire);// 配置缓存过期时间 + redisManager.setTimeout(timeout); + redisManager.setPassword(password); + return redisManager; + } + + /** + * cacheManager 缓存 redis实现 + * 使用的是shiro-redis开源插件 + * + * @return + */ + public RedisCacheManager cacheManager() { + RedisCacheManager redisCacheManager = new RedisCacheManager(); + redisCacheManager.setRedisManager(redisManager()); + return redisCacheManager; + } + + + /** + * RedisSessionDAO shiro sessionDao层的实现 通过redis + * 使用的是shiro-redis开源插件 + */ + @Bean + public RedisSessionDAO redisSessionDAO() { + RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); + redisSessionDAO.setRedisManager(redisManager()); + return redisSessionDAO; + } + + /** + * shiro session的管理 + */ + @Bean + public DefaultWebSessionManager sessionManager() { + DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); + //设置session过期时间为1小时(单位:毫秒),默认为30分钟 + sessionManager.setGlobalSessionTimeout(60 * 60 * 1000); + sessionManager.setSessionValidationSchedulerEnabled(true); + sessionManager.setSessionIdUrlRewritingEnabled(false); + + sessionManager.setSessionDAO(redisSessionDAO()); + sessionManager.setSessionIdCookie(simpleCookie()); + return sessionManager; + } + + @Bean + public SimpleCookie simpleCookie() { + SimpleCookie simpleCookie = new SimpleCookie("SSIDS"); + simpleCookie.setDomain(""); + return simpleCookie; + } + +// @Bean +// public SimpleCookie rememberMeCookie(){ +// //System.out.println("ShiroConfiguration.rememberMeCookie()"); +// //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe +// SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); +// // +// simpleCookie.setMaxAge(60*30); +// return simpleCookie; +// } + +// @Bean +// public CookieRememberMeManager rememberMeManager(){ +// //System.out.println("ShiroConfiguration.rememberMeManager()"); +// CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); +// cookieRememberMeManager.setCookie(rememberMeCookie()); +// //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) +// cookieRememberMeManager.setCipherKey(Base64.decodeBytes("2AvVhdsgUs0FSA3SDFAdag==")); +// return cookieRememberMeManager; +// } + +// @Bean(name = "securityManager") +// public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm){ +// DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); +// //设置realm +// securityManager.setRealm(realm); +// //用户授权/认证信息Cache, 采用EhCache缓存 +// securityManager.setCacheManager(cacheManager()); +// //注入记住我管理器 +// securityManager.setRememberMeManager(rememberMeManager()); +// return securityManager; +// } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/ShiroLoginFilter.java b/mallinkTTAdmin/src/main/java/com/iformall/config/ShiroLoginFilter.java new file mode 100644 index 000000000..67c07385e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/ShiroLoginFilter.java @@ -0,0 +1,31 @@ +package com.iformall.config; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; + +import com.alibaba.fastjson.JSON; +import com.iformall.common.ResultData; +public class ShiroLoginFilter extends FormAuthenticationFilter { + + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + ResultData resultData = new ResultData(ResultData.UNLOGIN,"用户未登录"); + response.getWriter().write(JSON.toJSONString(resultData)); + return false; + } + + /** + * 判断ajax请求 + * @param request + * @return + */ + boolean isAjax(HttpServletRequest request){ + return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) ) ; + } + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/Swagger2Config.java b/mallinkTTAdmin/src/main/java/com/iformall/config/Swagger2Config.java new file mode 100644 index 000000000..335b86b7b --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/Swagger2Config.java @@ -0,0 +1,61 @@ +package com.iformall.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Parameter; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.RelativePathProvider; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import javax.servlet.ServletContext; +import java.util.ArrayList; +import java.util.List; + +//参考:http://blog.csdn.net/catoop/article/details/50668896 +@Configuration +@EnableSwagger2 +public class Swagger2Config { + + @Autowired + private ServletContext servletContext; + + @Bean + public Docket createRestApi() { + ParameterBuilder tokenPar = new ParameterBuilder(); + List pars = new ArrayList(); + //增加一个request的header参数 + tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); + pars.add(tokenPar.build()); + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.iformall.controller")) + .paths(PathSelectors.any()) + .build() + .globalOperationParameters(pars) + .pathProvider(new RelativePathProvider(servletContext) { + @Override + public String getApplicationBasePath() { + return "/api"; + } + }); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("a端 api") + .description("a api") + .termsOfServiceUrl("http://localhost:7000") + .version("2.0") + .build(); + } + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/WebConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/WebConfig.java new file mode 100644 index 000000000..d4e06206b --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/WebConfig.java @@ -0,0 +1,164 @@ +package com.iformall.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.iformall.file.aliyun.AliyunOSS; +import com.iformall.interceptor.CurrentTenantInterceptor; +import com.iformall.interceptor.HttpServletRequestWrapperFilter; +import com.iformall.interceptor.RequestInterceptor; +import com.iformall.service.MallResourceService; +import com.iformall.ueditor.ActionEnter; +import com.iformall.ueditor.ConfigManager; +import com.iformall.ueditor.UEditorConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CharacterEncodingFilter; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.*; + +import javax.servlet.Filter; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.List; + +@Configuration +@EnableWebMvc +@EnableConfigurationProperties({UEditorConfig.class, AwsProperty.class}) +public class WebConfig implements WebMvcConfigurer { + @Autowired + private UEditorConfig uEditorConfig; + + @Autowired + private AwsProperty awsProperty; + + @Autowired + private RequestInterceptor requestInterceptor; + + @Autowired + private CurrentTenantInterceptor tenantInterceptor; + + @Autowired + private MallResourceService mallResourceService; + + @Autowired + private AliyunOSS aliyunOSS; + + @Bean + @ConditionalOnMissingBean(ActionEnter.class) + public ActionEnter actionEnter() { + ActionEnter actionEnter = new ActionEnter(ConfigManager.getInstance(uEditorConfig, awsProperty, mallResourceService, aliyunOSS)); + return actionEnter; + } + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + // 允许cookies跨域 + corsConfiguration.setAllowCredentials(true); + // 允许向该服务器提交请求的URI, *表示全部允许 + corsConfiguration.addAllowedOrigin("*"); + // 允许访问的头信息,*表示全部 + corsConfiguration.addAllowedHeader("*"); + // 允许提交请求的方法, *表示全部允许 + corsConfiguration.addAllowedMethod("*"); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); + } + + /** + * 用于处理编码问题 + * + * @return + */ + @Bean("myCharacterEncodingFilter") + public Filter characterEncodingFilter() { + CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); + characterEncodingFilter.setEncoding("UTF-8"); + characterEncodingFilter.setForceEncoding(true); + return characterEncodingFilter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(requestInterceptor).addPathPatterns("/**"); + registry.addInterceptor(tenantInterceptor).addPathPatterns("/**"); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("swagger-ui.html") + .addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + // ueditor + registry.addResourceHandler("/upload/**") + .addResourceLocations("file:" + uEditorConfig.getUploadPath()); + registry.addResourceHandler("/config.json").addResourceLocations("classpath:/config.json"); + + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + + @Override + public void configureMessageConverters(List> converters) { + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + //ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然 + ObjectMapper objectMapper = new ObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + + //不显示为null的字段 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + DeserializationConfig dc = objectMapper.getDeserializationConfig(); + // 设置反序列化日期格式、忽略不存在get、set的属性 + objectMapper.setConfig( + dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) + .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + ); + + //序列化将Long转String类型 + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + SimpleModule bigIntegerModule = new SimpleModule(); + //序列化将BigInteger转String类型 + bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance); + SimpleModule bigDecimalModule = new SimpleModule(); + //序列化将BigDecimal转String类型 + bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + objectMapper.registerModule(bigDecimalModule); + objectMapper.registerModule(bigIntegerModule); + jackson2HttpMessageConverter.setObjectMapper(objectMapper); + converters.add(jackson2HttpMessageConverter); + } + + @Bean + public FilterRegistrationBean Filters() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(new HttpServletRequestWrapperFilter()); + registrationBean.addUrlPatterns("/*"); + registrationBean.setName("koalaSignFilter"); + return registrationBean; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/WechatMpConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/config/WechatMpConfig.java new file mode 100644 index 000000000..4433386c9 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/WechatMpConfig.java @@ -0,0 +1,32 @@ +package com.iformall.config; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.WxMpConfigStorage; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Component +public class WechatMpConfig { + + @Autowired + private WechatWebProperties wechatWebProperties; + + @Bean + public WxMpService wxMpService() { + //创建WxMpService实例并设置appid和sectret + WxMpService wxMpService = new WxMpServiceImpl(); + //这里的设置方式是跟着这个sdk的文档写的 + wxMpService.setWxMpConfigStorage(wxConfigProvider()); + return wxMpService; + } + + public WxMpConfigStorage wxConfigProvider(){ + WxMpDefaultConfigImpl wxConfigProvider = new WxMpDefaultConfigImpl(); + wxConfigProvider.setAppId(wechatWebProperties.getAppId()); + wxConfigProvider.setSecret(wechatWebProperties.getSecret()); + return wxConfigProvider; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/config/WechatWebProperties.java b/mallinkTTAdmin/src/main/java/com/iformall/config/WechatWebProperties.java new file mode 100644 index 000000000..0b9047399 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/config/WechatWebProperties.java @@ -0,0 +1,59 @@ +package com.iformall.config; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * Stormeye + */ +@Component +@ConfigurationProperties(prefix = "wechat.web") +public class WechatWebProperties { + /** + * 设置微信第三方平台-微信登录的web应用appid + */ + private String appId; + + /** + * 设置微信第三方平台-微信登录的web应用app secret + */ + private String secret; + + /** + * 网页URL + * @return + */ + private String url; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, + ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/base/BaseController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/base/BaseController.java new file mode 100644 index 000000000..37d7924ed --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/base/BaseController.java @@ -0,0 +1,114 @@ +package com.iformall.controller.base; + +import java.beans.PropertyEditorSupport; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.shiro.UserSession; +import com.iformall.utils.IPUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; + +@RestController +public class BaseController { + + @InitBinder + public void InitBinder(WebDataBinder dataBinder) { + dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { + public void setAsText(String value) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)); + } catch(ParseException e) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value)); + } catch (ParseException e1) { + setValue(null); + } + } + } + + public String getAsText() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue()); + } + + }); + } + public MallUserInfo getUser(){ + MallUserInfo user = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + return user; + } + + public Long getUserId(){ + Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userId); + return userId; + } + +// @Deprecated +// public String getTenantId(){ +// String tenantId = (String)SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId); +// return tenantId; +// } + + /** + * 返回租户信息 + * 集团版帐号tenantId为空,parentTenantId为集团tenantId + * @return + */ + public TenantEntity getTenantInfo(){ + Session session = SecurityUtils.getSubject().getSession(); + String tenantId = (String)session.getAttribute(UserSession.tenantId); + String parentTenantId = (String)session.getAttribute(UserSession.parentTenantId); + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(tenantId); + tenantEntity.setParentTenantId(parentTenantId); + return tenantEntity; + } + + /** + * 处理集团新增修改所需租户信息(广场独立修改,集团修改全部) + * 处理集团版 tenantId为空,parentTenantId为集团tenantId + * ifParentUpdateTenantInfo + */ + public TenantEntity ifParentUpdateTenantInfo() { + TenantEntity info = this.getTenantInfo(); + if(StringUtils.isBlank(info.getTenantId())){ + info.setTenantId(info.getParentTenantId()); + info.setParentTenantId(null); + } + return info; + } + + /** + * 处理集团新增修改所需租户信息(各广场和集团独立修改) + * ifParentUpdateTenantInfo + */ + public TenantEntity ifParentUpdateAloneTenantInfo(){ + TenantEntity info = this.getTenantInfo(); + if(StringUtils.isBlank(info.getTenantId())){ + info.setTenantId(info.getParentTenantId()); + info.setParentTenantId(null); + } + if(getUser().getTenantId().equals(info.getTenantId())){ + return info; + } + new Exception("权限不足,只能独立操作"); + return null; + } + + public String getIpAddr() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String ipaddress = IPUtil.getIpAddr(request); + return ipaddress; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/EnumController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/EnumController.java new file mode 100644 index 000000000..9f92ae5b8 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/EnumController.java @@ -0,0 +1,56 @@ +package com.iformall.controller.basic; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + +import java.lang.reflect.Method; +import java.util.*; + +@RestController +@RequestMapping("enum") +@Api(description="枚举接口") +public class EnumController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @SystemControllerLog(description = "会员管理-标签获取") + @ApiOperation(value="获取枚举对象", notes="根据获取枚举类名获取枚举对象") + @GetMapping("/getEnum/{type}") + public ResultData getEnum(@PathVariable("type") String type) { + if(StringUtils.isBlank(type)){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + String className = "com.iformall.enums." + type; + List> list = new ArrayList>(); + try { + // 1.得到枚举类对象 + Class clz = (Class) Class.forName(className); + // 2.得到所有枚举常量 + Object[] objects = clz.getEnumConstants(); + Method getCode = clz.getMethod("getCode"); + Method getMessage = clz.getMethod("getMessage"); + Map map = null; + for (Object obj : objects) { + map = new HashMap(); + map.put("code", getCode.invoke(obj).toString()); + map.put("message", getMessage.invoke(obj).toString()); + list.add(map); + } + } catch (Exception e) { + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR,"数据不存在"); + } + if(list.size() == 0){ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR,"数据不存在"); + } + return new ResultData(list); + + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxBrandController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxBrandController.java new file mode 100644 index 000000000..dc7d3a401 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxBrandController.java @@ -0,0 +1,128 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.WxBrand; +import com.iformall.domain.po.WxMerchant; +import com.iformall.enums.EnumDelFlag; +import com.iformall.service.WxBrandService; +import com.iformall.service.WxMerchantService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxBrand") +public class WxBrandController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxBrandService wxBrandService; + @Autowired + private WxMerchantService wxMerchantService; + + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "品牌-列表") + public ResultData list(@ModelAttribute WxBrand wxBrand,Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxBrandController::list"); + if (null == wxBrand) { + wxBrand = new WxBrand(); + } + wxBrand.updateTenantInfo(getTenantInfo()); + wxBrand.setSortColumns(BaseEntity.SortField.Id_DESC); + final PageInfo page = wxBrandService.listAsPage(wxBrand, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "品牌-增加") + public ResultData add(@RequestBody WxBrand wxBrand) { + logger.debug("[" + getIpAddr() + "] WxBrandController::add"); + wxBrand.updateTenantInfo(getTenantInfo()); + return wxBrandService.save(wxBrand); + } + + @PostMapping("update") + @SystemControllerLog(description = "品牌-更新") + public ResultData update(@RequestBody WxBrand wxBrand) { + logger.debug("[" + getIpAddr() + "] WxBrandController::update"); + wxBrand.updateTenantInfo(getTenantInfo()); + + if(EnumDelFlag.YES.getCode().equals(wxBrand.getIsDel())){ + //判断是否解绑商户 + WxMerchant wxMerchant = new WxMerchant() {{ + setIsDel(0); + setBrand(wxBrand.getId()); + updateTenantInfo(wxBrand); + }}; + List merchantList = wxMerchantService.findList(wxMerchant); + if(CollectionUtils.isNotEmpty(merchantList)){ + return new ResultData(Result.ERROR, "请先删除已绑定该品牌的商户。"); + } + } + wxBrandService.update(wxBrand); + return new ResultData(Result.SUCCESS, "操作成功"); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "品牌-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxBrandController::del"); + wxBrandService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "品牌-查找") + public ResultData findById(Long id) { + return new ResultData(Result.SUCCESS, "查询成功", wxBrandService.getById(id)); + } + + @GetMapping("/queryBrand") + @SystemControllerLog(description = "品牌-租户-全部") + public ResultData queryBrand() { + List> brandList = wxBrandService.queryBrand(getTenantInfo()); + return new ResultData(brandList); + } + + + @ApiOperation("查询品牌名称是否存在") + @GetMapping("hasBrand") + @ApiImplicitParams({ + @ApiImplicitParam(name = "name", value = "name", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query")}) + @SystemControllerLog(description = "品牌-名称是否存在") + public ResultData hasBrand(String name, Long id) { + logger.debug("[" + getIpAddr() + "] WxBrandController::hasBrand"); + WxBrand wxBrand = new WxBrand() {{ + setName(name); + updateTenantInfo(getTenantInfo()); + }}; + wxBrand.setId(id); + return wxBrandService.hasBrand(wxBrand); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxGroupController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxGroupController.java new file mode 100644 index 000000000..c01941f64 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxGroupController.java @@ -0,0 +1,73 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxGroup; +import com.iformall.service.WxGroupService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxGroup") +public class WxGroupController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxGroupService wxGroupService; + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "集团-列表") + public ResultData list(@ModelAttribute WxGroup wxGroup, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxGroupController::list"); + if (null == wxGroup) wxGroup = new WxGroup(); + final PageInfo page = wxGroupService.listAsPage(wxGroup, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "集团-添加") + public ResultData add(@RequestBody WxGroup wxGroup) { + logger.debug("[" + getIpAddr() + "] WxGroupController::add"); + //Assert.notNull(wxGroup.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxGroupService.saveOrUpdate(wxGroup); + return new ResultData(); + } + + @PostMapping("update") + @SystemControllerLog(description = "集团-更新") + public ResultData update(@RequestBody WxGroup wxGroup) { + logger.debug("[" + getIpAddr() + "] WxGroupController::update"); + wxGroupService.saveOrUpdate(wxGroup); + return new ResultData(); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "集团-删除") + public ResultData delete(String id) { + logger.debug("[" + getIpAddr() + "] WxGroupController::delete"); + wxGroupService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "集团-查询") + public ResultData findById(String id) { + logger.debug("[" + getIpAddr() + "] WxGroupController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxGroupService.getById(id)); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMallBuildingController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMallBuildingController.java new file mode 100644 index 000000000..32e377604 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMallBuildingController.java @@ -0,0 +1,88 @@ +package com.iformall.controller.basic; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMallBuilding; +import com.iformall.domain.po.WxMallFloor; +import com.iformall.service.WxMallBuildingService; +import com.iformall.utils.Constant; +import com.iformall.utils.RedisCacheUtils; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("wxMallBuilding") +public class WxMallBuildingController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMallBuildingService wxMallBuildingService; + + @Autowired + @Qualifier("objectCommonRedisTemplate") + RedisTemplate objectCommonRedisTemplate; + + @ApiOperation("获取楼层楼座数据") + @GetMapping("getbuildingfloorlist") + @SystemControllerLog(description = "商城-楼座-获取楼层楼座数据") + public ResultData getbuildingfloorlist() { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::getbuildingfloorlist"); + return wxMallBuildingService.getBuildingFloorList(getTenantInfo()); + } + + @ApiOperation("保存楼层楼座地图") + @PostMapping("saveFloorImg") + @SystemControllerLog(description = "商城-楼座/楼层-保存地图") + public ResultData saveFloorImg(@RequestBody List record) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::addBuildingAndFloor"); + if(record == null && record.size() > 0) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + for (WxMallBuilding building: record) { + List floors = building.getFloors(); + if(floors != null && floors.size() > 0){ + for (WxMallFloor floor:floors) { + if (floor.getId() == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + floor.updateTenantInfo(getTenantInfo()); + wxMallBuildingService.saveFloorImg(floor); + + } + } + } + + String key = Constant.mallBuildingPrev + getTenantInfo().getTenantId(); + RedisCacheUtils.removeCache(objectCommonRedisTemplate, key); + return new ResultData(); + } + + @ApiOperation("保存楼层楼座面积") + @PostMapping("saveFloorArea") + @SystemControllerLog(description = "商城-楼座/楼层-保存面积") + public ResultData saveFloorArea(@RequestBody WxMallFloor record) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::addBuildingAndFloor"); + if(record == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if (record.getId() == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if (record.getTotalArea() == null && record.getOperatingArea() == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + record.updateTenantInfo(getTenantInfo()); + wxMallBuildingService.saveFloorArea(record); + return new ResultData(); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMallController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMallController.java new file mode 100644 index 000000000..4030ffe15 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMallController.java @@ -0,0 +1,48 @@ +package com.iformall.controller.basic; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMall; +import com.iformall.service.WxMallService; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMall") +public class WxMallController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMallService wxMallService; + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "商城-更新") + public ResultData update(@RequestBody WxMall wxMall) { + logger.debug("[" + getIpAddr() + "] WxMallController::update"); + wxMallService.update(wxMall); + return new ResultData(); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/mallinfoExt") + @SystemControllerLog(description = "商城-查询") + public ResultData mallinfoExt() { + logger.debug("[" + getIpAddr() + "] WxMallController::mallinfoExt"); + return new ResultData(wxMallService.getByTenantInfoExt(getTenantInfo())); + } + + @ApiOperation("查询当前mall的信息") + @GetMapping("/mallinfo") + @SystemControllerLog(description = "商城-当前查询") + public ResultData mallinfo() { + logger.debug("[" + getIpAddr() + "] WxMallController::mallinfo"); + return new ResultData(wxMallService.getByTenantInfo(ifParentUpdateTenantInfo())); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantBUserController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantBUserController.java new file mode 100644 index 000000000..bf6af813f --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantBUserController.java @@ -0,0 +1,31 @@ +package com.iformall.controller.basic; + +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.service.WxMerchantBUserService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMerchantBUser") +public class WxMerchantBUserController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMerchantBUserService wxMerchantBUserService; + + @ApiOperation("手机号是否存在") + @GetMapping("/hasphone") + @ApiImplicitParam(name = "phone", value = "phone", dataType = "String", paramType = "query", required = true) + public ResultData hasPhone(String phone) { + logger.debug("[" + getIpAddr() + "] WxMerchantBUserController::hasphone"); + boolean has = wxMerchantBUserService.hasPhone(getTenantInfo(), phone); + return new ResultData(Result.SUCCESS, "查询成功", has); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantController.java new file mode 100644 index 000000000..42d0b919b --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantController.java @@ -0,0 +1,344 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.annotation.TenantIgnore; +import com.iformall.annotation.UserDataRuleAnnotation; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.WxMerchant; +import com.iformall.domain.po.WxProfitSharingReceiver; +import com.iformall.domain.vo.WxMerchantTradeDetailVo; +import com.iformall.domain.vo.WxMerchantTradeVo; +import com.iformall.domain.vo.WxMerchantVo; +import com.iformall.enums.EnumMerchantStatus; +import com.iformall.enums.EnumPayWay; +import com.iformall.service.QrCodeService; +import com.iformall.service.WxMerchantService; +import com.iformall.utils.Constant; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxMerchant") +public class WxMerchantController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMerchantService wxMerchantService; + @Autowired + private QrCodeService qrCodeService; + + @UserDataRuleAnnotation("merchant_list") + @ApiOperation("分页列表接口") + @GetMapping("listVo") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商户-列表") + public ResultData listVo(@ModelAttribute WxMerchant wxMerchant, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchant.setSortColumns(BaseEntity.SortField.TopTime_DESC); + final PageInfo page = wxMerchantService.listVoAsPage(wxMerchant, pageNum, pageSize); + return new ResultData(page); + } + + + @UserDataRuleAnnotation("merchant_list") + @ApiOperation("分页列表接口") + @GetMapping("listVo2") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商户-列表") + public ResultData listVo2(@ModelAttribute WxMerchant wxMerchant, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchant.setSortColumns(BaseEntity.SortField.TopTime_DESC); + final PageInfo page = wxMerchantService.listVoAsPage2(wxMerchant, pageNum, pageSize); + return new ResultData(page); + } + + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), + }) + @SystemControllerLog(description = "商户-列表") + public ResultData list(@ModelAttribute WxMerchant wxMerchant, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchant.setSortColumns(BaseEntity.SortField.TopTime_DESC); + final PageInfo page = wxMerchantService.listAsPage(wxMerchant, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("获取商户ID,名称接口") + @GetMapping("IdAndNamelist") + @ApiImplicitParams({ + @ApiImplicitParam(name = "type", value = "类型", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true) + }) + @SystemControllerLog(description = "商户-列表") + public ResultData IdAndNamelist(Integer type,Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + WxMerchant wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchant.setSortColumns(BaseEntity.SortField.TopTime_DESC); + wxMerchant.setStatus(EnumMerchantStatus.VALID.getCode()); + wxMerchant.setType(type); + wxMerchant.setCarVendorType(0); + return new ResultData(wxMerchantService.queryIdAndNames(wxMerchant)); + } + + + @ApiOperation("ETCP商户列表") + @GetMapping("etcplist") + @SystemControllerLog(description = "商户-ETCP商户列表") + public ResultData etcpList(@ModelAttribute WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::etcpList"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + final List merchantList = wxMerchantService.etcpList(wxMerchant); + return new ResultData(merchantList); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::delete"); + wxMerchantService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::findById"); + WxMerchant wxMerchant = wxMerchantService.getById(id); + return new ResultData(wxMerchant); + } + + @ApiOperation("停用") + @GetMapping("disable") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-停用") + public ResultData disable(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::disable"); + wxMerchantService.disable(id); + return new ResultData(Result.SUCCESS, "停用成功"); + } + + @ApiOperation("新增商户接口") + @PostMapping("addMerchant") + @SystemControllerLog(description = "商户-新增") + public ResultData addMerchant(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::addMerchant"); + wxMerchant.updateTenantInfo(getTenantInfo()); + ResultData resultData = wxMerchantService.addMerchant(wxMerchant, getUserId()); + + if(resultData.code == 200){ + //加载二维码图片 + String pageUrl = Constant.mainPageUrl; + String param = "t:md:"+resultData.data; + + //这里暂时只有微信二维码,后续有别的二维码,再加字段 + ResultData resultQrCode = qrCodeService.uploadQrcode(wxMerchant,1,pageUrl,param,0,"","","店铺详情",EnumPayWay.PAY_WAY_WECHAT); + Map map = (Map)resultQrCode.data; + if(map!=null && map.get("url") !=null) { + String url = map.get("url"); + wxMerchant.setQrCode(url); + wxMerchantService.updateMerchant(wxMerchant); + } + } + + return resultData; + } + + + @ApiOperation("更新商户接口") + @PostMapping("updateMerchant") + @SystemControllerLog(description = "商户-更新") + public ResultData updateMerchant(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchant"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.updateMerchant(wxMerchant); + } + + @ApiOperation("更新账户接口") + @PostMapping("updateMerchantAccount") + @SystemControllerLog(description = "商户-更新账户") + public ResultData updateMerchantAccount(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantAccount"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.updateMerchantAccount(wxMerchant,EnumPayWay.PAY_WAY_WECHAT); + } + + @ApiOperation("更新管理员接口") + @PostMapping("updateMerchantAdmin") + @SystemControllerLog(description = "商户-更新管理员") + public ResultData updateMerchantAdmin(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantAdmin"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.updateMerchantAdmin(wxMerchant); + } + + @ApiOperation("更新法人接口") + @PostMapping("updateMerchantCorp") + @SystemControllerLog(description = "商户-更新法人") + public ResultData updateMerchantCopr(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantCorp"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.updateMerchantCorp(wxMerchant); + } + + @ApiOperation("更新税务接口") + @PostMapping("updateMerchantTax") + @SystemControllerLog(description = "商户-更新税务") + public ResultData updateMerchantTax(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantTax"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.updateMerchantTax(wxMerchant); + } + + @ApiOperation("商户信息设置接口") + @PostMapping("updateMerchantLevel") + @SystemControllerLog(description = "商户-更新会员等级权益") + public ResultData updateMerchantLevel(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantLevel"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.updateMerchantLevel(wxMerchant); + } + + @ApiOperation("查询当前租户下商户名称列表") + @GetMapping("/name_list") + @SystemControllerLog(description = "查询当前租户下商户名称列表") + public ResultData nameList() { + logger.debug("[" + getIpAddr() + "] WxMerchantController::name_list"); + return new ResultData(wxMerchantService.findList(getTenantInfo())); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findMerchantById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-查询") + public ResultData findMerchantById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::findMerchantById"); + WxMerchantVo wxMerchant = wxMerchantService.findMerchantById(id); + return new ResultData(wxMerchant); + } + + @UserDataRuleAnnotation("merchant_list") + @ApiOperation("商户数据导出") + @GetMapping("/exportData") + @SystemControllerLog(description = "商户-商户数据导出") + public void exportData(@ModelAttribute WxMerchant wxMerchant, HttpServletRequest request, HttpServletResponse response) { + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchant.setSortColumns(BaseEntity.SortField.TopTime_DESC); + wxMerchantService.exportData(wxMerchant,request,response); + } + + @ApiOperation("置顶") + @PostMapping("top") + @SystemControllerLog(description = "商户-置顶") + public ResultData top(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::top"); + wxMerchant.updateTenantInfo(getTenantInfo()); + return wxMerchantService.top(wxMerchant); + } + + @ApiOperation("更新收款账户状态") + @PostMapping("useAccount") + @SystemControllerLog(description = "商户-更新收款账户状态") + public ResultData useAccount(@RequestBody WxProfitSharingReceiver wxProfitSharingReceiver) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::useAccount"); + wxProfitSharingReceiver.updateTenantInfo(getTenantInfo()); + return wxMerchantService.useAccount(wxProfitSharingReceiver); + } + + @ApiOperation("查看是否存在商户名称相同记录") + @GetMapping("/hasMerchant") + @SystemControllerLog(description = "商户-查看是否存在商户名称相同记录") + public ResultData hasMerchant(@ModelAttribute WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::hasMerchant"); + wxMerchant.updateTenantInfo(getTenantInfo()); + boolean has = wxMerchantService.hasMerchant(wxMerchant); + return new ResultData(has); + } + + @ApiOperation("查看是否存在商户名称相同记录") + @GetMapping("/hasMerchantEncode") + @SystemControllerLog(description = "商户-查看是否存在商户编码相同记录") + @TenantIgnore + public ResultData hasMerchantEncode(@ModelAttribute WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::hasMerchantEncode{}"+wxMerchant.toString()); + boolean has = wxMerchantService.hasMerchantEncode(wxMerchant); + return new ResultData(has); + } + + @ApiOperation("商户会员消费分页列表接口") + @GetMapping("userTradeList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商户-消费列表") + public ResultData userTradeList(@ModelAttribute WxMerchant wxMerchant, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchant.setSortColumns(BaseEntity.SortField.TopTime_DESC); + final PageInfo page = wxMerchantService.userTradeList(wxMerchant, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("商户会员消费明细列表接口") + @GetMapping("userTradeDetailList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商户-商户会员消费明细列表接口") + public ResultData userTradeDetailList(@ModelAttribute WxMerchant wxMerchant, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + final PageInfo page = wxMerchantService.userTradeDetailList(wxMerchant, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("导出商户会员消费分页列表") + @GetMapping("exportUserTradeDetailList") + @SystemControllerLog(description = "导出商户会员消费分页列表") + public void exportUserTradeList(@ModelAttribute WxMerchant wxMerchant,HttpServletRequest request, HttpServletResponse response) throws Exception{ + logger.debug("[" + getIpAddr() + "] WxBusinessController::exportUserTradeDetailList"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.updateTenantInfo(getTenantInfo()); + wxMerchantService.exportUserTradeList(wxMerchant, request,response); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantShopController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantShopController.java new file mode 100644 index 000000000..49a23b3f6 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMerchantShopController.java @@ -0,0 +1,40 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMerchantShop; +import com.iformall.domain.po.WxShop; +import com.iformall.service.WxMerchantShopService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMerchantShop") +public class WxMerchantShopController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMerchantShopService wxMerchantShopService; + + @ApiOperation("获取关联商铺信息") + @GetMapping("queryShopList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商户商铺--获取关联商铺信息") + public ResultData queryShopList(@ModelAttribute WxMerchantShop wxMerchantShop, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantShopController::queryShopList"); + if (null == wxMerchantShop) wxMerchantShop = new WxMerchantShop(); + wxMerchantShop.updateTenantInfo(getTenantInfo()); + final PageInfo page = wxMerchantShopService.queryShopList(wxMerchantShop, pageNum, pageSize); + return new ResultData(page); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMiniappThemeController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMiniappThemeController.java new file mode 100644 index 000000000..764f6c017 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxMiniappThemeController.java @@ -0,0 +1,154 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.annotation.TenantIgnore; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.config.WechatWebProperties; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.vo.WxWeappInfo; +import com.iformall.enums.EnumGroupSupport; +import com.iformall.enums.EnumInvestUserType; +import com.iformall.enums.EnumThemeType; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.*; +import com.iformall.shiro.PasswordHelper; +import com.iformall.utils.Constant; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@RestController +@Api(description = "MiniappTheme相关接口") +@RequestMapping("wxMiniappTheme") +public class WxMiniappThemeController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + WxMiniappThemeService wxMiniappThemeService; + + @ApiOperation("查询MiniappTheme列表") + @GetMapping(value = "/list") + @SystemControllerLog(description = "查询MiniappTheme列表") + @TenantIgnore + public ResultData getList(@ModelAttribute WxMiniappTheme wxMiniappTheme, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMiniappThemeController::getList"); + try { + if(wxMiniappTheme == null){ + wxMiniappTheme = new WxMiniappTheme(); + } + wxMiniappTheme.setTenantId(getTenantInfo().getTenantId()); + if(wxMiniappTheme.getType() == null){ + wxMiniappTheme.setType(EnumThemeType.C.getCode()); + } + PageInfo page = wxMiniappThemeService.listAsPage(wxMiniappTheme, pageNum, pageSize); + WxThemeMall wxThemeMall = new WxThemeMall(); + wxThemeMall.setTenantId(getTenantInfo().getTenantId()); + wxThemeMall.setThemeType(EnumThemeType.C.getCode()); + WxThemeMall themeMall = wxMiniappThemeService.findThemeMall(wxThemeMall); + boolean updateStatus = true; + if(themeMall != null){ + for (WxMiniappTheme theme:page.getList()) { + if(theme.getId().equals(themeMall.getThemeId())){ + theme.setStatus(0); + updateStatus = false; + }else{ + theme.setStatus(1); + } + } + } + if(updateStatus){ + page.getList().get(0).setStatus(0); + } + + return new ResultData(page); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("根据id使之生效") + @PostMapping("/updateEffect") + @ApiImplicitParam(name = "themeId", value = "themeId", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "根据id使之生效") + @TenantIgnore + public ResultData updateEffect(@RequestBody WxThemeMall wxThemeMall) { + logger.debug("[" + getIpAddr() + "] WxMiniappThemeController::updateEffect"); + if(wxThemeMall == null || wxThemeMall.getThemeId() == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxThemeMall.setTenantId(getTenantInfo().getTenantId()); + if(wxThemeMall.getThemeType() == null){ + wxThemeMall.setThemeType(EnumThemeType.C.getCode()); + } + + wxMiniappThemeService.updateEffect(wxThemeMall); + return new ResultData(Result.SUCCESS); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "-删除") + @TenantIgnore + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMiniappThemeController::delete"); + if(id == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxMiniappThemeService.updateDel(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @PostMapping("add") + @SystemControllerLog(description = "-添加") + @TenantIgnore + public ResultData add(@RequestBody WxMiniappTheme wxMiniappTheme) { + logger.debug("[" + getIpAddr() + "] WxMiniappThemeController::add"); + if(wxMiniappTheme == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxMiniappTheme.setTenantId(getTenantInfo().getTenantId()); + if(wxMiniappTheme.getType() == null){ + wxMiniappTheme.setType(EnumThemeType.C.getCode()); + } + wxMiniappThemeService.saveOrUpdate(wxMiniappTheme); + return new ResultData(); + } + + @PostMapping("update") + @SystemControllerLog(description = "集团-更新") + public ResultData update(@RequestBody WxMiniappTheme wxMiniappTheme) { + logger.debug("[" + getIpAddr() + "] WxMiniappThemeController::update"); + if(wxMiniappTheme == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxMiniappTheme.setTenantId(getTenantInfo().getTenantId()); + wxMiniappThemeService.saveOrUpdate(wxMiniappTheme); + return new ResultData(); + } + + + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxProjectConfigController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxProjectConfigController.java new file mode 100644 index 000000000..c62d18daf --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxProjectConfigController.java @@ -0,0 +1,751 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.annotation.TenantIgnore; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.config.WechatWebProperties; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.vo.WxWeappInfo; +import com.iformall.enums.EnumGroupSupport; +import com.iformall.enums.EnumInvestUserType; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.*; +import com.iformall.shiro.PasswordHelper; +import com.iformall.utils.Constant; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@RestController +@Api(description = "初始化相关接口") +@RequestMapping("wxProjectConfig") +public class WxProjectConfigController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + WxProjectConfigService wxProjectConfigService; + + @Autowired + WxCouponSendConfigService wxCouponSendConfigService; + + @Autowired + WxMallService wxMallService; + + @Autowired + WxPayAccountService wxPayAccountService; + + @Autowired + WxPayAccountBillService wxPayAccountBillService; + + @Autowired + MallUserInfoService userInfoService; + + @Autowired + WxAppinfoService wxAppinfoService; + + @Autowired + WxMsgConfigService wxMsgConfigService; + + @Autowired + WxParkService wxParkService; + + @Autowired + WxWiWideInfoService wxWiWideInfoService; + + @Autowired + WxAuthorizerInfoService wxAuthorizerInfoService; + + @Autowired + WxWeappExtSetService wxWeappExtSetService; + + @Autowired + WxScoreRulesService wxScoreRulesService; + + @Autowired + WxTemplateMsgService wxTemplateMsgService; + + @Autowired + WxQuestionService wxQuestionService; + + @Autowired + WxMsgValidationcodeModelService wxMsgValidationcodeModelService; + + @Autowired + WxFlowConfigService wxFlowConfigService; + + @Autowired + WxMallBuildingService wxMallBuildingService; + + @Autowired + MallUserInfoService mallUserInfoService; + + @Autowired + private WechatWebProperties wechatWebProperties; + + @Autowired + @Qualifier("openRedisTemplate") + RedisTemplate openRedisTemplate; + + +// @ApiOperation("添加商场基础数据") +// @GetMapping(value = "/init/{id}") +// @SystemControllerLog(description = "商场基础数据") +// @TenantIgnore +// public ResultData init(@PathVariable Long id) { +// logger.debug("[" + getIpAddr() + "] WxProjectConfigController::init"); +// try { +// wxProjectConfigService.initProjectConfig(id); +// return new ResultData(); +// }catch (Exception e){ +// logger.error(e.getMessage(),e); +// return new ResultData(ErrorCode.SYS_SERVER_ERROR); +// } +// +// } + + + @ApiOperation("查询商场集团列表") + @GetMapping(value = "/mallList") + @SystemControllerLog(description = "商场基础数据") + @TenantIgnore + public ResultData getMallList(@ModelAttribute WxMall wxMall, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::getMallList"); + try { + if(wxMall == null){ + wxMall = new WxMall(); + } + PageInfo page = wxMallService.listAsPage(wxMall, pageNum, pageSize); + return new ResultData(page); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("查询商场集团列表(选择子集团)") + @GetMapping(value = "/mallListbyMall") + @SystemControllerLog(description = "商场基础数据") + @TenantIgnore + public ResultData mallListbyMall(@ModelAttribute WxMall wxMall) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::mallListbyMall"); + try { + if(wxMall == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(wxMall.getId() == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(wxMall.getId().toString()); + + WxMall parentWxMall = wxMallService.getByTenantInfo(tenantEntity); + if(parentWxMall == null || parentWxMall.getSaleType() != 100 + || !parentWxMall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode()) + || StringUtils.isNotBlank(parentWxMall.getParentTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR); + } + + List list = wxMallService.listAsSelectMall(wxMall.getId()); + return new ResultData(list); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + + @ApiOperation("添加修改商场集团") + @PostMapping("/init/mall") + @SystemControllerLog(description = "商场集团-更新") + @TenantIgnore + public ResultData initMall(@RequestBody WxMall wxMall) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initMall"); + try { + //集团版 + if(wxMall.getSaleType().equals(100)){ + wxMall.setGroupSupport(EnumGroupSupport.SUPPORT.getCode()); + }else{ + wxMall.setGroupSupport(EnumGroupSupport.NOT_SUPPORT.getCode()); + } + if(wxMall.getId() == null && StringUtils.isBlank(wxMall.getBusinessHours())){ + wxMall.setBusinessHours("[]"); + } + if(wxMall.getId() == null && StringUtils.isBlank(wxMall.getIntroduction())){ + wxMall.setIntroduction(""); + } + if(wxMall.getId() == null && StringUtils.isBlank(wxMall.getImg())){ + wxMall.setImg(""); + } + if(wxMall.getId() == null && StringUtils.isBlank(wxMall.getWeapNote())){ + wxMall.setWeapNote("{}"); + } + wxProjectConfigService.initMall(wxMall); + + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("添加修改商场楼座信息") + @PostMapping("/init/building") + @SystemControllerLog(description = "商场楼座-更新") + @TenantIgnore + public ResultData initBuilding(@RequestBody List wxMallBuildings) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initBuilding"); + try { + if(wxMallBuildings == null || wxMallBuildings.size() == 0){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + for (WxMallBuilding wxMallBuilding:wxMallBuildings) { + if(StringUtils.isBlank(wxMallBuilding.getTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + } + wxProjectConfigService.initBuilding(wxMallBuildings); + + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("添加修改特殊商户号信息") + @PostMapping("/init/payAccount") + @SystemControllerLog(description = "特殊商户号-更新") + @TenantIgnore + public ResultData initPayAccount(@RequestBody WxPayAccount wxPayAccount) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initPayAccount"); + try { + if(StringUtils.isBlank(wxPayAccount.getTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + WxPayAccount getByTenantId = wxPayAccountService.getByTenantId(wxPayAccount.getTenantId()); + if(wxPayAccount.getId() != null && (getByTenantId == null || !getByTenantId.getId().equals(wxPayAccount.getId()))){ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR); + } + if(wxPayAccount.getId() == null && getByTenantId != null){ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR); + } + + if(StringUtils.isBlank(wxPayAccount.getNotifyUrl())){ + wxPayAccount.setNotifyUrl(wechatWebProperties.getUrl()+"/wxPay/notify"); + } + if(StringUtils.isBlank(wxPayAccount.getCertPath())){ + wxPayAccount.setCertPath("/opt/iformall/service/apiclient_cert.p12"); + } + if(wxPayAccount.getType() == null){ + wxPayAccount.setType(1);//0:普通商户模式, 1:服务商模式(默认服务商模式) + } + if(wxPayAccount.getShare() == null){ + wxPayAccount.setShare(0);//0: 未分账,1:分账(默认不分账) + } + + wxProjectConfigService.initPayAccount(wxPayAccount); + + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("添加修改小程序信息") + @PostMapping("/init/appinfo") + @SystemControllerLog(description = "小程序信息-更新") + @TenantIgnore + public ResultData initAppinfo(@RequestBody WxAppinfo wxAppinfo) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initAppinfo"); + try { + if(StringUtils.isBlank(wxAppinfo.getTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(wxAppinfo.getId() == null){ + WxPayAccount byTenantId = wxPayAccountService.getByTenantId(wxAppinfo.getTenantId()); + if(byTenantId != null){ + wxAppinfo.setPayId(byTenantId.getId()); + } + WxPayAccountBill billByTenantId = wxPayAccountBillService.getByTenantId(wxAppinfo.getTenantId()); + if(billByTenantId != null){ + wxAppinfo.setPayBillId(billByTenantId.getId()); + } + } + + wxAppinfoService.saveOrUpdate(wxAppinfo); + + WxAuthorizerInfo wxAuthorizerInfo = wxAuthorizerInfoService.getByAppId(wxAppinfo.getAppId()); + if(wxAuthorizerInfo == null){ + wxAuthorizerInfo = new WxAuthorizerInfo(); + } +// wxAuthorizerInfo.updateTenantInfo(wxAppinfo); + wxAuthorizerInfo.setTenantId(wxAppinfo.getTenantId()); + wxAuthorizerInfo.setType(wxAppinfo.getType()); + wxAuthorizerInfo.setAuthorizerAppid(wxAppinfo.getAppId()); + + if(wxAuthorizerInfo.getAuthorizationStatus() == null){ + wxAuthorizerInfo.setAuthorizationStatus(0);//授权状态,0为已授权,1为已取消授权 + wxAuthorizerInfo.setAuthTime(new Date()); + } + if(wxAuthorizerInfo.getBaseStatus() == null){ + wxAuthorizerInfo.setBaseStatus(0);//微信基础版本设置状态,0为已设置,1为设置失败 + wxAuthorizerInfo.setBaseTime(new Date()); + } + if(wxAuthorizerInfo.getDomainStatus() == null){ + wxAuthorizerInfo.setDomainStatus(0);//服务器域名设置状态,0为已设置,1为设置失败 + wxAuthorizerInfo.setDomainTime(new Date()); + } + if(wxAuthorizerInfo.getWebdomainStatus() == null){ + wxAuthorizerInfo.setWebdomainStatus(0);//服务器业务域名设置状态,0为已设置,1为设置失败 + wxAuthorizerInfo.setWebdomainTime(new Date()); + } + if(StringUtils.isBlank(wxAuthorizerInfo.getRefreshToken())){ + wxAuthorizerInfo.setRefreshToken(""); + } + if(StringUtils.isBlank(wxAuthorizerInfo.getAccessToken())){ + wxAuthorizerInfo.setAccessToken(""); + } + wxAuthorizerInfoService.saveOrUpdate(wxAuthorizerInfo); + + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + /** + * 这里添加多个用户会生成多套角色 + */ + @ApiOperation("添加修改商场后台管理帐号") + @PostMapping("/init/userInfo") + @SystemControllerLog(description = "商场后台管理帐号-更新") + @TenantIgnore + public ResultData initUserInfo(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initUserInfo"); + try { + if(StringUtils.isBlank(userInfo.getTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(StringUtils.isBlank(userInfo.getUsername())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(StringUtils.isBlank(userInfo.getPhone())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + boolean bChangedPhone = false; + if(userInfo.getId() == null){ + if(userInfoService.cntByUserName(userInfo.getUsername()) > 0){ + return new ResultData(ErrorCode.USER_NAME_IS_FOUND.getCode(),"用户名已存在"); + } + if(userInfoService.cntByUserPhone(userInfo.getPhone()) > 0){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND.getCode(),"手机号已存在"); + } + Assert.notNull(userInfo.getPassword(), "密码不能为空"); + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(userInfo); + userInfo.setIsAdmin(EnumUserAdmin.ADMIN.getCode()); + userInfo.setInvestRule(EnumInvestUserType.ALL.getCode()); + + wxProjectConfigService.initUserInfo(userInfo); + }else{ + MallUserInfo oldUser = userInfoService.getById(userInfo.getId()); + if (!oldUser.getUsername().equals(userInfo.getUsername())) { + if(userInfoService.cntByUserName(userInfo.getUsername()) > 0){ + return new ResultData(ErrorCode.USER_NAME_IS_FOUND.getCode(),"用户名已存在"); + } + } + if (!oldUser.getPhone().equals(userInfo.getPhone())) { + if(userInfoService.cntByUserPhone(userInfo.getPhone()) > 0){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND.getCode(),"手机号已存在"); + } + bChangedPhone = true; + } + if (StringUtils.isNotBlank(userInfo.getPassword()) && userInfo.getPassword().length() > 0) { + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(userInfo); + }else{ + userInfo.setPassword(null); + } + userInfo.setIsAdmin(EnumUserAdmin.ADMIN.getCode()); + userInfoService.saveOrUpdate(userInfo); + + if(bChangedPhone) { + // 手机号修改,清除bopen_id, 清除web_open_id + userInfoService.cleanAllOpenId(userInfo); + } + } + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + +// @ApiOperation("添加修改商场短信配置") +// @PostMapping("/init/msgConfig") +// @SystemControllerLog(description = "商场后短信配置-更新") +// public ResultData initMsgConfig(@RequestBody WxMsgConfig wxMsgConfig) { +// logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initMsgConfig"); +// try { +// if(StringUtils.isBlank(wxMsgConfig.getTenantId())){ +// return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); +// } +// if(wxMsgConfig.getSmsChannel() == null){ +// wxMsgConfig.setSmsChannel(EnumSMSChannel.WIWIDE.getCode()); +// } +// if(wxMsgConfig.getSmsChannel() == EnumSMSChannel.WIWIDE.getCode()){ +// wxMsgConfig.setSecret("7305150347587283553aa8898e7dbf20"); +// wxMsgConfig.setPublickey("MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvh8j/zagfxQdnSh5OIic\\r" + +// "\\nMzN+MuRuWQJPjgu4Gza4+gX3j5Ln2xNDBOTjpwyuLBjh/JcBd1cGO3lAaKCwcaix\\r" + +// "\\nsmhTq56wVXXUMgDiAChu4ud8FSvRc8G8tdZAirKVAIi3NW+/pYgpWBs/0wnF8hz4\\r" + +// "\\n8no4pyJHl9Jc1LH3VNIMz8vqzKUPc4ack4pFUXlcNj6C+sBlaurmI4/vwLqNxBGs\\r" + +// "\\n7/zyM7dv6oy3DSU/Y1qBArM1YPjfL2dNun8rmtPgJvlPwXqA7uoHPwQ2Ym3aUn59\\r" + +// "\\npkS7QI6IE8uuqNkfSte8BXLd2nIqPLFxLYLDmdll7eoyRblHcHqAYSj8stK6StC7\\r" + +// "\\nDNryNKEjTEwbgf9trUI0uvF1pfgTy2gpclnY69FtD/m0+FvLyorMq+nmBqYMjka5\\r" + +// "\\nK0txDQJPOa7gsi//uXd/cJW2SAXY9MSO1AfMi8Xq/YKRQzN9FW5iapskXFHca7uX\\r" + +// "\\ng5NhH7flr6DW+QInFlpoN6WIEAuDF1aj4O49Ikm3WxwhTqnvEkdSCfivpYQkp9Sh\\r" + +// "\\n4kQ/SQdxuT7VX+Nz6k+uMx2z4cySk33bHi0KoHbA9QFGg/54Qd0+eU4qZnd4mrgh\\r" + +// "\\nhH7/QQhL7Z9eF1U5UPrsHq2Vq3rEnN+tYQ26AuKeU8vzTxBrC/SxC6C/SMFt3f/Y\\r" + +// "\\nnuFh1UnNJZleZwyQt+ZdGO0CAwEAAQ=="); +// wxMsgConfig.setBid("465565"); +// wxMsgConfig.setAccount("15626593768"); +// wxMsgConfig.setNotifyurl("https://admin.malls.iformall.com/wxMsgCallback/receivemsg/" + wxMsgConfig.getTenantId()); +// wxMsgConfig.setModelnotifyurl("https://admin.malls.iformall.com/wxMsgCallback/receivemodel/" + wxMsgConfig.getTenantId()); +// wxMsgConfig.setVerifynotifyurl("https://admin.malls.iformall.com/wxMsgCallback/receiveverifymodel/" + wxMsgConfig.getTenantId()); +// } +// if(wxMsgConfig.getTotal() == null){ +// wxMsgConfig.setTotal((long) 100000); +// } +// wxMsgConfig.setRecharge((long) 0); +// wxMsgConfig.setRemains(wxMsgConfig.getTotal()); +// wxMsgConfig.setReminderstatus(0); +// wxMsgConfigService.saveOrUpdate(wxMsgConfig); +// return new ResultData(); +// }catch (Exception e){ +// logger.error(e.getMessage(),e); +// return new ResultData(ErrorCode.SYS_SERVER_ERROR); +// } +// } + + @ApiOperation("添加修改停车场配置") + @PostMapping("/init/park") + @SystemControllerLog(description = "商场停车场配置-更新") + @TenantIgnore + public ResultData initPark(@RequestBody WxPark wxPark) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initPark"); + try { + if(StringUtils.isBlank(wxPark.getTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(StringUtils.isBlank(wxPark.getAddr())){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(wxPark.getNumber() == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(wxPark.getId() == null && StringUtils.isBlank(wxPark.getVendorParams())){ + wxPark.setVendorParams("{}"); + } + if(wxPark.getId() == null && wxPark.getVendorType() == null){ + wxPark.setVendorType(0); + } + if(wxPark.getId() == null && StringUtils.isBlank(wxPark.getParkId())){ + wxPark.setParkId("0"); + } + if(wxPark.getId() == null && StringUtils.isBlank(wxPark.getStopFee())){ + wxPark.setStopFee(""); + } + if(wxPark.getId() == null && wxPark.getEntryExit() == null){ + wxPark.setEntryExit(1); + } + wxParkService.saveOrUpdate(wxPark); + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + +// @ApiOperation("添加修改迈外迪信息") +// @PostMapping("/init/wiwidi") +// @SystemControllerLog(description = "迈外迪信息配置-更新") +// public ResultData initWiwidi(@RequestBody WxWiWideInfo wxWiWideInfo) { +// logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initPark"); +// try { +// if(StringUtils.isBlank(wxWiWideInfo.getTenantId())){ +// return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); +// } +// wxWiWideInfoService.saveOrUpdate(wxWiWideInfo); +// return new ResultData(); +// }catch (Exception e){ +// logger.error(e.getMessage(),e); +// return new ResultData(ErrorCode.SYS_SERVER_ERROR); +// } +// } + +// @ApiOperation("添加修改微信公众账号的基本信息") +// @PostMapping("/init/authorizer") +// @SystemControllerLog(description = "微信公众账号的基本信息-更新") +// public ResultData initAuthorizer(@RequestBody WxAuthorizerInfo wxAuthorizerInfo) { +// logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initAuthorizer"); +// try { +// if(StringUtils.isBlank(wxAuthorizerInfo.getTenantId())){ +// return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); +// } +// if(wxAuthorizerInfo.getAuthorizationStatus() == null){ +// wxAuthorizerInfo.setAuthorizationStatus(0);//授权状态,0为已授权,1为已取消授权 +// wxAuthorizerInfo.setAuthTime(new Date()); +// } +// if(wxAuthorizerInfo.getBaseStatus() == null){ +// wxAuthorizerInfo.setBaseStatus(0);//微信基础版本设置状态,0为已设置,1为设置失败 +// wxAuthorizerInfo.setBaseTime(new Date()); +// } +// if(wxAuthorizerInfo.getDomainStatus() == null){ +// wxAuthorizerInfo.setDomainStatus(0);//服务器域名设置状态,0为已设置,1为设置失败 +// wxAuthorizerInfo.setDomainTime(new Date()); +// } +// if(wxAuthorizerInfo.getWebdomainStatus() == null){ +// wxAuthorizerInfo.setWebdomainStatus(0);//服务器业务域名设置状态,0为已设置,1为设置失败 +// wxAuthorizerInfo.setWebdomainTime(new Date()); +// } +// if(StringUtils.isNotBlank(wxAuthorizerInfo.getCurrentVersion()) +// && wxAuthorizerInfo.getReleaseTime() != null){ +// wxAuthorizerInfo.setReleaseTime(new Date()); +// } +// if(StringUtils.isNotBlank(wxAuthorizerInfo.getOpenAppid()) +// && wxAuthorizerInfo.getBindOpenTime() != null){ +// wxAuthorizerInfo.setBindOpenTime(new Date()); +// } +// if(StringUtils.isBlank(wxAuthorizerInfo.getRefreshToken())){ +// wxAuthorizerInfo.setRefreshToken(""); +// } +// if(StringUtils.isBlank(wxAuthorizerInfo.getAccessToken())){ +// wxAuthorizerInfo.setAccessToken(""); +// } +// wxAuthorizerInfoService.saveOrUpdate(wxAuthorizerInfo); +// return new ResultData(); +// }catch (Exception e){ +// logger.error(e.getMessage(),e); +// return new ResultData(ErrorCode.SYS_SERVER_ERROR); +// } +// } + + @ApiOperation("查询商场基础数据") + @GetMapping(value = "/getinit/{id}") + @SystemControllerLog(description = "商场基础数据") + @TenantIgnore + public ResultData getinit(@PathVariable Long id) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::getinit"); + try { + Map map = new HashMap(); + WxMall wxMall = wxMallService.getById(id); + map.put("wxMall",wxMall); + List subWxMall = wxMallService.getSubByParentTenantId(wxMall.getTenantId()); + map.put("subWxMall",subWxMall); + WxCouponSendConfig wxCouponSendConfig = new WxCouponSendConfig(); + wxCouponSendConfig.setTenantId(wxMall.getTenantId()); + List wxCouponSendConfigList = wxCouponSendConfigService.findList(wxCouponSendConfig); + map.put("wxCouponSendConfigList",wxCouponSendConfigList); + WxScoreRules wxScoreRules = new WxScoreRules(); + wxScoreRules.setTenantId(wxMall.getTenantId()); + List wxScoreRulesList = wxScoreRulesService.findList(wxScoreRules); + map.put("wxScoreRulesList",wxScoreRulesList); + WxTemplateMsg wxTemplateMsg = new WxTemplateMsg(); + wxTemplateMsg.setTenantId(wxMall.getTenantId()); + + List wxTemplateMsgList = wxTemplateMsgService.findList(wxTemplateMsg); + map.put("wxTemplateMsgList",wxTemplateMsgList); + WxQuestion wxQuestion = new WxQuestion(); + wxQuestion.setTenantId(wxMall.getTenantId()); + + List wxQuestionList = wxQuestionService.findList(wxQuestion); + map.put("wxQuestionList",wxQuestionList); + WxMsgValidationcodeModel wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); + wxMsgValidationcodeModel.setTenantId(wxMall.getTenantId()); + + List wxMsgValidationcodeModelList = wxMsgValidationcodeModelService.findList(wxMsgValidationcodeModel); + map.put("wxMsgValidationcodeModelList",wxMsgValidationcodeModelList); + WxFlowConfig wxFlowConfig = new WxFlowConfig(); + wxFlowConfig.setTenantId(wxMall.getTenantId()); + + List wxFlowConfigList = wxFlowConfigService.findList(wxFlowConfig); + map.put("wxFlowConfigList",wxFlowConfigList); + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(wxMall.getTenantId()); + + ResultData wxMallBuildingFloorList = wxMallBuildingService.getBuildingFloorList(tenantEntity); + map.put("wxMallBuildingFloorList",wxMallBuildingFloorList.data); + WxPayAccount wxPayAccount = wxPayAccountService.getByTenantId(wxMall.getTenantId()); + map.put("wxPayAccount",wxPayAccount); + WxPayAccountBill wxPayAccountBill = wxPayAccountBillService.getByTenantId(wxMall.getTenantId()); + map.put("wxPayAccountBill",wxPayAccountBill); + WxAppinfo wxAppinfo = new WxAppinfo(); + wxAppinfo.setTenantId(wxMall.getTenantId()); + + List wxAppinfoList = wxAppinfoService.getList(wxAppinfo); + map.put("wxAppinfoList",wxAppinfoList); + MallUserInfo mallUserInfo = new MallUserInfo(); + mallUserInfo.setTenantId(wxMall.getTenantId()); + mallUserInfo. setIsAdmin(1); + + List mallUserInfoList = mallUserInfoService.findList(mallUserInfo); + map.put("mallUserInfoList",mallUserInfoList); + WxMsgConfig wxMsgConfig = new WxMsgConfig(); + wxMsgConfig.setTenantId(wxMall.getTenantId()); + + WxMsgConfig wxMsgConfigObject = wxMsgConfigService.findObject(wxMsgConfig); + map.put("wxMsgConfig",wxMsgConfigObject); + WxPark wxPark = new WxPark(); + wxPark.setTenantId(wxMall.getTenantId()); + + WxPark wxParkObj = wxParkService.getByObj(wxPark); + map.put("wxPark",wxParkObj); + WxWiWideInfo wxWiWideInfo = new WxWiWideInfo(); + wxWiWideInfo.setTenantId(wxMall.getTenantId()); + + WxWiWideInfo wxWiWideInfoObject = wxWiWideInfoService.findObject(wxWiWideInfo); + map.put("wxWiWideInfo",wxWiWideInfoObject); + WxWeappInfo wxWeappInfo = new WxWeappInfo(); + wxWeappInfo.setTenantId(wxMall.getTenantId()); + + List wxAuthorizerInfoList = wxAuthorizerInfoService.getList(wxWeappInfo); + map.put("wxAuthorizerInfoList",wxAuthorizerInfoList); + + return new ResultData(map); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("集团新增修改子广场") + @PostMapping("/init/submall") + @SystemControllerLog(description = "子广场-更新") + @TenantIgnore + public ResultData initSubmall(@RequestBody Map map) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initSubmall"); + try { + String tenantId = (String) map.get("tenantId"); + List subTenantIds = (List) map.get("subTenantIds"); + + if(StringUtils.isBlank(tenantId)){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } +// if(subTenantIds == null || subTenantIds.length == 0){ +// return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); +// } + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(tenantId); + WxMall parentWxMall = wxMallService.getByTenantInfo(tenantEntity); + if(parentWxMall == null || parentWxMall.getSaleType() != 100 + || !parentWxMall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode()) + || StringUtils.isNotBlank(parentWxMall.getParentTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR); + } + wxProjectConfigService.initSubmall(tenantId,subTenantIds); + + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("刷集团商场历史数据(五分钟内只能掉一次)") + @PostMapping("/init/after/group") + @SystemControllerLog(description = "商场-数据更新") + @TenantIgnore + public ResultData initAfterGroup(@RequestBody Map map) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initAfterGroup"); + try { + String tenantId = (String) map.get("tenantId"); + List subTenantIds = (List) map.get("subTenantIds"); + String subTenantIdStrs = null; + + if(StringUtils.isBlank(tenantId)){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(subTenantIds == null || subTenantIds.size() == 0){ + //return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + }else{ + subTenantIdStrs = StringUtils.join(subTenantIds, ','); + } + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(tenantId); + + WxMall parentWxMall = wxMallService.getByTenantInfo(tenantEntity); + if(parentWxMall == null || parentWxMall.getSaleType() != 100 + || !parentWxMall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode()) + || StringUtils.isNotBlank(parentWxMall.getParentTenantId())){ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR); + } + StringBuilder sb = new StringBuilder(); + sb.append(Constant.INTERFACE_VISIT_LIMIT_KEY).append("initAfterGroup"); + String key = sb.toString(); + boolean hasKey = openRedisTemplate.hasKey(key); + if(hasKey){ + return new ResultData(ErrorCode.TOO_MANY_REQUEST); + }else{ + openRedisTemplate.opsForValue().set(key,"1",3000, TimeUnit.SECONDS); + } + +// String join = StringUtils.join(subTenantIds, ','); + wxProjectConfigService.initAfterGroup(tenantId,subTenantIdStrs); + + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("查询ext数据") + @GetMapping(value = "/getExt/{appId}") + @SystemControllerLog(description = "商场基础数据") + @TenantIgnore + public ResultData getExt(@PathVariable String appId) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::getExt"); + try { + if(StringUtils.isBlank(appId)){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + WxWeappExtSet byAppId = wxWeappExtSetService.getByAppId(appId); + return new ResultData(byAppId); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + + @ApiOperation("添加修改ext数据配置") + @PostMapping("/init/appExt") + @SystemControllerLog(description = "商场ext数据配置-更新") + @TenantIgnore + public ResultData initAppExt(@RequestBody WxWeappExtSet wxWeappExtSet) { + logger.debug("[" + getIpAddr() + "] WxProjectConfigController::initAppExt"); + try { + wxWeappExtSetService.updateById(wxWeappExtSet); + return new ResultData(); + }catch (Exception e){ + logger.error(e.getMessage(),e); + return new ResultData(ErrorCode.SYS_SERVER_ERROR); + } + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxShopController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxShopController.java new file mode 100644 index 000000000..be6b6cce8 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxShopController.java @@ -0,0 +1,189 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.WxShop; +import com.iformall.service.WxShopService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxShop") +public class WxShopController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxShopService wxShopService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "店铺管理-列表") + public ResultData list(@ModelAttribute WxShop wxShop, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxShopController::list"); + if (null == wxShop){ + wxShop = new WxShop(); + } + wxShop.updateTenantInfo(getTenantInfo()); + wxShop.setSortColumns(BaseEntity.SortField.CreateDate_DESC,BaseEntity.SortField.Id_DESC); + + final PageInfo> page = wxShopService.listMapAsPage(wxShop, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "店铺管理-新增") + public ResultData add(@RequestBody WxShop wxShop) { + logger.debug("[" + getIpAddr() + "] WxShopController::add"); + wxShop.updateTenantInfo(getTenantInfo()); + return wxShopService.saveOrUpdate(wxShop); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "店铺管理-更新") + public ResultData update(@RequestBody WxShop wxShop) { + logger.debug("[" + getIpAddr() + "] WxShopController::update"); + if (null == wxShop){ + wxShop = new WxShop(); + } + wxShop.updateTenantInfo(getTenantInfo()); + return wxShopService.saveOrUpdate(wxShop); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @SystemControllerLog(description = "店铺管理-删除") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxShopController::delete"); + Integer isAdmin = getUser().getIsAdmin(); + return wxShopService.deleteById(id, isAdmin); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "店铺管理-id查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxShopController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxShopService.getById(id)); + } + + @ApiOperation("获取商铺数据") + @GetMapping("getShopListByShopNumber") + @ApiImplicitParam(name = "shopNumber", value = "shopNumber", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "店铺管理-获取商铺数据") + public ResultData getShoplist(String shopNumber) { + logger.debug("[" + getIpAddr() + "] WxShopController::getbshoplist"); + return wxShopService.getShopList(getTenantInfo(), shopNumber); + } + + @ApiOperation("获取商户商铺数据") + @GetMapping("getMerchantShopByShopId") + @ApiImplicitParam(name = "shopId", value = "shopId", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "店铺管理-获取商户商铺数据") + public ResultData getMerchantShopByShopId(String shopId) { + logger.debug("[" + getIpAddr() + "] WxShopController::getMerchantShopByShopId"); + return wxShopService.getMerchantShopByShopId(getTenantInfo(), shopId); + } + + @ApiOperation("查询商铺号是否存在") + @GetMapping("hasShopNumber") + @ApiImplicitParams({ + @ApiImplicitParam(name = "shopNumber", value = "shopNumber", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query"), + @ApiImplicitParam(name = "type", value = "type", dataType = "Integer", paramType = "query", required = true)}) + @SystemControllerLog(description = "店铺管理-查询商铺号是否存在") + public ResultData hasShopNumber(String shopNumber, Long id, Integer type) { + logger.debug("[" + getIpAddr() + "] WxShopController::hasShopNumber"); + WxShop wxShop = new WxShop() {{ + setShopNumber(shopNumber); + setType(type); + }}; + wxShop.setId(id); + wxShop.updateTenantInfo(getTenantInfo()); + return wxShopService.hasShopNumber(wxShop); + } + + + @ApiOperation("分页列表接品-合同访问") + @GetMapping("listShopFromContract") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "店铺管理-合同访问") + public ResultData listShopFromContract(@ModelAttribute WxShop wxShop, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxShopController::listShopFromContract"); + if (null == wxShop){ + wxShop = new WxShop(); + } + wxShop.updateTenantInfo(getTenantInfo()); + wxShop.setSortColumns(BaseEntity.SortField.CreateDate_DESC,BaseEntity.SortField.Id_DESC); + final PageInfo> page = wxShopService.listShopFromContract(wxShop, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("导出店铺") + @GetMapping("/exportShop") + @SystemControllerLog(description = "店铺管理-导出店铺") + public void exportShop(@ModelAttribute WxShop wxShop, HttpServletRequest request, HttpServletResponse response) { + logger.debug("[" + getIpAddr() + "] WxShopController::exportShop"); + if (null == wxShop){ + wxShop = new WxShop(); + } + wxShop.updateTenantInfo(getTenantInfo()); + wxShop.setSortColumns(BaseEntity.SortField.CreateDate_DESC,BaseEntity.SortField.Id_DESC); + wxShopService.exportShop(wxShop, request, response); + } + + @ApiOperation("导出未出租店铺") + @GetMapping("/exportNotRentShop") + @SystemControllerLog(description = "商铺出租数据-未出租商铺列表-导出") + public void exportNotRentShop(@ModelAttribute WxShop wxShop, HttpServletRequest request, HttpServletResponse response) { + logger.debug("[" + getIpAddr() + "] WxShopController::exportNotRentShop"); + if (null == wxShop){ + wxShop = new WxShop(); + } + wxShop.updateTenantInfo(getTenantInfo()); + wxShop.setSortColumns(BaseEntity.SortField.SCreateDate_DESC,BaseEntity.SortField.SId_DESC); + wxShopService.exportNotRentShop(wxShop, request, response); + } + + @ApiOperation("未出租商铺分页列表接口") + @GetMapping("notRentShopList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "未出租商铺分页列表接口") + public ResultData notRentShopList(@ModelAttribute WxShop wxShop, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxShopController::notRentShopList"); + if (null == wxShop){ + wxShop = new WxShop(); + } + wxShop.updateTenantInfo(getTenantInfo()); + wxShop.setSortColumns(BaseEntity.SortField.SCreateDate_DESC,BaseEntity.SortField.SId_DESC); + + final PageInfo> page = wxShopService.notRentListMapAsPage(wxShop, pageNum, pageSize); + return new ResultData(page); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxTagsController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxTagsController.java new file mode 100644 index 000000000..1a14dcc9f --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/basic/WxTagsController.java @@ -0,0 +1,52 @@ +package com.iformall.controller.basic; + +import java.util.Arrays; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.controller.base.BaseController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.RestController; + +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.service.WxCUserTagsService; +import com.iformall.service.WxTagsService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@RestController +@RequestMapping("wxTags") +@Api(description="标签弹窗接口") +public class WxTagsController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxTagsService wxTagsService; + + + @Autowired + private WxCUserTagsService wxCUserTagsService; + + @GetMapping("getAllList") + @ApiOperation("标签弹窗接口") + @SystemControllerLog(description = "会员管理-标签获取") + public ResultData getAllList() { + logger.debug("[" + getIpAddr() + "] WxTagsController::getAllList"); + return new ResultData(wxTagsService.listAllVo()); + } + + @ApiOperation("查询会员用户人群") + @GetMapping("findCountByTag") + @SystemControllerLog(description = "会员管理-查询会员用户人群") + public Result findCountByTag(Long[] tagIds) { + logger.debug("[" + getIpAddr() + "] WxTagsController::findCountByTag"); + return new ResultData(wxCUserTagsService.findTagList(getTenantInfo(), Arrays.asList(tagIds))); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java new file mode 100644 index 000000000..2a7770e4f --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java @@ -0,0 +1,81 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.WxMsgCallback; +import com.iformall.service.WxMsgCallbackService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("msgCallback") +public class WxMsgCallbackController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgCallbackService wxMsgCallbackService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "短信回调结果-列表") + public ResultData list(@ModelAttribute WxMsgCallback wxMsgCallback, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::list"); + if (null == wxMsgCallback) wxMsgCallback = new WxMsgCallback(); + wxMsgCallback.updateTenantInfo(getTenantInfo()); + wxMsgCallback.setSortColumns(BaseEntity.SortField.Createtime_DESC); + final PageInfo page = wxMsgCallbackService.listAsPage(wxMsgCallback, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "短信回调结果-新增") + public ResultData add(@RequestBody WxMsgCallback wxMsgCallback) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::add"); + //Assert.notNull(wxMsgCallback.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgCallback.updateTenantInfo(getTenantInfo()); + wxMsgCallbackService.saveOrUpdate(wxMsgCallback); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "短信回调结果-更新") + public ResultData update(@RequestBody WxMsgCallback wxMsgCallback) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::update"); + wxMsgCallbackService.saveOrUpdate(wxMsgCallback); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信回调结果-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::delete"); + wxMsgCallbackService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信回调结果-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgCallbackService.getById(id)); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgConfigController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgConfigController.java new file mode 100644 index 000000000..ca0711d16 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgConfigController.java @@ -0,0 +1,81 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgConfig; +import com.iformall.service.WxMsgConfigService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgConfig") +public class WxMsgConfigController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgConfigService wxMsgConfigService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "短信-配置-列表") + public ResultData list(@ModelAttribute WxMsgConfig wxMsgConfig, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::list"); + if (null == wxMsgConfig) wxMsgConfig = new WxMsgConfig(); + final PageInfo page = wxMsgConfigService.listAsPage(wxMsgConfig, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "短信-配置-新增") + public ResultData add(@RequestBody WxMsgConfig wxMsgConfig) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::add"); + //Assert.notNull(wxMsgConfig.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgConfig.updateTenantInfo(getTenantInfo()); + wxMsgConfigService.saveOrUpdate(wxMsgConfig); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "短信-配置-更新") + public ResultData update(@RequestBody WxMsgConfig wxMsgConfig) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::update"); + wxMsgConfig.updateTenantInfo(getTenantInfo()); + wxMsgConfigService.saveOrUpdate(wxMsgConfig); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信-配置-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::delete"); + wxMsgConfigService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信-配置-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgConfigService.getById(id)); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgController.java new file mode 100644 index 000000000..af1e096a0 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgController.java @@ -0,0 +1,174 @@ +package com.iformall.controller.msg; + +import com.aliyun.openservices.shade.com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxTemplateMsg; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.po.msg.WxMsg; +import com.iformall.enums.EnumSendWay; +import com.iformall.service.WxMsgService; +import com.iformall.service.WxTemplateMsgService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.*; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxMsg") +public class WxMsgController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private String fmUploadDir; + + @Autowired + private WxMsgService wxMsgService; + + @Autowired + WxTemplateMsgService wxTemplateMsgService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "标签短信-列表") + public ResultData list(@ModelAttribute WxMsg wxMsg, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgController::list"); + if (null == wxMsg) wxMsg = new WxMsg(); + wxMsg.updateTenantInfo(getTenantInfo()); + //wxMsg.setWay(EnumSendWay.TAG.getCode()); + wxMsg.setSortColumns(BaseEntity.SortField.Createtime_DESC); + final PageInfo page = wxMsgService.listAsPage(wxMsg, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("模板分页列表接口") + @GetMapping("templateList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "moban-列表") + public ResultData templateList(@ModelAttribute WxTemplateMsg wxTemplateMsg, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgController::list"); + if (null == wxTemplateMsg) wxTemplateMsg = new WxTemplateMsg(); + wxTemplateMsg.updateTenantInfo(getTenantInfo()); + final PageInfo page = wxTemplateMsgService.listAsPageForMiniApp(wxTemplateMsg, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("修改模板接口") + @PostMapping("tempUpd") + @SystemControllerLog(description = "moban xiugai") + public ResultData tempUpd(@RequestBody WxTemplateMsg wxTemplateMsg) { + logger.debug("[" + getIpAddr() + "] WxMsgController::tempUpd"); + if(wxTemplateMsg.getId() == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxTemplateMsg.updateTenantInfo(getTenantInfo()); +// if(null == wxTemplateMsg.getOnOff()){ +// wxTemplateMsg.setOnOff(1); +// } + wxTemplateMsgService.saveOrUpdate(wxTemplateMsg); + return new ResultData(); + } + + @ApiOperation("推送模板") + @PostMapping("pushTemp") + @SystemControllerLog(description = "moban tuisong") + public ResultData pushTemp(@RequestBody WxTemplateMsg wxTemplateMsg) { + logger.debug("[" + getIpAddr() + "] WxMsgController::tuisong"); + if(wxTemplateMsg.getId() == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxTemplateMsg.updateTenantInfo(getTenantInfo()); +// if(null == wxTemplateMsg.getOnOff()){ +// wxTemplateMsg.setOnOff(1); +// } + return wxTemplateMsgService.pushTemp(wxTemplateMsg); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "标签短信-新增") + public ResultData add(@RequestBody WxMsg wxMsg) { + logger.debug("[" + getIpAddr() + "] WxMsgController::add"); + wxMsg.updateTenantInfo(getTenantInfo()); + if(null == wxMsg.getWay()){ + wxMsg.setWay(EnumSendWay.TAG.getCode()); + } + if(wxMsg.getWay() == EnumSendWay.APPINFOR.getCode() && !JSONObject.isValidObject(wxMsg.getMsg())){ + return new ResultData(ErrorCode.TEMPLATE_DATA_ERROR); + } + return wxMsgService.add(wxMsg); + } + + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "标签短信-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgController::delete"); + if(id == null){ + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + wxMsgService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "标签短信-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgController::findById"); + WxMsg wxMsg = wxMsgService.getById(id); + return new ResultData(wxMsg); + } + + + @RequestMapping("/excleupload") + @SystemControllerLog(description = "标签短信-导出") + public ResultData excleupload(@RequestParam("file") MultipartFile file) { + logger.debug("[" + getIpAddr() + "] WxMsgController::excleupload"); + if (file.isEmpty()) { + return new ResultData(Result.SUCCESS, "上传文件不能为空"); + } + + String filename = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); + File path = new File(fmUploadDir); + if (!path.exists()) { + path.mkdirs(); + } + String filepath = fmUploadDir + filename; + try { + FileOutputStream out = new FileOutputStream(new File(filepath)); + IOUtils.write(file.getBytes(), out); + IOUtils.closeQuietly(out); + } catch (Exception e) { + return new ResultData(Result.ERROR, "上传失败"); + } + + return new ResultData(Result.SUCCESS, "上传成功", filepath); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgModelController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgModelController.java new file mode 100644 index 000000000..8a9ee6640 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgModelController.java @@ -0,0 +1,90 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.WxMsgModel; +import com.iformall.service.WxMsgModelService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgModel") +public class WxMsgModelController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgModelService wxMsgModelService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "短信模板-列表") + public ResultData list(@ModelAttribute WxMsgModel wxMsgModel, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::list"); + if (null == wxMsgModel) wxMsgModel = new WxMsgModel(); + wxMsgModel.updateTenantInfo(getTenantInfo()); + wxMsgModel.setSortColumns(BaseEntity.SortField.Createtime_DESC); + final PageInfo page = wxMsgModelService.listAsPage(wxMsgModel, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "短信模板-新增") + public ResultData add(@RequestBody WxMsgModel wxMsgModel) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::add"); + //Assert.notNull(wxMsgModel.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgModel.updateTenantInfo(getTenantInfo()); + return wxMsgModelService.saveOrUpdate(wxMsgModel); + + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "短信模板-更新") + public ResultData update(@RequestBody WxMsgModel wxMsgModel) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::update"); + return wxMsgModelService.saveOrUpdate(wxMsgModel); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信模板-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::delete"); + wxMsgModelService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信模板-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgModelService.getById(id)); + } + + @ApiOperation("获取所有数据") + @GetMapping("getmodellist") + @SystemControllerLog(description = "短信模板-获取所有数据") + public ResultData getModelList() { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::getmodellist"); + return wxMsgModelService.getModelList(getTenantInfo()); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgRecordController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgRecordController.java new file mode 100644 index 000000000..43c391a07 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgRecordController.java @@ -0,0 +1,128 @@ +package com.iformall.controller.msg; + +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.po.msg.*; +import com.iformall.enums.*; +import com.iformall.mapper.WxMsgMapper; +import com.iformall.mq.MqBaseProducer; +import com.iformall.service.WxMsgRecordService; +import com.iformall.service.msg.impl.SendCallBackSmsServiceImpl; +import com.iformall.utils.JsonUtil; +import io.swagger.annotations.Api; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@Api(description = "消息记录") +@RequestMapping(value = "msgrecord") +public class WxMsgRecordController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgRecordService wxMsgRecordService; + @Autowired + private MqBaseProducer mqBaseProducer; + @Autowired + private SendCallBackSmsServiceImpl msgSendService; + + + @GetMapping(value = "/test") + public ResultData test(Long id) throws Exception{ +// String systemTime = DateUtils.getSystemTime("yyyy-MM-dd HH:00:00"); +// WxMsg wxMsg = new WxMsg(); +// wxMsg.setIsright(0); +// wxMsg.setSendtime(systemTime); +// wxMsg.setId(id); +// List list = wxMsgMapper.findList(wxMsg); +// logger.info("将要发送的短信列表:" + JSONArray.toJSONString(list)); +// for (WxMsg msg : list) { +// //sendmsg(msg); +// msg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode()); +// msg.setReceiver(msg.getPhones()); +// mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(),null); +// } + + String s = "{\"msg\": \"新手妈妈不要怕,金宝贝帮您带孩子,音乐美术还有游戏,孩子玩着玩着就长大了\", \"way\": 2, \"name\": \"亲子活动\", \"uuid\": \"0a4ae632-9522-4a8f-bb0d-b22620ac79c3\", \"label\": \"\", \"domain\": 0, \"phones\": \"18601973448\", \"status\": 1, \"isright\": 1, \"modelId\": 204500584231862272, \"msgType\": 2, \"receiver\": \"18601973448\", \"sendtime\": \"2019-04-17 18:29:08\", \"tenantId\": \"456\", \"signature\": \"富茂科技\", \"errorNumber\": 0, \"wxMsgConfig\": {\"id\": 1, \"bid\": \"465565\", \"appid\": \"wx9ff823abeef23b94\", \"total\": 100000, \"secret\": \"7305150347587283553aa8898e7dbf20\", \"account\": \"15626593768\", \"remains\": 62667, \"recharge\": 0, \"tenantId\": \"456\", \"notifyurl\": \"http://202.165.179.86:9000/wxMsgCallback/receivemsg/456\", \"publickey\": \"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvh8j/zagfxQdnSh5OIic\\r\\nMzN+MuRuWQJPjgu4Gza4+gX3j5Ln2xNDBOTjpwyuLBjh/JcBd1cGO3lAaKCwcaix\\r\\nsmhTq56wVXXUMgDiAChu4ud8FSvRc8G8tdZAirKVAIi3NW+/pYgpWBs/0wnF8hz4\\r\\n8no4pyJHl9Jc1LH3VNIMz8vqzKUPc4ack4pFUXlcNj6C+sBlaurmI4/vwLqNxBGs\\r\\n7/zyM7dv6oy3DSU/Y1qBArM1YPjfL2dNun8rmtPgJvlPwXqA7uoHPwQ2Ym3aUn59\\r\\npkS7QI6IE8uuqNkfSte8BXLd2nIqPLFxLYLDmdll7eoyRblHcHqAYSj8stK6StC7\\r\\nDNryNKEjTEwbgf9trUI0uvF1pfgTy2gpclnY69FtD/m0+FvLyorMq+nmBqYMjka5\\r\\nK0txDQJPOa7gsi//uXd/cJW2SAXY9MSO1AfMi8Xq/YKRQzN9FW5iapskXFHca7uX\\r\\ng5NhH7flr6DW+QInFlpoN6WIEAuDF1aj4O49Ikm3WxwhTqnvEkdSCfivpYQkp9Sh\\r\\n4kQ/SQdxuT7VX+Nz6k+uMx2z4cySk33bHi0KoHbA9QFGg/54Qd0+eU4qZnd4mrgh\\r\\nhH7/QQhL7Z9eF1U5UPrsHq2Vq3rEnN+tYQ26AuKeU8vzTxBrC/SxC6C/SMFt3f/Y\\r\\nnuFh1UnNJZleZwyQt+ZdGO0CAwEAAQ==\", \"modelnotifyurl\": \"http://202.165.179.86:9000/wxMsgCallback/receivemodel/456\", \"reminderstatus\": 0, \"verifynotifyurl\": \"http://202.165.179.86:9000/wxMsgCallback/receiveverifymodel/456\"}, \"couponInject\": {\"id\": 278440211602472960, \"name\": \"END\", \"tags\": \"[{\\\"name\\\":\\\"一天以上+普通会员+男\\\",\\\"tagList\\\":[{\\\"id\\\":1011,\\\"typeId\\\":50},{\\\"id\\\":0,\\\"typeId\\\":51},{\\\"id\\\":1}]},{\\\"name\\\":\\\"一月以上+男\\\",\\\"tagList\\\":[{\\\"id\\\":1009,\\\"typeId\\\":50},{\\\"id\\\":1}]}]\", \"status\": 2, \"mUserId\": 204398756307664896, \"modelId\": 204500584231862272, \"muserId\": 204398756307664896, \"couponId\": 275856462247362560, \"sendTime\": \"2019-04-17 18:28:49\", \"sendType\": 0, \"tenantId\": \"456\", \"couponName\": \"礼品券大礼5\", \"filterList\": [{\"name\": \"一天以上+普通会员+男\", \"tagList\": [{\"id\": 1011, \"typeId\": 50}, {\"id\": 0, \"typeId\": 51}, {\"id\": 1}]}, {\"name\": \"一月以上+男\", \"tagList\": [{\"id\": 1009, \"typeId\": 50}, {\"id\": 1}]}], \"sendAmount\": 40}, \"successNumber\": 0, \"delayTimeLevel\": 0, \"expectSendNumber\": 40}"; + WxMsg wxMsg = (WxMsg) JsonUtil.readValue(s,WxMsg.class); + wxMsg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode()); + wxMsg.setReceiver("18601973448"); + wxMsg.setTenantId("456"); + msgSendService.send(wxMsg); + return new ResultData(); + } + + /** + * 重新发送失败的消息 + * @param x + * @return + */ + @GetMapping(value = "/resendMsg") + public ResultData resendMsg(String x, String tenantId, Integer msgType) { + logger.debug("[" + getIpAddr() + "] WxMsgRecordController::resendMsg"); + if("xll1dxx1314".equals(x)){ + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(tenantId); + WxMsgRecord msgRecord = new WxMsgRecord(); + msgRecord.setMsgType(msgType); + msgRecord.updateTenantInfo(tenantEntity); + msgRecord.setMsgStatus(EnumMsgRecordStatus.CONSUME_FAIL.getCode()); + List recordList = wxMsgRecordService.findList(msgRecord); + for (WxMsgRecord wxMsgRecord:recordList) { + if(EnumMsgRecordType.SMS.getCode().equals(wxMsgRecord.getMsgType())){ + //短信 + mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.SMS_CALLBACK.getCode().equals(wxMsgRecord.getMsgType())){ + //业务短信 + WxMsg wxMsg = (WxMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),WxMsg.class); + wxMsg.setMsgType(wxMsgRecord.getMsgType()); + wxMsg.setReceiver(wxMsgRecord.getReceiver()); + wxMsg.updateTenantInfo(tenantEntity); + mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.EMAIL.getCode().equals(wxMsgRecord.getMsgType())){ + //邮件 + MailMsg wxMsg = (MailMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),MailMsg.class); + wxMsg.setMsgType(wxMsgRecord.getMsgType()); + wxMsg.setReceiver(wxMsgRecord.getReceiver()); + wxMsg.updateTenantInfo(tenantEntity); + mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); +// }else if(EnumMsgRecordType.SMART_APP.getCode().equals(wxMsgRecord.getMsgType())){ + }else if(EnumMsgRecordType.SMART_APP_TO.getCode().equals(wxMsgRecord.getMsgType())){ + //微信小程序 + SmartAppMsg wxMsg = (SmartAppMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),SmartAppMsg.class); + wxMsg.setMsgType(wxMsgRecord.getMsgType()); + wxMsg.setReceiver(wxMsgRecord.getReceiver()); + wxMsg.updateTenantInfo(tenantEntity); + mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.INSIDE_ORDER_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ + //内部消息 - 下订单成功 + FmInsideOrderSuccessMsg msg = (FmInsideOrderSuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideOrderSuccessMsg.class); + msg.setMsgType(wxMsgRecord.getMsgType()); + msg.setReceiver(wxMsgRecord.getReceiver()); + msg.updateTenantInfo(tenantEntity); + mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.INSIDE_COUPON_VERIFY.getCode().equals(wxMsgRecord.getMsgType())){ + //内部消息 - 券核销 + FmInsideCouponVerifyMsg msg = (FmInsideCouponVerifyMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideCouponVerifyMsg.class); + msg.setMsgType(wxMsgRecord.getMsgType()); + msg.setReceiver(wxMsgRecord.getReceiver()); + msg.setTenantId(wxMsgRecord.getTenantId()); + msg.updateTenantInfo(tenantEntity); + mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + } + } + return new ResultData(); + }else{ + return new ResultData("fail"); + } + } + + + + + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgSignatureController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgSignatureController.java new file mode 100644 index 000000000..7e720295a --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgSignatureController.java @@ -0,0 +1,92 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.WxMsgSignature; +import com.iformall.service.WxMsgSignatureService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgSignature") +public class WxMsgSignatureController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgSignatureService wxMsgSignatureService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "消息签名-列表") + public ResultData list(@ModelAttribute WxMsgSignature wxMsgSignature, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::list"); + if (null == wxMsgSignature) wxMsgSignature = new WxMsgSignature(); + wxMsgSignature.updateTenantInfo(getTenantInfo()); + wxMsgSignature.setSortColumns(BaseEntity.SortField.Createtime_DESC); + final PageInfo page = wxMsgSignatureService.listAsPage(wxMsgSignature, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "消息签名-新增") + public ResultData add(@RequestBody WxMsgSignature wxMsgSignature) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::add"); + //Assert.notNull(wxMsgSignature.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgSignature.updateTenantInfo(getTenantInfo()); + wxMsgSignatureService.saveOrUpdate(wxMsgSignature); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "消息签名-更新") + public ResultData update(@RequestBody WxMsgSignature wxMsgSignature) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::update"); + wxMsgSignature.updateTenantInfo(getTenantInfo()); + wxMsgSignatureService.saveOrUpdate(wxMsgSignature); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息签名-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::delete"); + wxMsgSignatureService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息签名-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgSignatureService.getById(id)); + } + + @ApiOperation("获取所有数据") + @GetMapping("getsignaturelist") + @SystemControllerLog(description = "消息签名-获取所有") + public ResultData getsignaturelist() { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::getsignaturelist"); + return wxMsgSignatureService.getSignatureList(getTenantInfo()); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeController.java new file mode 100644 index 000000000..ba42f6a3d --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeController.java @@ -0,0 +1,119 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgValidationcode; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.service.WxMsgValidationcodeService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgValidationcode") +public class WxMsgValidationcodeController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgValidationcodeService wxMsgValidationcodeService; + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "消息验证码-列表") + public ResultData list(@ModelAttribute WxMsgValidationcode wxMsgValidationcode, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::list"); + if (null == wxMsgValidationcode) wxMsgValidationcode = new WxMsgValidationcode(); + final PageInfo page = wxMsgValidationcodeService.listAsPage(wxMsgValidationcode, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "消息验证码-添加") + public ResultData add(@RequestBody WxMsgValidationcode wxMsgValidationcode) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::add"); + //Assert.notNull(wxMsgValidationcode.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgValidationcode.updateTenantInfo(getTenantInfo()); + wxMsgValidationcodeService.saveOrUpdate(wxMsgValidationcode); + return new ResultData(); + } + + @PostMapping("update") + @SystemControllerLog(description = "消息验证码-更新") + public ResultData update(@RequestBody WxMsgValidationcode wxMsgValidationcode) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::update"); + wxMsgValidationcode.updateTenantInfo(getTenantInfo()); + wxMsgValidationcodeService.saveOrUpdate(wxMsgValidationcode); + return new ResultData(); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证码-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::update"); + wxMsgValidationcodeService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证码-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgValidationcodeService.getById(id)); + } + + + @GetMapping("sendvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "tenantId", value = "租户ID", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "parentTenantId", value = "父租户ID", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景", dataType = "Integer", paramType = "query", required = true), + @ApiImplicitParam(name = "appid", value = "appid", dataType = "String", paramType = "query", required = true)}) + public ResultData sendvalidationcode(String tenantId, String parentTenantId, String phone, Integer type, String appid) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::sendvalidationcode"); + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.updateTenantInfo(new TenantEntity(){{ + setTenantId(tenantId); + setParentTenantId(parentTenantId); + }}); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.setType(type); + wxMsgValidationcode.setAppid(appid); + return wxMsgValidationcodeService.sendvalidationcode(wxMsgValidationcode); + } + + @GetMapping("hasvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "tenantId", value = "租户ID", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "parentTenantId", value = "父租户ID", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景", dataType = "Integer", paramType = "query", required = true), + @ApiImplicitParam(name = "code", value = "验证码", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "appid", value = "appid", dataType = "String", paramType = "query", required = true)}) + public ResultData hasvalidationcode(String tenantId, String parentTenantId, String phone, Integer type, String code, String appid) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::hasvalidationcode"); + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.updateTenantInfo(new TenantEntity(){{ + setTenantId(tenantId); + setParentTenantId(parentTenantId); + }}); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.setType(type); + wxMsgValidationcode.setCode(code); + wxMsgValidationcode.setAppid(appid); + return wxMsgValidationcodeService.hasvalidationcode(wxMsgValidationcode); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeModelController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeModelController.java new file mode 100644 index 000000000..302b337b4 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeModelController.java @@ -0,0 +1,95 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgValidationcodeModel; +import com.iformall.enums.EnumMsgModelReplace; +import com.iformall.service.WxMsgValidationcodeModelService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgValidationcodeModel") +public class WxMsgValidationcodeModelController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgValidationcodeModelService wxMsgValidationcodeModelService; + + @ApiOperation("消息模板-列表") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "消息验证模板-列表") + public ResultData list(@ModelAttribute WxMsgValidationcodeModel wxMsgValidationcodeModel, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::list"); + if (null == wxMsgValidationcodeModel) wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); + wxMsgValidationcodeModel.updateTenantInfo(getTenantInfo()); + PageInfo page = wxMsgValidationcodeModelService.listAsPage(wxMsgValidationcodeModel, pageNum, pageSize); + page.getList().forEach(m -> { + for (EnumMsgModelReplace e : EnumMsgModelReplace.values()) { + m.setContent(m.getContent().replace(e.getCode(),e.getMessage())); + } + }); + return new ResultData(page); + } + + @ApiOperation("消息模板-添加") + @PostMapping("add") + @SystemControllerLog(description = "消息验证模板-添加") + public ResultData add(@RequestBody WxMsgValidationcodeModel wxMsgValidationcodeModel) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::add"); + //Assert.notNull(wxMsgValidationcodeModel.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgValidationcodeModel.updateTenantInfo(getTenantInfo()); + return wxMsgValidationcodeModelService.saveOrUpdate(wxMsgValidationcodeModel); + } + + @ApiOperation("消息模板-更新") + @PostMapping("update") + @SystemControllerLog(description = "消息验证模板-更新") + public ResultData update(@RequestBody WxMsgValidationcodeModel wxMsgValidationcodeModel) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::update"); + wxMsgValidationcodeModelService.saveOrUpdate(wxMsgValidationcodeModel); + return new ResultData(); + } + + @ApiOperation("消息模板-打开/关闭发送") + @PostMapping("updateOpen") + @SystemControllerLog(description = "消息验证模板-打开/关闭发送") + public ResultData updateOpen(@RequestBody WxMsgValidationcodeModel wxMsgValidationcodeModel) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::updateOpen"); + wxMsgValidationcodeModelService.update(wxMsgValidationcodeModel); + return new ResultData(); + } + + @ApiOperation("消息模板-删除") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证模板-删除") + public ResultData delete(String id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::delete"); + wxMsgValidationcodeModelService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("消息模板-查询") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证模板-查询") + public ResultData findById(String id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgValidationcodeModelService.getById(id)); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/HomeController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/HomeController.java new file mode 100644 index 000000000..786a9fabe --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/HomeController.java @@ -0,0 +1,467 @@ +package com.iformall.controller.sys; + +import com.alibaba.fastjson.JSON; +import com.google.code.kaptcha.Constants; +import com.google.code.kaptcha.Producer; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.vo.MallUserInfoVo; +import com.iformall.enums.*; +import com.iformall.exception.MallinkException; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.service.*; +import com.iformall.shiro.UserSession; +import com.iformall.shiro.UseriFormallToken; +import com.iformall.utils.ShiroUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; +import javax.imageio.ImageIO; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@RestController +@Api(description = "登录相关接口") +public class HomeController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Value("${version}") + private String version; + + @Autowired + private Producer producer; + + @Autowired + private MallUserInfoService mallUserInfoService; + + @Autowired + private MallUserRoleService mallUserRoleService; + + @Autowired + private WxAppinfoService appinfoService; + + @Autowired + private WxMsgValidationcodeService wxMsgValidationcodeService; + + @Autowired + private MallUserActionService mallUserActionService; + + @Autowired + private WxMallService mallService; + + @ApiOperation("验证码") + @GetMapping("/captcha.jpg") + public void captcha(HttpServletResponse response)throws ServletException, IOException { + logger.debug("[" + getIpAddr() + "] HomeController::captcha"); + response.setHeader("Cache-Control", "no-store, no-cache"); + response.setContentType("image/jpeg"); + + //生成文字验证码 + String text = producer.createText(); + //生成图片验证码 + BufferedImage image = producer.createImage(text); + //保存到shiro session + ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text); + + ServletOutputStream out = response.getOutputStream(); + ImageIO.write(image, "jpg", out); + IOUtils.closeQuietly(out); + } + + @ApiOperation("登录") + @PostMapping("/doLogin") + public ResultData login(@RequestBody MallUserInfo user, HttpServletResponse response) { + String ipaddress = getIpAddr(); + logger.debug("[" + ipaddress + "] HomeController::doLogin"); + try { + String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY); + if(!user.getCaptcha().equalsIgnoreCase(kaptcha)){ + return new ResultData(ErrorCode.KAPCHA_NOT_EQUAL); + } + } catch (MallinkException e) { + logger.error("验证码" + e.getMessage()); + return new ResultData(ErrorCode.KAPCHA_NOT_VALID.getCode(), e.getMessage()); + } + + + ResultData data = new ResultData(); + if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) { +// throw new SystemException(ErrorCode.LOGIN_USER_OR_PWD_ERROR); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + // check user + MallUserInfo userCheck = mallUserInfoService.getByUsername(user.getUsername()); + if(userCheck == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if(userCheck.getStatus().equals(EnumMallUserStatus.NOT_VALID.getCode())) { + logger.error(ErrorCode.USER_IS_LOCKED.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); + subject.login(token); + isLogin = true; + logger.info("ADMIN USER:"+user.getUsername() + ", password:" + user.getPassword()); + } catch (UnknownAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } catch (DisabledAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + + if(isLogin) { + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + mallUserActionService.saveActionInfo(info, EnumMallUserAction.CONTROLLER.getCode(), ipaddress, info.getId(), "用户登录"); + + WxMall mall = mallService.getByTenantInfo(info); + if(mall == null) { + logger.error("未配置相应的mall"); + return new ResultData(Result.ERROR, "未配置相应的mall"); + } + if(!mall.isValid()) { + logger.error("mall未启用"); + return new ResultData(Result.ERROR, "mall未启用"); + } + Map map = new HashMap(); + if (mall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode()) && + StringUtils.isBlank(info.getParentTenantId())) { + + Session session = SecurityUtils.getSubject().getSession(); + session.setAttribute(UserSession.tenantId, null); + session.setAttribute(UserSession.parentTenantId, info.getTenantId()); + + // 集团用户获取子商场 + List mallList = mallService.getSubByParentTenantId(info.getTenantId()); + map.put("mall", JSON.toJSONString(mall)); + map.put("subMalls", JSON.toJSONString(mallList)); + map.put("group", EnumGroupSupport.SUPPORT.getCode()); + } + + try { + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + map.put("username", info.getUsername()); + map.put("withWechat", info.getWithWechat()); + data.data = map; + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(Result.ERROR, e.getMessage()); + } + } + return data; + } + + private boolean isInMobileAdmin(MallUserInfo user) { + // 检查用户是否有 移动端数据塔台 权限 + boolean isInMobile = false; + isInMobile = mallUserRoleService.checkIsMobileAdmin(user); + return isInMobile; + } + + @PostMapping("/selectMall") + @ApiOperation(value = "用户选中子广场及父广场", notes = "{\"tenantId\":\"string\",\"parentTenantId\":\"string\"}") + public ResultData selectMall(@RequestBody Map map) { + logger.debug(map.toString()); + + String tenantId = map.get("tenantId"); + String subTenantId = map.get("subTenantId"); + String parentTenantId = map.get("parentTenantId"); + + if (StringUtils.isBlank(tenantId)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "tenantId不能为空"); + } + + MallUserInfo userInfo = getUser(); + if (userInfo.getTenantId().equalsIgnoreCase(tenantId)) { + Session session = SecurityUtils.getSubject().getSession(); + if (StringUtils.isNotBlank(subTenantId)) { + session.setAttribute(UserSession.tenantId, subTenantId); + session.setAttribute(UserSession.parentTenantId, tenantId); + } else { + session.setAttribute(UserSession.tenantId, null); + session.setAttribute(UserSession.parentTenantId, tenantId); + } + } + return new ResultData(); + } + + @ApiOperation("B端登录") + @PostMapping("/bHidLogin") + public ResultData bLogin(@RequestBody MallUserInfo user, HttpServletResponse response) { + String ipaddress = getIpAddr(); + logger.debug("[" + ipaddress + "] HomeController::bHidLogin"); + ResultData data = new ResultData(); + // tenantId is appId + if (StringUtils.isBlank(user.getTenantId())) { + logger.error("appid信息未提供"); + return new ResultData(ErrorCode.MALL_INFO_NOT_FOUND); + } + WxAppinfo appinfo = appinfoService.getByAppId(user.getTenantId()); + if (appinfo == null) { + logger.error("appid未找到"); + return new ResultData(ErrorCode.MALL_INFO_NOT_FOUND); + } + TenantEntity tenantEntity = new TenantEntity() {{ + setTenantId(appinfo.getTenantId()); + }}; + if (StringUtils.isNotBlank(user.getPhone())) { + // 领导登录 + user = mallUserInfoService.getByPhone(user.getPhone(), tenantEntity); + if (user == null || !isInMobileAdmin(user)) { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + } else if (StringUtils.isNotBlank(user.getBopenId())) { + // 领导登录 + user = mallUserInfoService.getByBOpenId(user.getBopenId(), tenantEntity); + if (user == null || !isInMobileAdmin(user)) { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + } else { + if (StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) { +// throw new SystemException(ErrorCode.LOGIN_USER_OR_PWD_ERROR); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + } + if (user == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if (user.getStatus()==null ||!EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) { + logger.error(ErrorCode.USER_IS_LOCKED.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(user.getUsername()); + subject.login(token); + isLogin = true; + } catch (UnknownAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } catch (DisabledAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + + if (isLogin) { + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + + mallUserActionService.saveActionInfo(info, EnumMallUserAction.CONTROLLER.getCode(), ipaddress, info.getId(), "用户登录"); + + WxMall mall = mallService.getByTenantInfo(info); + if (mall == null) { + logger.error("未配置相应的mall"); + return new ResultData(Result.ERROR, "未配置相应的mall"); + } + if (!mall.isValid()) { + logger.error("mall未启用"); + return new ResultData(Result.ERROR, "mall未启用"); + } + Map map = new HashMap(); + if (mall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode())) { + List mallList = mallService.getSubByParentTenantId(mall.getTenantId()); + map.put("subMalls", JSON.toJSONString(mallList)); + map.put("group", EnumGroupSupport.SUPPORT.getCode()); + } + try { + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + map.put("username", info.getUsername()); + map.put("withWechat", info.getWithWechat()); + data.data = map; + + } catch(Exception e){ + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + } + return data; + } + + @ApiOperation("发送手机验证码") + @GetMapping("sendLoginPhoneCode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true)}) + public ResultData sendLoginPhoneCode(String phone) { + logger.debug("[" + getIpAddr() + "] HomeController::sendlogincode"); + // 1. 检查手机号是否在用户列表里, 是否只有一个 + // 2. 发送手机验证码, 直接发 + List users = mallUserInfoService.getUserByPhone(phone); + if(users.size() <= 0) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if(users.size() > 1) { + logger.error(ErrorCode.USER_IS_MULTI.getMessage()); + return new ResultData(ErrorCode.USER_IS_MULTI); + } + MallUserInfoVo user = users.get(0); + if (user==null) { + logger.error("用户不存在, userName: " + user.getUsername()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if(user.getStatus() == EnumMallUserStatus.NOT_VALID.getCode()){ + logger.error("用户已停用, userName: " + user.getUsername()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.updateTenantInfo(user); + wxMsgValidationcode.setType(EnumMsgModel.VALIDATION_CODE.getCode()); + return wxMsgValidationcodeService.sendvalidationcode(wxMsgValidationcode); + } + + @ApiOperation(value = "手机验证码登录", notes = "{\"phone\",\"string\",\"code\",\"string\"}") + @PostMapping("/doLoginByPhone") + public ResultData doLoginByPhone(@RequestBody Map params, HttpServletResponse response) { + String ipaddress = getIpAddr(); + logger.debug("[" + ipaddress + "] HomeController::doLoginByPhone"); + // String phone,String code,String pwd + String phone = params.get("phone"); + String code = params.get("code"); + + if (StringUtils.isBlank(phone)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "userName不能为空"); + } + if (StringUtils.isBlank(code)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "验证码不能为空"); + } + + // 获取用户信息列表 + List userList = mallUserInfoService.getUserByPhone(phone); + if(userList.size() == 1) { + MallUserInfoVo user = userList.get(0); + if (user == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if (user.getStatus()==null ||!EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) { + logger.error(ErrorCode.USER_IS_LOCKED.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + // check 验证码正确 + boolean isValidCode = false; + try { + isValidCode = mallUserInfoService.checkCodeValid(user, code); + } catch (Exception e) { + return new ResultData(Result.ERROR, e.getMessage()); + } + if(isValidCode) { + + // 验证码正确,直接登录 + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(user.getUsername()); + subject.login(token); + + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + mallUserActionService.saveActionInfo(info, EnumMallUserAction.CONTROLLER.getCode(), ipaddress, info.getId(), "用户手机号登录"); + + WxMall mall = mallService.getByTenantInfo(info); + if (mall == null) { + logger.error("未配置相应的mall"); + return new ResultData(Result.ERROR, "未配置相应的mall"); + } + if (!mall.isValid()) { + logger.error("mall未启用"); + return new ResultData(Result.ERROR, "mall未启用"); + } + Map map = new HashMap(); + if (mall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode())) { + List mallList = mallService.getSubByParentTenantId(mall.getTenantId()); + map.put("subMalls", JSON.toJSONString(mallList)); + map.put("group", EnumGroupSupport.SUPPORT.getCode()); + } + + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + map.put("username", info.getUsername()); + map.put("withWechat", info.getWithWechat()); + + return new ResultData(map); + } catch (MallinkException e) { + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + } else { + return new ResultData(ErrorCode.MSG_VERIFY_CODE_NOT_FOUND); + } + } else { + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + } + + @ApiOperation("登出") + @GetMapping("/logout") + @SystemControllerLog(description = "用户登出") + public ResultData logout() { + logger.debug("[" + getIpAddr() + "] HomeController::logout"); + ResultData data = new ResultData(); + SecurityUtils.getSubject().logout(); + return data; + } + + @ApiOperation("获取后端版本号") + @GetMapping("/version") + public ResultData version() { + logger.debug("[" + getIpAddr() + "] HomeController::version"); + logger.info(">>>>>>>>>>>>>"+version); + return new ResultData(version); + } +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallRoleController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallRoleController.java new file mode 100644 index 000000000..70125f588 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallRoleController.java @@ -0,0 +1,156 @@ +package com.iformall.controller.sys; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.MallRolePermissionService; +import com.iformall.service.MallRoleService; +import com.iformall.service.MallUserRoleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + + +@RestController +@RequestMapping("role") +@Api(description = "角色相关接口") +public class MallRoleController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private MallRoleService sysRoleService; + + @Autowired + private MallRolePermissionService sysRolePermissionService; + + @Autowired + private MallUserRoleService mallUserRoleService; + + @ApiOperation("角色列表") + @GetMapping("list") + //@RequiresPermissions("sys:role:list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "用户管理-role列表") + public ResultData list(MallRole sysRole, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] MallRoleController::list"); + sysRole.updateTenantInfo(ifParentUpdateTenantInfo()); + sysRole.setSortColumns(BaseEntity.SortField.Id_DESC); + final PageInfo page = sysRoleService.listAsPage(sysRole, pageNum, pageSize); + for (MallRole r : page.getList()) { + MallRolePermission p = new MallRolePermission(); + p.setRoleId(r.getId()); + p.updateTenantInfo(sysRole); + List pers = sysRolePermissionService.getList(p); + String menus = ""; + for (MallRolePermission rp : pers) { + menus += rp.getPermissionId() + ","; + } + if (menus.length() > 1) { + menus = menus.substring(0, menus.length() - 1); + } + r.setMenus(menus); + } + return new ResultData(page); + } + + @ApiOperation("角色详情") + @GetMapping("findById") + //@RequiresPermissions("sys:role:get") + @SystemControllerLog(description = "用户管理-role信息") + public ResultData findById(MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::list"); + if (sysRole.getId() == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + MallRole role = sysRoleService.getById(sysRole.getId()); + MallRolePermission p = new MallRolePermission(); + p.setRoleId(role.getId()); + p.updateTenantInfo(ifParentUpdateTenantInfo()); + List pers = sysRolePermissionService.getList(p); + String menus = ""; + for (MallRolePermission rp : pers) { + menus += rp.getPermissionId() + ","; + } + if (menus.length() > 1) { + menus = menus.substring(0, menus.length() - 1); + } + role.setMenus(menus); + return new ResultData(role); + } + + + @ApiOperation("角色保存") + @PostMapping("saveOrUpdate") + //@RequiresPermissions("sys:role:save") + @SystemControllerLog(description = "用户管理-rule保存") + public ResultData saveOrUpdate(@RequestBody MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::saveOrUpdate"); + MallUserInfo currentUser = getUser(); + if (currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有系统管理员才能保存角色"); + } + int count = checkUnique(sysRole.getName(), currentUser); + if (sysRole.getId() == null && count > 0) { + return new ResultData(ResultData.ERROR, "角色名已存在"); + } + sysRole.updateTenantInfo(currentUser); + sysRoleService.saveOrUpdate(sysRole); + if (StringUtils.isNoneBlank(sysRole.getMenus())) { + String[] menuIds = sysRole.getMenus().split(","); + List mIds = new ArrayList<>(); + for (String mId : menuIds) { + mIds.add(Long.valueOf(mId)); + } + sysRolePermissionService.savePermissions(currentUser, sysRole.getId(), mIds.toArray(new Long[]{})); + } + return new ResultData(); + } + + @ApiOperation("角色删除") + @PostMapping("/del") + //@RequiresPermissions("sys:role:del") + @SystemControllerLog(description = "用户管理-rule删除") + public ResultData delete(@RequestBody MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::delete"); + MallUserInfo currentUser = getUser(); + if (currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有系统管理员才能删除角色"); + } + MallUserRole record = new MallUserRole(); + record.setRoleId(sysRole.getId()); + int count = mallUserRoleService.cntUserList(record); + if (count > 0) { + return new ResultData(ErrorCode.USER_USE_ROLE.getCode(), "有用户使用此角色,请先删除相应的用户!!"); + } + sysRoleService.deleteById(sysRole.getId()); + sysRolePermissionService.deleteByRoleId(sysRole.getId()); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + private int checkUnique(String name, TenantEntity tenantEntity) { + MallRole role = new MallRole(); + role.setName(name); + role.updateTenantInfo(tenantEntity); + return sysRoleService.countList(role); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallUserActionController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallUserActionController.java new file mode 100644 index 000000000..ce9921d22 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallUserActionController.java @@ -0,0 +1,43 @@ +package com.iformall.controller.sys; + +import com.github.pagehelper.PageInfo; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.vo.MallUserActionVo; +import com.iformall.service.MallUserActionService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("mallUserAction") +public class MallUserActionController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + @Autowired + private MallUserActionService mallUserActionService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + public ResultData list(@ModelAttribute MallUserActionVo userAction, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] MallUserActionController::list"); + if (null == userAction) { + userAction = new MallUserActionVo(); + } else { + if(StringUtils.isBlank(userAction.getName())) { + userAction.setName(null); + } + } + final PageInfo page = mallUserActionService.listAsPage(userAction, pageNum, pageSize); + return new ResultData(page); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallUserInfoController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallUserInfoController.java new file mode 100644 index 000000000..39158e41d --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/MallUserInfoController.java @@ -0,0 +1,383 @@ +package com.iformall.controller.sys; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.*; +import com.iformall.shiro.PasswordHelper; +import com.iformall.shiro.UserSession; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author chenkx + * @date 2018-01-05. + */ +@Api(value = "API - UserInfoController", description = "用户接口") +@RestController +@RequestMapping("user") +public class MallUserInfoController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + MallUserInfoService userInfoService; + + @Autowired + MallUserRoleService userRoleService; + + @Autowired + MallRoleService mallRoleService; + + @Autowired + MallUserRoleService mallUserRoleService; + + @Autowired + MallPermissionService mallPermissionService; + + @Autowired + MallRolePermissionService mallRolePermissionService; + + @Autowired + WxMsgValidationcodeService wxMsgValidationcodeService; + + @ApiOperation(value = "用户分页接口", response = String.class) + @GetMapping("lists") + //@RequiresPermissions("sys:user:list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "用户管理-列表") + public ResultData listAsPage(MallUserInfo userInfo, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::listAsPage"); + + userInfo.updateTenantInfo(ifParentUpdateTenantInfo()); + userInfo.setSortColumns(BaseEntity.SortField.CreateTime_DESC,BaseEntity.SortField.Id_DESC); + final PageInfo page = userInfoService.listAsPage(userInfo, pageNum, pageSize); + for (MallUserInfo u : page.getList()) { + MallUserRole r = new MallUserRole(); + r.setUid(u.getId()); + PageInfo ur = userRoleService.listAsPage(r, 1, 1); + if (ur.getSize() > 0) { + MallRole role = mallRoleService.getById(ur.getList().get(0).getRoleId()); + if (role != null) { + u.setRoleName(role.getName()); + u.setRoleId(role.getId()); + } + } + // 保密 + u.setPassword(null); + u.setBopenId(null); + if(StringUtils.isNotBlank(u.getWebOpenId())) { + u.setWebOpenId("保密"); + } + } + return new ResultData(page); + } + + @ApiOperation(value = "用户详情接口", response = String.class) + @GetMapping("detail") + //@RequiresPermissions("sys:user:info") + @SystemControllerLog(description = "用户管理-用户详情") + public ResultData detail(Long id) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::detail"); + final MallUserInfo user = userInfoService.getById(id); + user.setPassword(null); + user.setBopenId(null); + if(StringUtils.isNotBlank(user.getWebOpenId())) { + user.setWebOpenId("保密"); + } + + return new ResultData(user); + } + + @ApiOperation(value = "创建用户接口", response = String.class) + @PostMapping("add") + //@RequiresPermissions("sys:user:add") + @SystemControllerLog(description = "用户管理-创建用户") + public ResultData createUser(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::createUser"); + MallUserInfo currentUser = getUser(); + if(currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有系统管理员才能添加用户"); + } + + if(checkUniqueName(userInfo.getUsername()) > 0){ + return new ResultData(ErrorCode.USER_NAME_IS_FOUND.getCode(),"用户名已存在"); + } + if(checkUniquePhone(userInfo.getPhone()) > 0){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND.getCode(),"手机号已存在"); + } + Assert.notNull(userInfo.getPassword(), "密码不能为空"); + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(userInfo); + userInfo.updateTenantInfo(currentUser); + // 无法创建超管 + userInfo.setIsAdmin(EnumUserAdmin.Normal.getCode()); + userInfoService.saveOrUpdate(userInfo); + if (userInfo.getRoleId() != null) { + MallUserRole r = new MallUserRole(); + r.setRoleId(userInfo.getRoleId()); + r.setUid(userInfo.getId()); + userRoleService.saveOrUpdate(r); + } + return new ResultData(userInfo); + } + + @ApiOperation(value = "修改用户接口", response = String.class) + @PostMapping("update") + //@RequiresPermissions("sys:user:update") + @SystemControllerLog(description = "用户管理-修改用户") + public ResultData updateUser(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::updateUser"); + boolean bChangedPhone = false; + MallUserInfo currentUser = getUser(); + // 只有超管和自己能更新信息 + if (!(currentUser.getId().equals(userInfo.getId()) || + currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode()))) { + return new ResultData(ErrorCode.USER_NO_PERMISSION.getCode(), "系统管理员和自己才能修改信息"); + } + MallUserInfo oldUser = userInfoService.getById(userInfo.getId()); + if (!oldUser.getUsername().equals(userInfo.getUsername())) { + if(checkUniqueName(userInfo.getUsername()) > 0){ + return new ResultData(ErrorCode.USER_NAME_IS_FOUND.getCode(),"用户名已存在"); + } + } + if (!oldUser.getPhone().equals(userInfo.getPhone())) { + if(checkUniquePhone(userInfo.getPhone()) > 0){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND.getCode(),"手机号已存在"); + } + bChangedPhone = true; + } + + userInfo.updateTenantInfo(currentUser); + if (StringUtils.isNotBlank(userInfo.getPassword()) && userInfo.getPassword().length() > 0) { + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(userInfo); + } + // 系统内人员不能设置系统管理员 + userInfo.setIsAdmin(null); + /* + if (!currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + // 只有系统管理员才能设置系统管理员 + userInfo.setIsAdmin(null); + } + */ + + if (currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode()) && + currentUser.getId().equals(userInfo.getId())) { + // 超管 + MallUserInfo adminUser = new MallUserInfo(); + adminUser.setEmail(userInfo.getEmail()); + adminUser.setId(userInfo.getId()); + if (StringUtils.isNotBlank(userInfo.getPassword()) && userInfo.getPassword().length() > 0) { + adminUser.setPassword(userInfo.getPassword()); + } + if (StringUtils.isNotBlank(userInfo.getNickName())) { + adminUser.setNickName(userInfo.getNickName()); + } + if (StringUtils.isNotBlank(userInfo.getPhone())) { + adminUser.setPhone(userInfo.getPhone()); + } + adminUser.setInvestRule(userInfo.getInvestRule()); + userInfoService.saveOrUpdate(adminUser); + } else { + userInfoService.saveOrUpdate(userInfo); + if (userInfo.getRoleId() != null) { + userRoleService.deleteByUserId(userInfo.getId()); + MallUserRole r = new MallUserRole(); + r.setRoleId(userInfo.getRoleId()); + r.setUid(userInfo.getId()); + userRoleService.saveOrUpdate(r); + } + } + if(bChangedPhone) { + // 手机号修改,清除bopen_id, 清除web_open_id + userInfoService.cleanAllOpenId(userInfo); + } + + return new ResultData(); + } + + @ApiOperation(value = "删除用户接口", response = String.class) + @PostMapping("/del") + //@RequiresPermissions("sys:user:del") + @SystemControllerLog(description = "用户管理-删除用户") + public ResultData deleteUser(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::deleteUser"); + MallUserInfo currentUser = getUser(); + if (currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有系统管理员才能删除用户"); + } + if (currentUser.getId().equals(userInfo.getId())) { + return new ResultData(ErrorCode.USER_NO_PERMISSION.getCode(), "用户不能删除自己"); + } + userInfoService.deleteById(userInfo.getId()); + userRoleService.deleteByUserId(userInfo.getId()); + return new ResultData(); + } + + @ApiOperation(value = "起停用户接口") + @PostMapping("updateStatus") + //@RequiresPermissions("sys:user:update") + @SystemControllerLog(description = "用户管理-起停用户") + public ResultData modifyStatus(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::modifyStatus"); + MallUserInfo currentUser = getUser(); + if (currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + MallUserInfo userInfo1 = userInfoService.getById(userInfo.getId()); + if(userInfo1 == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + MallUserInfo updateUserInfo = new MallUserInfo(); + updateUserInfo.setId(userInfo.getId()); + updateUserInfo.updateTenantInfo(currentUser); + updateUserInfo.setStatus(userInfo.getStatus()); + userInfoService.saveOrUpdate(userInfo); + return new ResultData(); + } else { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + } + + private int checkUniqueName(String userName) { + return userInfoService.cntByUserName(userName); + } + + private int checkUniquePhone(String phone) { + return userInfoService.cntByUserPhone(phone); + } + + + @ApiOperation(value = "用户权限检查") + @GetMapping("hasButtonPermission") + @SystemControllerLog(description = "用户管理-用户权限检查") + public ResultData hasButtonPermission(String permissions) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::hasButtonPermission"); + MallUserInfo info = getUser(); + info.setPassword("保密"); + Map map = new HashMap<>(); + for (String name : permissions.split(",")) { + Long userId = (Long)SecurityUtils.getSubject().getSession().getAttribute(UserSession.userId); + boolean has = userInfoService.hasButtonPermission(userId, name); + map.put(name, has); + } + return new ResultData(map); + } + + @ApiOperation(value = "用户权限检查") + @GetMapping("getUser") + //@RequiresPermissions("sys:user:info") + @SystemControllerLog(description = "用户管理-获取用户信息") + public ResultData getUserInfo() { + ///logger.debug("[" + getIpAddr() + "] MallUserInfoController::getUserInfo"); + MallUserInfo info = getUser(); + info.protectInfos(); + return new ResultData(info); + } + + @ApiOperation(value = "获取菜单") + @GetMapping("/getMenu") + @SystemControllerLog(description = "用户管理-获取菜单") + public ResultData getMenu() { + MallUserInfo info = getUser(); + String menu = userRoleService.getPermissionsByUser(info); + return new ResultData(menu); + } + + @ApiOperation(value = "用户密码发送验证码") + @GetMapping("sendvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userName", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景(1:登录)", dataType = "Integer", paramType = "query", required = true)}) + public ResultData sendvalidationcode(String userName, Integer type) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::sendvalidationcode"); + MallUserInfo userQ = new MallUserInfo(); + userQ.setUsername(userName); + + MallUserInfo user = userInfoService.getByUsername(userName); + if (user==null) { + logger.error("用户不存在, userName: " + userName); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + + if(user.getStatus() == EnumMallUserStatus.NOT_VALID.getCode()){ + logger.error("用户已停用, userName: " + userName); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + + if (StringUtils.isBlank(user.getPhone())) { + logger.error("用户手机号为空, userName: " + userName); + return new ResultData(ErrorCode.USER_PHONE_IS_NOT_FOUND); + } + + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.updateTenantInfo(user); + wxMsgValidationcode.setPhone(user.getPhone()); + wxMsgValidationcode.setType(type); + return wxMsgValidationcodeService.sendvalidationcode(wxMsgValidationcode); + } + + @ApiOperation(value = "修改密码", notes = "{\"userName\",\"string\",\"code\",\"string\",\"pwd\",\"string\"}") + @PostMapping("/updatepwd") + @SystemControllerLog(description = "用户管理-修改密码") + public ResultData updatepwd(@RequestBody Map params) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::updatepwd"); + // String phone,String code,String pwd + String userName = params.get("userName"); + String code = params.get("code"); + String pwd = params.get("pwd"); + + if (StringUtils.isBlank(userName)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "userName不能为空"); + } + if (StringUtils.isBlank(code)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "验证码不能为空"); + } + if (StringUtils.isBlank(pwd)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "密码不能为空"); + } + + MallUserInfo userQ = new MallUserInfo(); + userQ.setUsername(userName); + MallUserInfo user = userInfoService.getByUsername(userName); + if (user==null) { + logger.error("用户不存在, userName: " + userName); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + + user.setPassword(pwd); + + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(user); + + + try { + return userInfoService.updatepwd(user, code); + } catch (Exception e) { + return new ResultData(Result.ERROR, e.getMessage()); + } + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/SysMenuController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/SysMenuController.java new file mode 100644 index 000000000..ce8bd4740 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/SysMenuController.java @@ -0,0 +1,119 @@ +package com.iformall.controller.sys; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallPermission; +import com.iformall.domain.po.MallRole; +import com.iformall.domain.po.MallRolePermission; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.enums.EnumMenuType; +import com.iformall.enums.EnumPermissionType; +import com.iformall.exception.MallinkException; +import com.iformall.service.MallPermissionService; +import com.iformall.service.MallRolePermissionService; +import com.iformall.service.MallRoleService; +import com.iformall.service.MallUserInfoService; +import com.iformall.utils.Constant; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.apache.shiro.util.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.util.*; + +/** + * @author Stormeye Wu + * @date 2019-04-20. + */ +@RestController +@RequestMapping("menu") +public class SysMenuController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private MallPermissionService mallPermissionService; + + @Autowired + private MallUserInfoService mallUserInfoService; + + @ApiOperation("导航菜单") + @GetMapping("/nav") + @SystemControllerLog(description = "菜单-导航菜单") + public ResultData nav(){ + logger.debug("[" + getIpAddr() + "] MallPermissionController::nav"); + MallUserInfo user = getUser(); + List menuList = mallPermissionService.getUserMenuList(user, 0L, true); + Set permissions = mallUserInfoService.getUserPermissions(user, true); + Map map = new HashMap<>(); + map.put("menuList", menuList); + map.put("permissions", permissions); + return new ResultData(map); + } + + @ApiOperation("所有菜单列表") + @GetMapping("list") + //@RequiresPermissions("sys:menu:list") + @SystemControllerLog(description = "菜单-所有菜单列表") + public ResultData getList() { + logger.debug("[" + getIpAddr() + "] MallPermissionController::list"); + MallUserInfo user = getUser(); + if (user.checkGroupAdmin()) { + TenantEntity tenantEntity = ifParentUpdateTenantInfo(); + user.setTenantId(tenantEntity.getTenantId()); + if (StringUtils.isNotBlank(tenantEntity.getParentTenantId())) { + user.setParentTenantId(tenantEntity.getParentTenantId()); + } + } + List menuList = mallPermissionService.getUserMenuList(user, 0L, false); + Set permissions = mallUserInfoService.getUserPermissions(user, false); + Map map = new HashMap<>(); + map.put("menuList", menuList); + map.put("permissions", permissions); + return new ResultData(map); + } + + @ApiOperation("菜单信息") + @GetMapping("/findById") + //@RequiresPermissions("sys:menu:info") + @SystemControllerLog(description = "菜单-权限查找") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::findById"); + return new ResultData(Result.SUCCESS, "成功", mallPermissionService.getById(id)); + } + + @ApiOperation("获取父子菜单ID信息") + @GetMapping("/getMenuIdsById") + //@RequiresPermissions("sys:menu:info") + @SystemControllerLog(description = "菜单-父子菜单查找") + public ResultData getMenuIdsById(Long parentId) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::getMenusById"); + MallUserInfo user = getUser(); + return new ResultData(Result.SUCCESS, "成功", mallPermissionService.queryUserMenuIds(user, parentId, false)); + } + + @ApiOperation("获取父子菜单信息") + @GetMapping("/getMenusById") + //@RequiresPermissions("sys:menu:info") + @SystemControllerLog(description = "菜单-父子菜单查找") + public ResultData getMenusById(Long parentId) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::getMenusById"); + MallUserInfo user = getUser(); + return new ResultData(Result.SUCCESS, "成功", mallPermissionService.getUserMenuList(user, parentId, false)); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/SysNoticeController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/SysNoticeController.java new file mode 100644 index 000000000..e3274b55a --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/SysNoticeController.java @@ -0,0 +1,37 @@ +package com.iformall.controller.sys; + +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.SysNotice; +import com.iformall.service.SysNoticeService; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("sysnotice") +public class SysNoticeController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private SysNoticeService sysNoticeService; + + @ApiOperation("分页列表接口") + @GetMapping("sysNotice") + public ResultData sysNotice() { + SysNotice notice = new SysNotice(); + notice.setStatus(1); + notice.setType(1); + List noticelist = sysNoticeService.selectList(notice); + if (null != noticelist && noticelist.size() > 0 ) { + return new ResultData(noticelist.get(0)); + } + return new ResultData(); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/UploadController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/UploadController.java new file mode 100644 index 000000000..496c8af0d --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/UploadController.java @@ -0,0 +1,206 @@ +package com.iformall.controller.sys; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.file.aliyun.AliyunOSS; +import com.iformall.utils.ImgUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.util.*; + +@RestController +@RequestMapping(value = "upload") +@Api(description = "文件上传接口") +public class UploadController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private AliyunOSS aliyunOSS; + + /** + * 上传文件 + * + * @param multiReq + * @return + * @throws Exception + */ + @PostMapping(value = "/awsFileUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("上传文件") + @SystemControllerLog(description = "文件上传") + public ResultData awsfileUpload(@RequestParam("file") MultipartFile multiReq) { + logger.info("[" + getIpAddr() + "] UploadController::awsfileUpload"); + + TenantEntity tenantEntity = getTenantInfo(); + + try { + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + String fileFormat = ""; + if (dot >= 0) { + fileFormat = multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } + ResultData data = aliyunOSS.uploadFile(tenantEntity.getTenantId(), fileFormat, multiReq.getInputStream()); + return data; + + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); + } + } + + + /** + * 图片上传 + * + * @param multiReq + * @return + * @throws Exception + */ + @PostMapping(value = "/awsImgUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("上传图片") + @SystemControllerLog(description = "上传图片") + public ResultData awsImgUpload(@RequestParam("file") MultipartFile multiReq + ,@RequestParam Map param) { + logger.info("[" + getIpAddr() + "] UploadController::awsImgUpload"); + TenantEntity tenantEntity = getTenantInfo(); + + long size = multiReq.getSize(); + final long length = 2097152; + if (size > length) { + return new ResultData(ErrorCode.PICTURE_SIZE_EXCEED); + } + + String fileFormat = ""; + try { + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + if (dot >= 0) { + fileFormat = multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } + + String imgFormat = ImgUtil.getImgFormat(fileFormat); + if(StringUtils.isNotBlank(imgFormat)) { + long maxSize = 0l; + try { + maxSize = Long.parseLong(param.get("size")); + } catch (NumberFormatException e) {} + if(maxSize > 0l && size > maxSize*1024){ + return new ResultData(ErrorCode.PICTURE_SIZE_CUSTOMIZE); + } + BufferedImage bufferedImage = ImageIO.read(multiReq.getInputStream()); + if(bufferedImage != null){ + int width = 0;int hight = 0; + try { + width = Integer.parseInt(param.get("width")); + hight = Integer.parseInt(param.get("hight")); + } catch (NumberFormatException e) {} + Integer relWidth = bufferedImage.getWidth(); + Integer relHeight = bufferedImage.getHeight(); + if((width > 0 && width != relWidth.intValue()) + || (hight > 0 && hight != relHeight.intValue())){ + return new ResultData(ErrorCode.PICTURE_W_H_CUSTOMIZE); + } + } + } + ResultData data = aliyunOSS.uploadFile(tenantEntity.getTenantId(), fileFormat, multiReq.getInputStream()); + return data; + + } catch (Exception e) { + logger.error("解析图片",e); + return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); + } + } + + /** + * 多文件上传 + * + * @param files + * @return + * @throws Exception + */ + @PostMapping(value = "/awsFilesUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("多文件上传") + @SystemControllerLog(description = "多文件上传") + public ResultData awsFilesUpload(@RequestParam("files") MultipartFile[] files) { + logger.info("[" + getIpAddr() + "] UploadController::awsFilesUpload"); + TenantEntity tenantEntity = getTenantInfo(); + try { + if(files.length > 0){ + ResultData data = new ResultData(); + List> dataList = new ArrayList>(); + for(MultipartFile multipartFile: files) { + Map map = new HashMap<>(); + + map.put("key", multipartFile.getOriginalFilename()); + + int dot = multipartFile.getOriginalFilename().lastIndexOf('.'); + String fileFormat = ""; + if (dot >= 0) { + fileFormat = multipartFile.getOriginalFilename().substring(dot, multipartFile.getOriginalFilename().length());; + } + + ResultData data1 = aliyunOSS.uploadFile(tenantEntity.getTenantId(), fileFormat, multipartFile.getInputStream()); + + if(data1.code == ResultData.SUCCESS) { + Map _data = (Map)data1.data; + map.put("url", (String) _data.get("url")); + dataList.add(map); + } else { + // 部分成功 + data.code = ResultData.SUCCESS; + data.data = dataList; + return data; + } + } + data.code = ResultData.SUCCESS; + data.data = dataList; + return data; + + }else{ + return new ResultData(); + } + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); + } + } + + /** + * 内部接口-A端上传图片文件 + * + * @param multiReq + * @return + * @throws Exception + */ + @PostMapping(value = "/cimgUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("内部接口-A端上传图片文件") + public ResultData cimgUpload(@RequestParam("file") MultipartFile multiReq) { + logger.info("[" + getIpAddr() + "] UploadController::cimgUpload"); + + try { + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + String fileFormat = ""; + if (dot >= 0) { + fileFormat = multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } + + ResultData data = aliyunOSS.uploadFile("aimg", fileFormat, multiReq.getInputStream()); + return data; + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); + } + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WechatLoginController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WechatLoginController.java new file mode 100644 index 000000000..83a9fb528 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WechatLoginController.java @@ -0,0 +1,479 @@ +package com.iformall.controller.sys; + +import com.alibaba.fastjson.JSON; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallUserAction; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.WxMall; +import com.iformall.domain.vo.MallUserInfoVo; +import com.iformall.enums.EnumGroupSupport; +import com.iformall.enums.EnumMallUserAction; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.MallUserActionService; +import com.iformall.service.MallUserInfoService; +import com.iformall.service.MallUserRoleService; +import com.iformall.service.WxMallService; +import com.iformall.shiro.UserSession; +import com.iformall.shiro.UseriFormallToken; +import com.iformall.utils.TOTP; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.subject.Subject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.util.SafeEncoder; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.*; + + +@Controller +@RequestMapping("/wechat") +@Slf4j +public class WechatLoginController extends BaseController { + private String WECHAT_PREV = "LOGIN:OPEN:"; + + @Autowired + private WxMpService wxMpService; + + @Autowired + private MallUserInfoService mallUserInfoService; + + @Autowired + private MallUserRoleService mallUserRoleService; + + @Autowired + private MallUserActionService mallUserActionService; + + @Autowired + private WxMallService mallService; + + @Autowired + @Qualifier("openRedisTemplate") + RedisTemplate openRedisTemplate; + + @Data + private class DisplayUserInfo { + String mallName; + String userName; + String userRole; + } + + @ApiOperation(value = "微信登录") + @GetMapping("login") + public void login(HttpServletRequest request, HttpServletResponse response) { + log.debug("[" + getIpAddr() + "] MallUserInfoController::login"); + String host = request.getHeader("host"); + log.debug("Host: " + host); + String wechatUrl = wxMpService.buildQrConnectUrl("https://"+host+"/api/wechat/callback", "snsapi_login", "111"); + try { + response.sendRedirect(wechatUrl); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + @ApiOperation(value = "微信网页登录回调", notes = "请配置此callback到网页redirect_uri") + @GetMapping("callback") + public void getAccessToken(String code, String state, HttpServletRequest request, HttpServletResponse response) { + String ipaddress = getIpAddr(); + log.debug("[" + ipaddress + "] WechatLoginController::getAccessToken"); + String host = request.getHeader("host"); + log.debug("host: " + host); + log.debug("code: " + code); + try { + WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); + log.info("accessToken: " + accessToken.getAccessToken() + ", openId: " + accessToken.getOpenId() + ", unionId: " + accessToken.getUnionId()); + + accessToken = wxMpService.oauth2refreshAccessToken(accessToken.getRefreshToken()); + log.info("accessToken: " + accessToken.getAccessToken() + ", openId: " + accessToken.getOpenId() + ", unionId: " + accessToken.getUnionId()); + + // 获取 用户信息 + WxMpUser mpUser = wxMpService.oauth2getUserInfo(accessToken, null); + if(mpUser != null) { + log.info(mpUser.toString()); + } + + // check user openid 是否是已授权用户 + List userList = mallUserInfoService.getUsersByWebOpenId(accessToken.getOpenId()); + log.info("login user list count " + userList.size()); + if(userList.size() > 0) { + if(userList.size() == 1) { + Map ret = new HashMap<>(); + // 唯一用户 + MallUserInfo user = userList.get(0); + if (user == null) { + ret.put("code", ErrorCode.USER_IS_EMPTY.getCode()); + ret.put("message", ErrorCode.USER_IS_EMPTY.getMessage()); + } + if (user.getStatus()==null ||!EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) { + ret.put("code", ErrorCode.USER_IS_LOCKED.getCode()); + ret.put("message", ErrorCode.USER_IS_LOCKED.getMessage()); + } + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(user.getUsername()); + subject.login(token); + isLogin = true; + } catch (UnknownAccountException e) { + log.error(e.getMessage()); + ret.put("code", ErrorCode.USER_IS_EMPTY.getCode()); + ret.put("message", e.getMessage()); + } catch (DisabledAccountException e) { + log.error(e.getMessage()); + ret.put("code", ErrorCode.USER_IS_LOCKED.getCode()); + ret.put("message", e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage()); + ret.put("code", Result.ERROR); + ret.put("message", e.getMessage()); + } + if(isLogin) { + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + String menus = mallUserRoleService.getPermissionsByUser(info); + if(menus != null) { + info.setMenus(menus); + } + WxMall mall = mallService.getByTenantInfo(info); + if (mall == null) { + ret.put("code", Result.ERROR); + ret.put("message", "未配置相应的mall"); + log.info("用户登录失败-4,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode=" + errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + if (!mall.isValid()) { + ret.put("code", Result.ERROR); + ret.put("message", "mall未启用"); + log.info("用户登录失败-5,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode=" + errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + Map map = new HashMap(); + if (mall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode())) { + List mallList = mallService.getSubByParentTenantId(mall.getTenantId()); + map.put("subMalls", JSON.toJSONString(mallList)); + map.put("group", EnumGroupSupport.SUPPORT.getCode()); + } + try { + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + MallUserAction action = new MallUserAction(); + action.updateTenantInfo(info); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setUserId(info.getId()); + action.setActionDesc("用户微信登录"); + action.setActionTime(new Date()); + mallUserActionService.saveOrUpdate(action); + } catch (Exception e) { + log.error(e.getMessage()); + ret.put("code", Result.ERROR); + ret.put("message", e.getMessage()); + } + Object codeObj = ret.get("code"); + if(codeObj == null) { + log.info("用户登录成功,切换主页"); + try { + response.sendRedirect("https://"+host+"/#/layout"); + } catch (Exception e) { + log.error(e.getMessage()); + } + } else { + log.info("用户登录失败-3,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode=" + errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } else { + log.info("用户登录失败-2,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode="+errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } else { + // 跳转登录选择页面 + String openId = accessToken.getOpenId(); + String key = TOTP.generateWechatOpen(openId); + String openKey = WECHAT_PREV + key; + Boolean isAbsent = openRedisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + RedisSerializer valueSerializer = openRedisTemplate.getValueSerializer(); + RedisSerializer keySerializer = openRedisTemplate.getKeySerializer(); + Object obj = connection.execute("set", keySerializer.serialize(openKey), + valueSerializer.serialize(openId), + SafeEncoder.encode("NX"), + SafeEncoder.encode("EX"), + Protocol.toByteArray(60)); // 60s 过期时间 + return obj != null; + } + }); + List users = new ArrayList(); + for(MallUserInfoVo user: userList) { + DisplayUserInfo disUser = new DisplayUserInfo(); + disUser.setMallName(user.getMallName()); + disUser.setUserName(user.getUsername()); + disUser.setUserRole(user.getRoleName()); + users.add(disUser); + } + String usersStr = JSON.toJSONString(users); + log.info(usersStr); + try { + usersStr = URLEncoder.encode(usersStr, "utf-8"); + response.sendRedirect("https://" + host + "/#/loginselect?key=" + key + "&list=" + usersStr); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } else { + log.info("用户登录失败-1,返回登录"); + // 跳转登录页面 + Map ret = new HashMap<>(); + ret.put("code", ErrorCode.WECHAT_LOGIN_NOT_BIND.getCode()); + ret.put("message", ErrorCode.WECHAT_LOGIN_NOT_BIND.getMessage()); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode="+errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } catch (WxErrorException e) { + log.error(e.getMessage()); + } + } + + @ApiOperation(value = "微信用户登录") + @GetMapping("weChatUserLogin") + @ApiImplicitParams({ + @ApiImplicitParam(name = "key", value = "key", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "userName", value = "userName", dataType = "String", paramType = "query", required = true)}) + public ResultData weChatUserLogin(String key, String userName, HttpServletRequest request, HttpServletResponse response) { + String ipaddress = getIpAddr(); + log.debug("[" + ipaddress + "] MallUserInfoController::weChatUserLogin"); + String host = request.getHeader("host"); + log.debug("Host: " + host); + if(StringUtils.isBlank(userName)) { + log.error("请选择要登录的用户"); + return new ResultData(ErrorCode.WECHAT_LOGIN_USER_SELECT); + } + + String openKey = WECHAT_PREV + key; + // 限时时间内查找到此用户openId + if (openRedisTemplate.hasKey(openKey)){ + log.info(openKey + " - 找不到"); + String openId = openRedisTemplate.opsForValue().get(openKey); + openRedisTemplate.delete(openKey); + log.info("KEY: " + openKey + " deleted"); + + MallUserInfo userInfo = mallUserInfoService.getByUsername(userName); + if (userInfo == null) { + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if (userInfo.getStatus()==null ||!EnumMallUserStatus.VALID.getCode().equals(userInfo.getStatus())) { + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + if(userInfo.getWebOpenId().equals(openId)) { + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(userInfo.getUsername()); + subject.login(token); + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + String menus = mallUserRoleService.getPermissionsByUser(info); + if(menus != null) { + info.setMenus(menus); + } + Map ret = new HashMap<>(); + WxMall mall = mallService.getByTenantInfo(info); + if (mall == null) { + ret.put("code", Result.ERROR); + ret.put("message", "未配置相应的mall"); + log.info("用户登录失败-4,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode=" + errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + if (!mall.isValid()) { + ret.put("code", Result.ERROR); + ret.put("message", "mall未启用"); + log.info("用户登录失败-5,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode=" + errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + Map map = new HashMap(); + if (mall.getGroupSupport().equals(EnumGroupSupport.SUPPORT.getCode())) { + List mallList = mallService.getSubByParentTenantId(mall.getTenantId()); + map.put("subMalls", JSON.toJSONString(mallList)); + map.put("group", EnumGroupSupport.SUPPORT.getCode()); + } + // 登录cookie + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + MallUserAction action = new MallUserAction(); + action.updateTenantInfo(info); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setUserId(info.getId()); + action.setActionDesc("用户微信登录"); + action.setActionTime(new Date()); + mallUserActionService.saveOrUpdate(action); + + return new ResultData(); + } catch (UnknownAccountException e) { + log.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY.getCode(), e.getMessage()); + } catch (DisabledAccountException e) { + log.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED.getCode(), e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage()); + return new ResultData(Result.ERROR, e.getMessage()); + } + } else { + // 登录失败 + log.error("微信登录失败,用户微信未绑定:" + openId); + return new ResultData(ErrorCode.WECHAT_LOGIN_NOT_BIND); + } + } + log.error("微信登录失败,KEY已过期: "+ key); + return new ResultData(ErrorCode.WECHAT_LOGIN_KEY_OVERTIME); + } + + @ApiOperation(value = "微信第三方登录绑定", notes = "请配置此callback到网页redirect_uri") + @GetMapping("bindWebOpenId") + @SystemControllerLog(description = "微信第三方登录绑定") + public void userBindWebOpenId(String code, String state, HttpServletRequest request, HttpServletResponse response) { + log.debug("[" + getIpAddr() + "] WechatLoginController::bindWebOpenId"); + String host = request.getHeader("host"); + String errCode = null; + try { + WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); + log.debug("accessToken: " + accessToken.getAccessToken() + ", openId: " + accessToken.getOpenId() + ", unionId: " + accessToken.getUnionId()); + + // 获取 用户信息 + WxMpUser mpUser = wxMpService.oauth2getUserInfo(accessToken, null); + if(mpUser != null) { + log.debug(mpUser.toString()); + } + + String uname = state; + MallUserInfo user = mallUserInfoService.getByUsername(uname); + if(user != null) { + user.setWebOpenId(accessToken.getOpenId()); + mallUserInfoService.updateWebOpenId(user); + log.debug("https://" + host + "/#/layout"); + response.sendRedirect("https://" + host + "/#/layout"); + } else { + log.debug("https://" + host + "/#/layout?errcode=绑定失败"); + errCode = URLEncoder.encode("绑定失败", "utf-8"); + response.sendRedirect("https://" + host + "/#/layout?errcode="+errCode); + } + } catch (WxErrorException e) { + log.error(e.getMessage()); + errCode = e.getMessage(); + } catch (IOException e) { + log.error(e.getMessage()); + errCode = e.getMessage(); + } + + if(StringUtils.isNotBlank(errCode)) { + try { + errCode = URLEncoder.encode(errCode, "utf-8"); + response.sendRedirect("https://" + host + "/#/layout?errcode="+errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } + + @ApiOperation(value = "微信第三方登录解绑", notes = "请配置此callback到网页redirect_uri") + @GetMapping("cleanWebOpenId") + @SystemControllerLog(description = "微信第三方登录解绑") + public ResultData cleanWebOpenId(@ModelAttribute MallUserInfo userInfo) { + log.debug("[" + getIpAddr() + "] WechatLoginController::cleanWebOpenId"); + MallUserInfo user = getUser(); + if(userInfo == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(StringUtils.isBlank(userInfo.getTenantId())) { + userInfo.setTenantId(user.getTenantId()); + } + if(StringUtils.isBlank(userInfo.getParentTenantId())) { + userInfo.setParentTenantId(user.getParentTenantId()); + } + if(userInfo.getId() == null && userInfo.getUsername() == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + // 只有本人及系统管理员可以解绑微信 + if(userInfo.getId().equals(user.getId()) + || user.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + mallUserInfoService.cleanWebOpenId(userInfo); + return new ResultData(); + } else { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxAdminLogController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxAdminLogController.java new file mode 100644 index 000000000..f4613cd31 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxAdminLogController.java @@ -0,0 +1,30 @@ +package com.iformall.controller.sys; + +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxAdminLog; +import com.iformall.service.WxAdminLogService; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxAdminLog") +public class WxAdminLogController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxAdminLogService wxAdminLogService; + + @ApiOperation("PV计数") + @PostMapping("pvlog") + public ResultData pvLog(@RequestBody WxAdminLog wxAdminLog) { + logger.debug("[" + getIpAddr() + "] WxAdminLogController::pvLog"); + wxAdminLog.updateTenantInfo(ifParentUpdateTenantInfo()); + wxAdminLogService.saveLogCount(wxAdminLog); + return new ResultData(); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxBusinessController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxBusinessController.java new file mode 100644 index 000000000..68d24c571 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxBusinessController.java @@ -0,0 +1,170 @@ +package com.iformall.controller.sys; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.po.WxBusiness; +import com.iformall.domain.po.WxSubBusiness; +import com.iformall.domain.vo.WxBusinessDataVo; +import com.iformall.service.ExcelService; +import com.iformall.service.WxBusinessService; +import com.iformall.service.WxSubBusinessService; +import com.iformall.utils.DateUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.*; + +@RestController +@RequestMapping("wxBusiness") +@Api(description = "业态接口") +public class WxBusinessController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxBusinessService wxBusinessService; + @Autowired + private WxSubBusinessService wxSubBusinessService; + @Autowired + private ExcelService excelService; + + + @ApiOperation("业态全列表接口") + @GetMapping("listAll") + @SystemControllerLog(description = "业态-全列表") + public ResultData listAll() { + logger.debug("[" + getIpAddr() + "] WxBusinessController::getList"); + final List busList = wxBusinessService.findListAll(getTenantInfo(),null); + return new ResultData(busList); + } + + @ApiOperation("子业态表接口") + @GetMapping("listSub") + @SystemControllerLog(description = "子业态") + public ResultData listSub(@ModelAttribute WxSubBusiness wxSubBusiness) { + logger.debug("[" + getIpAddr() + "] WxBusinessController::getList"); + final List busList = wxSubBusinessService.findList(wxSubBusiness); + return new ResultData(busList); + } + + @ApiOperation("业态分析接口") + @GetMapping("businessDataList") + @SystemControllerLog(description = "业态分析接口") + public ResultData businessDataList(@ModelAttribute WxBusiness wxBusiness) throws Exception{ + logger.debug("[" + getIpAddr() + "] WxBusinessController::businessDataList"); + wxBusiness.updateTenantInfo(getTenantInfo()); + if(wxBusiness.getStartdate() == null || wxBusiness.getEnddate() == null){ + Date sDate = DateUtils.getFirstDayForCurrMonth(DateUtils.getLastMonthToDay()); + Date eDate = DateUtils.getLastDayForMonth(DateUtils.getLastMonthToDay()); + SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat sdT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + wxBusiness.setStartdate(sdT.parse(sd.format(sDate)+" 00:00:00")); + wxBusiness.setEnddate(sdT.parse(sd.format(eDate)+" 23:59:59")); + } + + List> mapList = wxBusinessService.businessDataList(wxBusiness,getUserId()); + for (Map map:mapList) { + if(map.get("rent") == null){ + map.put("rent",0); + } + if(map.get("sale") == null){ + map.put("sale",0); + map.put("rentSaleRate",0); + continue; + } + BigDecimal sale = new BigDecimal(map.get("sale").toString()); + BigDecimal rent = new BigDecimal(map.get("rent").toString()); + if(sale.doubleValue() <= 0){ + map.put("rentSaleRate",0); + continue; + }else{ + BigDecimal divide = rent.divide(sale, 2, BigDecimal.ROUND_HALF_UP); + map.put("rentSaleRate", divide); + } + } + return new ResultData(mapList); + } + + @ApiOperation("导出业态数据列表") + @GetMapping("exportBusinessDataList") + @SystemControllerLog(description = "导出业态数据列表") + public void exportBusinessDataList(@ModelAttribute WxBusiness wxBusiness, HttpServletResponse response) throws Exception{ + logger.debug("[" + getIpAddr() + "] WxBusinessController::exportBusinessDataList"); + wxBusiness.updateTenantInfo(getTenantInfo()); + if(wxBusiness.getStartdate() == null || wxBusiness.getEnddate() == null){ + Date sDate = DateUtils.getFirstDayForCurrMonth(DateUtils.getLastMonthToDay()); + Date eDate = DateUtils.getLastDayForMonth(DateUtils.getLastMonthToDay()); + SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat sdT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + wxBusiness.setStartdate(sdT.parse(sd.format(sDate)+" 00:00:00")); + wxBusiness.setEnddate(sdT.parse(sd.format(eDate)+" 23:59:59")); + } + List> dataList = wxBusinessService.businessDataList(wxBusiness,getUserId()); + List exeList = new ArrayList<>(); + for (Map m:dataList) { + WxBusinessDataVo businessDataVo = new WxBusinessDataVo(); + businessDataVo.setName((String)m.get("title")); + if(m.get("comPrice") != null) + businessDataVo.setComPrice(m.get("comPrice").toString()); + if(m.get("rent") != null) + businessDataVo.setRentRate(m.get("rent").toString()); + if(m.get("rentSaleRate") != null) + businessDataVo.setRentSaleRate(m.get("rentSaleRate").toString()); + if(m.get("volume") != null) { + //单位转万 + BigDecimal b = (BigDecimal)m.get("volume"); + String dstr = b.divide(new BigDecimal(10000)).setScale(4, BigDecimal.ROUND_HALF_UP).toString(); + businessDataVo.setSale(dstr); + } + if(m.get("sale") != null) + businessDataVo.setSaleRate(m.get("sale").toString()); + + if(m.get("rent") == null){ + m.put("rent",0); + } + if(m.get("sale") == null){ + m.put("sale",0); + m.put("rentSaleRate",0); + businessDataVo.setRentSaleRate("0"); + exeList.add(businessDataVo); + continue; + } + BigDecimal sale = new BigDecimal(m.get("sale").toString()); + BigDecimal rent = new BigDecimal(m.get("rent").toString()); + if(sale.doubleValue() <= 0){ + businessDataVo.setRentSaleRate("0"); + exeList.add(businessDataVo); + continue; + }else { + BigDecimal divide = rent.divide(sale, 2, BigDecimal.ROUND_HALF_UP); + m.put("rentSaleRate", divide); + businessDataVo.setRentSaleRate(divide.toString()); + } + exeList.add(businessDataVo); + } + excelService.exportExcel(exeList, null, "业态统计", WxBusinessDataVo.class, "业态统计列表.xlsx", response, false); + } + + @ApiOperation("贡献率排行") + @GetMapping("devoteList") + @SystemControllerLog(description = "贡献率排行") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + public ResultData devoteList(@ModelAttribute WxBusiness wxBusiness,Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxBusinessController::devoteList"); + wxBusiness.updateTenantInfo(getTenantInfo()); + return new ResultData(wxBusinessService.devoteList(wxBusiness,pageNum,pageSize)); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxDataRuleTargetController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxDataRuleTargetController.java new file mode 100644 index 000000000..16a328d96 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxDataRuleTargetController.java @@ -0,0 +1,57 @@ +package com.iformall.controller.sys; + + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxDataRuleTarget; +import com.iformall.service.WxDataRuleTargetService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxDataRuleTarget") +@Api(description = "数据权限目标") +public class WxDataRuleTargetController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxDataRuleTargetService wxDataRuleTargetService; + + @ApiOperation("列表接口") + @GetMapping("list") + @SystemControllerLog(description = "数据权限目标-列表接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + public ResultData list(@ModelAttribute WxDataRuleTarget wxDataRuleTarget, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] wxDataRuleTarget::list"); + final PageInfo page = wxDataRuleTargetService.listAsPage(wxDataRuleTarget, pageNum, pageSize); + return new ResultData(page); + } + + + @ApiOperation("获取全部") + @GetMapping("getList") + @SystemControllerLog(description = "数据权限目标-获取全部") + public ResultData getList() { + logger.debug("[" + getIpAddr() + "] wxDataRuleTarget::getList"); + List datalist = wxDataRuleTargetService.getList(); + return new ResultData(datalist); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java new file mode 100644 index 000000000..eee9ec850 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java @@ -0,0 +1,56 @@ +package com.iformall.controller.sys; + + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.WxUserDataRule; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.WxUserDataRuleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxUserDataRule") +@Api(description = "用户数据权限") +public class WxUserDataRuleController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxUserDataRuleService wxUserDataRuleService; + + @ApiOperation("编辑") + @PostMapping("/modify") + @SystemControllerLog(description = "用户数据权限-新增") + public ResultData modify(@RequestBody WxUserDataRule wxUserDataRule) { + logger.debug("[" + getIpAddr() + "] wxDataRuleTarget::modify"); + MallUserInfo currentUser = getUser(); + // 系统管理员才能修改信息 + if (!currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + return new ResultData(ErrorCode.USER_NO_PERMISSION.getCode(), "系统管理员才能修改信息"); + } + wxUserDataRuleService.modify(wxUserDataRule); + return new ResultData(); + } + + @ApiOperation("根据用户ID查看") + @GetMapping("/findByUserId") + @ApiImplicitParam(name = "userId", value = "userId", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "用户数据权限-根据用户ID查看") + public ResultData findByUserId(Long userId) { + logger.debug("[" + getIpAddr() + "] wxDataRuleTarget::modify"); + WxUserDataRule wxUserDataRule = wxUserDataRuleService.findByUserId(userId); + return new ResultData(wxUserDataRule); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/video/VideoController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/video/VideoController.java new file mode 100644 index 000000000..597d9d55e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/video/VideoController.java @@ -0,0 +1,105 @@ +package com.iformall.controller.video; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.annotation.UserDataRuleAnnotation; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.WxBillProperty; +import com.iformall.domain.po.WxMallBuilding; +import com.iformall.domain.po.WxMallFloor; +import com.iformall.domain.po.WxMerchant; +import com.iformall.domain.po.WxPropertyContract; +import com.iformall.domain.po.WxRentContract; +import com.iformall.domain.po.WxShop; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.po.base.BaseEntity.SortField; +import com.iformall.enums.EnumContractOperationType; +import com.iformall.enums.EnumContractType; +import com.iformall.enums.EnumFlowContractType; +import com.iformall.enums.EnumFlowKey; +import com.iformall.enums.EnumIsPreview; +import com.iformall.enums.EnumRentContractAppStatus; +import com.iformall.enums.EnumRentContractStatus; +import com.iformall.enums.EnumRentShopType; +import com.iformall.enums.EnumRentStartType; +import com.iformall.exception.MallinkException; +import com.iformall.mapper.WxPropertyContractMapper; +import com.iformall.service.WxBillPropertyService; +import com.iformall.service.WxMallBuildingService; +import com.iformall.service.WxMallFloorService; +import com.iformall.service.WxPropertyContractService; +import com.iformall.service.WxRentPropertyContractService; +import com.iformall.service.WxShopService; +import com.iformall.video.VideoFactory; +import com.iformall.video.entity.VideUploadResult; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("video") +public class VideoController extends BaseController { + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + VideoFactory videoFactory; + + @Autowired + String videoType; + + @GetMapping("/test") + @ApiImplicitParams({ + @ApiImplicitParam(name = "title", value = "页数", dataType = "String", paramType = "query", required = true)}) + public ResultData list(@ModelAttribute WxPropertyContract wxPropertyContract, String title) { + VideUploadResult result = videoFactory.getExcutor(videoType).uploadLocalVideo("123123213", "/root/111.mp4"); + return new ResultData(result); + } + + /** + * 上传视频 + * + * @param multiReq + * @return + * @throws Exception + */ + @PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("上传视频") + @SystemControllerLog(description = "文件上传") + public ResultData awsfileUpload(@RequestParam("file") MultipartFile multiReq,@RequestParam Map param) { + try { + String title = param.get("title"); + VideUploadResult result = videoFactory.getExcutor(videoType).uploadLocalVideo(title, multiReq.getInputStream()); + return new ResultData(result); + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); + } + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/controller/workflow/WxFlowAbleController.java b/mallinkTTAdmin/src/main/java/com/iformall/controller/workflow/WxFlowAbleController.java new file mode 100644 index 000000000..266db19dc --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/controller/workflow/WxFlowAbleController.java @@ -0,0 +1,296 @@ +package com.iformall.controller.workflow; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.enums.EnumFlowRecordStatus; +import com.iformall.service.WxFlowService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.*; + +@RestController +@Api(description = "工作流相关接口") +@RequestMapping(value = "workflow") +public class WxFlowAbleController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxFlowService wxFlowService; + + @ApiOperation(value = "启动流程",notes = "{\"businessId\":\"221178539888607232\",\"businessType\":1,\"remark\":\"意见意见。\",\"taskAssignee\":[{\"taskKey\":\"firstTaskUser\",\"assignee\":\"243650055783841792\"},{\"taskKey\":\"secondTaskUser\",\"assignee\":\"\"}],\"variables\":[{\"key\":\"contractType\",\"value\":\"1\"},{\"key\":\"contractNumber\",\"value\":\"1111\"}]}") + @PostMapping("/start") + @SystemControllerLog(description = "工作流-启动流程") + public ResultData start(@RequestBody Map params) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::start"); + MallUserInfo user = getUser(); + return wxFlowService.start(params, user.getId(),user.getName(),user); + } + + /** + * 用户代办列表 + */ + @ApiOperation("用户代办列表") + @GetMapping(value = "/list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "businessType", value = "流程类型,1合同流程 2账单流程", dataType = "int", paramType = "query", required = true) + }) + @SystemControllerLog(description = "工作流-用户代办列表") + public ResultData list(Integer pageNum, Integer pageSize,Integer businessType) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::list"); + String flowType = null; + if (null != businessType) { + flowType = String.valueOf(businessType); + } + return wxFlowService.list(flowType,pageNum,pageSize,getUserId(),getTenantInfo()); + } + + /** + * 待办总数 + */ + @ApiOperation("待办总数") + @GetMapping(value = "/getTotal") + @SystemControllerLog(description = "工作流-待办总数") + public ResultData getTotal() { + logger.debug("[" + getIpAddr() + "] FlowAbleController::getTotal"); + return wxFlowService.getTotal(getUserId(), getTenantInfo()); + } + + /** + * 我的申请列表 + */ + @ApiOperation("我的申请列表") + @GetMapping(value = "/myApplyList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), + }) + @SystemControllerLog(description = "工作流-我的申请列表") + public ResultData myApplyList(@ModelAttribute WxFlowRecord record, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::myApplyList"); + record.setUserId(getUserId()); + record.setStatus(EnumFlowRecordStatus.NEW.getCode()); + + PageInfo pageInfo = wxFlowService.listAsPage(record,pageNum,pageSize); + List recordList = pageInfo.getList(); + for (WxFlowRecord wxFlowRecord:recordList) { + if(StringUtils.isBlank(wxFlowRecord.getVariables())){ + wxFlowRecord.setVariables("{}"); + } + } + return new ResultData(pageInfo); + } + + /** + * 我的审批列表 + */ + @ApiOperation("我的审批列表") + @GetMapping(value = "/myHandleList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "businessType", value = "业务类型", dataType = "int", paramType = "query", required = true) + }) + @SystemControllerLog(description = "工作流-我的审批列表") + public ResultData myHandleList(@ModelAttribute WxFlowRecord record, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::myHandelList"); + record.setUserId(getUserId()); + record.setStatus(EnumFlowRecordStatus.NEW.getCode()); + PageInfo pageInfo = wxFlowService.myHandelList(record,pageNum,pageSize); + List recordList = pageInfo.getList(); + for (WxFlowRecord wxFlowRecord:recordList) { + if(StringUtils.isBlank(wxFlowRecord.getVariables())){ + wxFlowRecord.setVariables("{}"); + } + } + return new ResultData(pageInfo); + } + + /** + * 审批历史 + */ + @ApiOperation("审批历史") + @GetMapping(value = "/applyHistory") + @ApiImplicitParams({ + @ApiImplicitParam(name = "businessId", value = "业务id", dataType = "String", paramType = "query", required = true), + }) + @SystemControllerLog(description = "工作流-审批历史") + public ResultData applyHistory(String businessId) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::applyHistory"); + return wxFlowService.applyHistory(businessId,getTenantInfo()); + } + + /** + * 审批历史和代办 + */ + @ApiOperation("审批历史和代办") + @GetMapping(value = "/applyHistoryAndAssignee") + @ApiImplicitParams({ + @ApiImplicitParam(name = "businessId", value = "业务id", dataType = "String", paramType = "query", required = true), + }) + @SystemControllerLog(description = "工作流-审批历史和代办") + public ResultData applyHistoryAndAssignee(String businessId) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::applyHistoryAndAssignee"); + return wxFlowService.getTaskStatusList(businessId,getTenantInfo()); + } + + /** + * 审批 + */ + @ApiOperation(value = "审批",notes = "{\"taskId\":\"\",\"processInstanceId\":\"\",\"remark\":\"\"}") + @PostMapping(value = "apply") + public ResultData apply(@RequestBody Map params) { + MallUserInfo user = getUser(); + return wxFlowService.apply(params,user.getId(),user.getName(),user); + } + + /** + * 驳回 + */ + @ApiOperation(value = "驳回",notes = "{\"taskId\":\"\",\"processInstanceId\":\"\",\"remark\":\"\"}") + @PostMapping(value = "reject") + @SystemControllerLog(description = "工作流-驳回") + public ResultData reject(@RequestBody Map params) { + MallUserInfo user = getUser(); + return wxFlowService.reject(params,user.getId(),user.getName(),user.getPhone(),user); + } + + + /** + * 撤回 + */ + @ApiOperation(value = "撤回",notes = "{\"taskId\":\"\",\"processInstanceId\":\"\",\"remark\":\"\"}") + @PostMapping(value = "setBack") + @SystemControllerLog(description = "工作流-撤回") + public ResultData setBack(@RequestBody Map params) { + MallUserInfo user = getUser(); + return wxFlowService.setBack(params,user.getId(),user.getName()); + } + + + /** + * 创建模板 + */ + @ApiOperation(value = "创建模板") + @PostMapping(value = "createModel") + @SystemControllerLog(description = "工作流-创建模板") + public ResultData createModel(@RequestBody WxFlowModel wxFlowModel) { + wxFlowModel.updateTenantInfo(getTenantInfo()); + wxFlowModel.setCreateUser(getUserId()); + return wxFlowService.createModel(wxFlowModel); + } + + /** + * 根据id查询模板 + */ + @ApiOperation(value = "根据id查询模板",notes = "") + @GetMapping(value = "findModelById") + @SystemControllerLog(description = "工作流-根据id查询模板") + public ResultData findById(@ModelAttribute WxFlowModel wxFlowModel){ + wxFlowModel.updateTenantInfo(getTenantInfo()); + return wxFlowService.findModelById(wxFlowModel); + } + + /** + * 删除模板 + */ + @ApiOperation(value = "删除模板") + @PostMapping(value = "delModel") + @SystemControllerLog(description = "工作流-删除模板") + public ResultData delModel(@RequestBody WxFlowModel wxFlowModel) { + wxFlowModel.updateTenantInfo(getTenantInfo()); + return wxFlowService.delModel(wxFlowModel); + } + + /** + * 模板列表 + */ + @ApiOperation("模板列表") + @GetMapping(value = "/modelList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), + }) + @SystemControllerLog(description = "工作流-模板列表") + public ResultData modelList(@ModelAttribute WxFlowModel wxFlowModel,Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::modelList"); + wxFlowModel.updateTenantInfo(getTenantInfo()); + return new ResultData(wxFlowService.modelList(wxFlowModel,pageNum,pageSize)); + } + + /** + * 根据业务查询模板 + */ + @ApiOperation("根据业务查询模板") + @GetMapping(value = "/getModelBybusiness") + @SystemControllerLog(description = "工作流-模板列表") + public ResultData getModelBybusiness(@ModelAttribute WxFlowModel wxFlowModel) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::getModelBybusiness"); + wxFlowModel.updateTenantInfo(getTenantInfo()); + return new ResultData(wxFlowService.getModelBybusiness(wxFlowModel)); + } + + /** + * 配置列表 + */ + @ApiOperation("配置列表") + @GetMapping(value = "/configList") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), + }) + @SystemControllerLog(description = "工作流-配置列表") + public ResultData configList(@ModelAttribute WxFlowConfig wxFlowConfig, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] FlowAbleController::modelList"); + wxFlowConfig.updateTenantInfo(getTenantInfo()); + if(pageSize == null){ + pageSize = Integer.MAX_VALUE; + } + if(pageNum == null){ + pageNum = 1; + } + + wxFlowConfig.setParentId(0l); + PageInfo pageInfo = wxFlowService.configList(wxFlowConfig,pageNum,pageSize); + List list = pageInfo.getList(); + for (WxFlowConfig c:list) { + if(CollectionUtils.isNotEmpty(c.getChilds())){ + for (WxFlowConfig ch:c.getChilds()) { + if(ch.getModelId() != null){ + WxFlowModel query = new WxFlowModel(); + query.setId(ch.getModelId()); + ch.setWxFlowModel((WxFlowModel)wxFlowService.findModelById(query).data); + } + } + } + } + pageInfo.setList(list); + return new ResultData(pageInfo); + } + + /** + * 类型设置 + */ + @ApiOperation(value = "类型设置") + @PostMapping(value = "updateConfig") + @SystemControllerLog(description = "工作流-类型设置") + public ResultData updateConfig(@RequestBody WxFlowConfig wxFlowConfig) { + wxFlowConfig.updateTenantInfo(getTenantInfo()); + return wxFlowService.updateConfig(wxFlowConfig); + } + + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/enums/EnumLoginType.java b/mallinkTTAdmin/src/main/java/com/iformall/enums/EnumLoginType.java new file mode 100644 index 000000000..d25d5f607 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/enums/EnumLoginType.java @@ -0,0 +1,38 @@ +package com.iformall.enums; + +/** + * Created by Stormeye on 2018/11/16. + */ +public enum EnumLoginType { + + // 0-password, 1-nopassword + + PASSWORD(0, "PASSWORD"), + NOPASSWD(1, "NOPASSWORD") + ; + + public static EnumLoginType getEnum(Integer code) { + for (EnumLoginType value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumLoginType(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/flowable/ContractTaskFinishHandler.java b/mallinkTTAdmin/src/main/java/com/iformall/flowable/ContractTaskFinishHandler.java new file mode 100644 index 000000000..39982396e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/flowable/ContractTaskFinishHandler.java @@ -0,0 +1,44 @@ +package com.iformall.flowable; + +import com.iformall.enums.EnumRentContractAppStatus; +import com.iformall.service.WxFlowService; +import com.iformall.service.WxPropertyContractService; +import com.iformall.service.impl.WxFlowServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.delegate.TaskListener; +import org.flowable.task.service.delegate.DelegateTask; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; + +/** + * 合同审批完成,修改状态 + * + */ +@Component(value="contractTaskFinishListener") +public class ContractTaskFinishHandler implements TaskListener { + @Autowired + private WxFlowService wxFlowService; + @Autowired + private WxPropertyContractService wxPropertyContractService; + + @Override + public void notify(DelegateTask delegateTask) { +// Long businessId = (Long)delegateTask.getVariable("businessId"); +// List> variables = (List)delegateTask.getVariable("variables"); +// Integer flowType = (Integer)delegateTask.getVariable("flowType"); +// +// Integer contractType = 0; +// String str = WxFlowServiceImpl.getVariableByKey(variables,"contractType"); +// if(StringUtils.isNotBlank(str)){ +// contractType = Integer.parseInt(str); +// +// if(3==contractType){ +// wxPropertyContractService.updatePropertyContractStatus(businessId); +// } +// } +// wxFlowService.updateBusinessStatus(businessId,flowType,contractType,EnumRentContractAppStatus.FINISH.getCode()); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/flowable/FlowableConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/flowable/FlowableConfig.java new file mode 100644 index 000000000..0c71fc1d7 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/flowable/FlowableConfig.java @@ -0,0 +1,22 @@ +package com.iformall.flowable; + +import org.flowable.spring.SpringProcessEngineConfiguration; +import org.flowable.spring.boot.EngineConfigurationConfigurer; +import org.springframework.context.annotation.Configuration; + +/** + * @author haiyangp + * date: 2018/4/7 + * desc: flowable配置----为放置生成的流程图中中文乱码 + */ +@Configuration +public class FlowableConfig implements EngineConfigurationConfigurer { + + + @Override + public void configure(SpringProcessEngineConfiguration engineConfiguration) { + engineConfiguration.setActivityFontName("宋体"); + engineConfiguration.setLabelFontName("宋体"); + engineConfiguration.setAnnotationFontName("宋体"); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java new file mode 100644 index 000000000..38aec3039 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -0,0 +1,76 @@ +package com.iformall.interceptor; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.*; + +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { + private final String body; + + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + try { + InputStream inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); + char[] charBuffer = new char[1024]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + throw ex; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ex) { + throw ex; + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(body.getBytes("utf-8")); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/interceptor/CurrentTenantInterceptor.java b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/CurrentTenantInterceptor.java new file mode 100644 index 000000000..aa77a078b --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/CurrentTenantInterceptor.java @@ -0,0 +1,39 @@ +package com.iformall.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import com.iformall.annotation.TenantIgnore; +import com.iformall.common.TenantThreadLocal; +import com.iformall.shiro.UserSession; + +/** + * 权限(Token)验证 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:38 + */ +@Component +public class CurrentTenantInterceptor extends HandlerInterceptorAdapter { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + TenantThreadLocal.setCurrentThreadTenant((String)request.getSession().getAttribute(UserSession.tenantId), + (String)request.getSession().getAttribute(UserSession.parentTenantId)); + + TenantIgnore annotation = null; + if(handler instanceof HandlerMethod) { + annotation = ((HandlerMethod) handler).getMethodAnnotation(TenantIgnore.class); + } + + //如果有@TenantIgnore注解,则把tenant信息全部清掉 + if(annotation != null){ + TenantThreadLocal.remove(); + } + + return true; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java new file mode 100644 index 000000000..aebf7d874 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -0,0 +1,72 @@ +package com.iformall.interceptor; + +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; + +public class HttpServletRequestWrapperFilter implements Filter { + private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapperFilter.class); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + ServletRequest requestWrapper = null; + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + + if (request instanceof HttpServletRequest) { + String url = ((HttpServletRequest) request).getRequestURI(); + if (!UrlCheck.checkUrl(url)) { + requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request); + } + } + if (null == requestWrapper) { + chain.doFilter(xssHttpServletRequestWrapper, response); + } else { + chain.doFilter(requestWrapper, response); + } + + } + + + @Override + public void destroy() { + + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/interceptor/RequestInterceptor.java b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/RequestInterceptor.java new file mode 100644 index 000000000..d7b493d12 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/RequestInterceptor.java @@ -0,0 +1,117 @@ +package com.iformall.interceptor; + +import com.iformall.common.ErrorCode; +import com.iformall.exception.MallinkException; +import com.iformall.utils.HashUtil; +import com.iformall.utils.IPUtil; +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.util.SafeEncoder; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.concurrent.TimeUnit; + +/** + * 幂等检查 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:38 + */ +@Component +public class RequestInterceptor extends HandlerInterceptorAdapter { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + private RedisTemplate redisTemplate; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if ("GET".equalsIgnoreCase(request.getMethod())) { + // 获取不检查幂等 + return true; + } + + String ipaddress = IPUtil.getIpAddr(request); + String url = request.getRequestURL().toString(); + if (UrlCheck.checkUrl(url)) { + // pvlog不检查幂等 + // awsFileUpload不检查幂等 + // ueditor 不检查幂等 + return true; + } + StringBuilder sb = new StringBuilder(); + sb.append(url); + sb.append("method=").append(request.getMethod()).append("&"); + sb.append("ip=").append(ipaddress).append("&"); + + final Enumeration parameterNames = request.getParameterNames(); + while (parameterNames.hasMoreElements()) { + String key = (String) parameterNames.nextElement(); + if(key.equalsIgnoreCase("ran")) // 跳过ran + continue; + String parameter = request.getParameter(key); + sb.append(key).append("=").append(parameter).append("&"); + } + + InputStream inStream = request.getInputStream(); + ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while ((len = inStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + String resultBody = new String(outSteam.toByteArray(), Charset.forName("UTF-8")); + inStream.close(); + outSteam.close(); + + sb.append(resultBody); + + String key = "request:A:" + HashUtil.md5(sb.toString()); + Boolean isAbsent = redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + RedisSerializer valueSerializer = redisTemplate.getValueSerializer(); + RedisSerializer keySerializer = redisTemplate.getKeySerializer(); + Object obj = connection.execute("set", keySerializer.serialize(key), + valueSerializer.serialize(key), + SafeEncoder.encode("NX"), + SafeEncoder.encode("EX"), + Protocol.toByteArray(3)); // 3s + return obj != null; + } + }); + if (isAbsent) { + logger.info(key + ": 第一次提交"); + return true; + } + logger.info(key + ": 第二次提交"); + throw new MallinkException(ErrorCode.SYS_REPEAT_SUBMIT_EXCEPTION); + } + + @Override + public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + + @Override + public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception { + + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..1d954d163 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,125 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + if(name.equalsIgnoreCase("user-agent")) { + return super.getHeader(name); + } + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); + value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); + value = value.replaceAll("'", "& #39;"); + value = value.replaceAll("eval\\((.*)\\)", ""); + value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); + value = value.replaceAll("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/log/SystemLogAspect.java b/mallinkTTAdmin/src/main/java/com/iformall/log/SystemLogAspect.java new file mode 100644 index 000000000..465889699 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/log/SystemLogAspect.java @@ -0,0 +1,174 @@ +package com.iformall.log; + + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.annotation.SystemServiceLog; +import com.iformall.domain.po.MallUserAction; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.enums.EnumMallUserAction; +import com.iformall.service.MallUserActionService; +import com.iformall.shiro.UserSession; +import com.iformall.utils.IPUtil; +import org.apache.shiro.SecurityUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Date; + +@Aspect +@Component +public class SystemLogAspect { + private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class); + + @Autowired + private MallUserActionService mallUserActionService; + + @Pointcut("@annotation(com.iformall.annotation.SystemControllerLog)") + public void controllerAspect(){ + } + + @Pointcut("@annotation(com.iformall.annotation.SystemServiceLog)") + public void serviceAspect(){ + } + + @Before("controllerAspect()") + public void doBefore(JoinPoint joinPoint) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + MallUserInfo user = (MallUserInfo) request.getSession().getAttribute(UserSession.userInfo); + if(user == null) { + logger.error("session 获取 user 失败"); + return; + } + String ipaddress = IPUtil.getIpAddr(request); + + try { + logger.info("===前置通知开始=== [" + + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName()) + "]" + + getControllerMethodDescription(joinPoint) + " " + user.getUsername() + + " ip:" + ipaddress); + + MallUserAction action = new MallUserAction(); + action.updateTenantInfo(user); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setUserId(user.getId()); + action.setActionDesc(getControllerMethodDescription(joinPoint)); + action.setActionTime(new Date()); + + mallUserActionService.saveOrUpdate(action); + } catch (Exception e) { + logger.error("===前置通知异常信息:{}",e.getMessage()); + } + } + + /** + * @Description 异常通知 用于拦截service层记录异常日志 + * @date 2019年3月29日 + */ + @AfterThrowing(pointcut = "serviceAspect()",throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint,Throwable e){ + /* + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + HttpSession session = request.getSession(); + MallUserInfo user = (MallUserInfo) request.getSession().getAttribute(UserSession.userInfo); + //获取请求ip + String ipaddress = IPUtil.getIpAddr(request); + //获取用户请求方法的参数并序列化为JSON格式字符串 + String params = ""; + if (joinPoint.getArgs()!=null&&joinPoint.getArgs().length>0){ + for (int i = 0; i < joinPoint.getArgs().length; i++) { + params+= JsonUtils.objectToJson(joinPoint.getArgs()[i])+";"; + } + } + try{ + // ========控制台输出========= + System.out.println("=====异常通知开始====="); + System.out.println("异常代码:" + e.getClass().getName()); + System.out.println("异常信息:" + e.getMessage()); + System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); + System.out.println("方法描述:" + getServiceMethodDescription(joinPoint)); + System.out.println("请求人:" + user.getUsername()); + System.out.println("请求IP:" + ipaddress); + System.out.println("请求参数:" + params); + + + MallUserAction action = new MallUserAction(); + action.setTenantId(user.getTenantId()); + action.setUserId(user.getId()); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setDesc(getControllerMethodDescription(joinPoint)); + action.setActionTime(new Date()); + + mallUserActionService.saveOrUpdate(action); + }catch (Exception ex){ + //记录本地异常日志 + logger.error("==异常通知异常=="); + logger.error("异常信息:{}", ex.getMessage()); + } + */ + } + + /** + * @author Stormeye + * @Description 获取注解中对方法的描述信息 用于Controller层注解 + * @date 2019年3月29日 + */ + public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception { + String targetName = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName();//目标方法名 + Object[] arguments = joinPoint.getArgs(); + Class targetClass = Class.forName(targetName); + Method[] methods = targetClass.getMethods(); + String description = ""; + for (Method method:methods) { + if (method.getName().equals(methodName)){ + Class[] clazzs = method.getParameterTypes(); + if (clazzs.length==arguments.length){ + description = method.getAnnotation(SystemControllerLog.class).description(); + break; + } + } + } + //TODO 调试使用 + //return String.format("%s%s",description, Arrays.asList(arguments)); + return description; + } + + /** + * @Description 获取注解中对方法的描述信息 用于service层注解 + * @date 2018年9月3日 下午5:05 + */ + public static String getServiceMethodDescription(JoinPoint joinPoint)throws Exception{ + String targetName = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + Object[] arguments = joinPoint.getArgs(); + Class targetClass = Class.forName(targetName); + Method[] methods = targetClass.getMethods(); + String description = ""; + for (Method method:methods) { + if (method.getName().equals(methodName)){ + Class[] clazzs = method.getParameterTypes(); + if (clazzs.length==arguments.length){ + description = method.getAnnotation(SystemServiceLog.class).description(); + break; + } + } + } + return description; + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/log/TableOperateAspect.java b/mallinkTTAdmin/src/main/java/com/iformall/log/TableOperateAspect.java new file mode 100644 index 000000000..3dee1b300 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/log/TableOperateAspect.java @@ -0,0 +1,213 @@ +package com.iformall.log; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Lists; +import com.google.common.collect.MapDifference; +import com.google.common.collect.Maps; +import com.iformall.common.LogColumn; +import com.iformall.domain.po.invest.InvestBaseEntity; +import com.iformall.domain.po.invest.InvestOperateRecordEntity; +import com.iformall.domain.vo.invest.InvestUserContext; +import com.iformall.domain.vo.invest.TableTriple; +import com.iformall.enums.EnumTableOperateType; +import com.iformall.service.invest.InvestHelper; +import com.iformall.service.invest.InvestOperateRecordService; +import com.iformall.service.invest.impl.InvestBaseServiceImpl; +import com.iformall.utils.SpringContextUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.*; + +/** + * + */ +@Slf4j +@Aspect +@Component +public class TableOperateAspect { + + @Autowired + private InvestOperateRecordService operateRecordService; + + @Pointcut("@annotation(com.iformall.common.TableLog)") + public void pointcut() { + } + + @Around("pointcut()") + public Object round(ProceedingJoinPoint joinPoint) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + log.debug("before , {}.{}() with argument[s] = {}", signature.getDeclaringType(), + signature.getName(), Arrays.toString(joinPoint.getArgs())); + Object result = null; + Object entity = null; + Map beforeMap = null; + Long tid = null; + try { + entity = joinPoint.getArgs()[0]; + tid = getId(entity); + beforeMap = getFeildMap(getById(signature, tid)); + } catch (Exception e) { + log.error("before ", e); + } + try { + result = joinPoint.proceed(); + } catch (Throwable throwable) { + log.error("proceed error , Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), + joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), throwable); + } finally { + log.debug("after , result: {}", result); + } + try { + saveRecord(signature, beforeMap, entity, tid); + } catch (Exception e) { + log.error("save table Record ", e); + } + return result; + } + + private Long getId(Object entity) { + Long tid; + if (entity instanceof InvestBaseEntity) { + tid = ((InvestBaseEntity) entity).getId(); + } else { + tid = (Long) entity; + } + return tid; + } + + private void saveRecord(MethodSignature signature, Map beforeMap, Object arg, Long tid) throws IllegalAccessException { + EnumTableOperateType operateType = getOperateType(signature.getName()); + if (Objects.equals(operateType, EnumTableOperateType.DELETE)) { + arg = null; + } + if (Objects.isNull(tid)) { + tid = getId(arg); + } + Map afterMap = getFeildMap(arg); + List content = getContent(beforeMap, afterMap); + log.debug("operate content: {}", JSON.toJSONString(content)); + if (CollectionUtils.isEmpty(content)) { + return; + } + List toSaveRecord = new ArrayList<>() ; + for (Object o : content) { + InvestOperateRecordEntity recordEntity = new InvestOperateRecordEntity(); + recordEntity.setContent(JSON.toJSONString(o)); + recordEntity.setOperateType(operateType); + recordEntity.setOperator(InvestUserContext.getUserId()); + recordEntity.setTbl(getTbl(signature)); + recordEntity.setTid(tid); + toSaveRecord.add(recordEntity) ; + } + operateRecordService.saveBatch(toSaveRecord); + log.debug("saveRecord: {}", JSON.toJSONString(content)); + } + + private String getTbl(MethodSignature signature) { + ParameterizedType type = (ParameterizedType) signature.getDeclaringType().getGenericSuperclass(); + Class clazz = (Class) type.getActualTypeArguments()[1]; + TableName tableName = (TableName) clazz.getAnnotation(TableName.class); + return tableName.value(); + } + + private EnumTableOperateType getOperateType(String methodName) { + if (StringUtils.contains(methodName, "update")) { + return EnumTableOperateType.UPDATE; + } else if (StringUtils.contains(methodName, "remove")) { + return EnumTableOperateType.DELETE; + } + return EnumTableOperateType.ADD; + } + + private Map getFeildMap(Object entity) throws IllegalAccessException { + if (Objects.isNull(entity)) { + return null; + } + Map map = new HashMap<>(); + List fields = FieldUtils.getFieldsListWithAnnotation(entity.getClass(), LogColumn.class); + for (Field field : fields) { + String annotationVal = field.getAnnotation(LogColumn.class).value(); + Object value = FieldUtils.readDeclaredField(entity, field.getName(), true); + if(Objects.isNull(value)) { + continue; + } + if (field.getType().isEnum()) { + value = InvestHelper.getEnumVal(InvestHelper.valueOf(value.getClass(), ((Enum) value).name())); + } + if (Objects.equals(annotationVal, InvestBaseEntity.COLUMN_TYPE)) { + value = JSON.parseObject((String) value, Map.class); + } + map.put(field.getName(), value); + } + return map; + } + + private List> getContent(Map before, Map after) { + if (Objects.isNull(before) || Objects.isNull(after)) { + return mapToList(before, after); + } + MapDifference diffInner = Maps.difference(before, after); + List> diffRows = Lists.newArrayList(); + if (diffInner.areEqual()) { + return diffRows; + } + Map> differenceMap = diffInner.entriesDiffering(); + for (Map.Entry> entry : differenceMap.entrySet()) { + String s = entry.getKey(); + MapDifference.ValueDifference objectValueDifference = entry.getValue(); + Object innerBefore = objectValueDifference.leftValue(); + Object innerAfter = objectValueDifference.rightValue(); + if (innerBefore instanceof Map) { + diffRows.addAll(getContent((Map) innerBefore, (Map) innerAfter)); + } else { + diffRows.add(new TableTriple(s, innerBefore, innerAfter)); + } + } + return diffRows; + } + + private List> mapToList(Map before, Map after) { + List> list = Lists.newArrayList(); + Set keys = Objects.isNull(before) ? after.keySet() : before.keySet(); + for (String key : keys) { + if (Objects.isNull(before)) { + Object innerAfter = after.get(key); + if (innerAfter instanceof Map) { + list.addAll(mapToList(null, (Map) innerAfter)); + } else { + list.add(new TableTriple(key, "", innerAfter)); + } + } else { + Object innerBefore = before.get(key); + if (innerBefore instanceof Map) { + list.addAll(mapToList((Map) innerBefore, null)); + } else { + list.add(new TableTriple(key, innerBefore, "")); + } + } + } + return list; + } + + private T getById(MethodSignature signature, Serializable id) { + Class service = signature.getDeclaringType(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("id", id); + return (T) ((InvestBaseServiceImpl) SpringContextUtils.getBean(service)).getOne(wrapper); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java b/mallinkTTAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java new file mode 100644 index 000000000..acd100a64 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java @@ -0,0 +1,108 @@ +package com.iformall.log; + + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.iformall.annotation.UserDataRuleAnnotation; +import com.iformall.domain.po.base.BaseEntity; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.WxUserDataRule; +import com.iformall.mapper.WxRentContractMapper; +import com.iformall.service.WxUserDataRuleService; +import com.iformall.shiro.UserSession; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; +import java.util.HashSet; + +/** + * @author gongbiao + */ +@Aspect +@Component +public class UserDataRuleAspect { + private static final Logger logger = LoggerFactory.getLogger(UserDataRuleAspect.class); + + @Autowired + private WxUserDataRuleService wxUserDataRuleService; + + @Autowired + private WxRentContractMapper wxRentContractMapper; + + @Pointcut("@annotation(com.iformall.annotation.UserDataRuleAnnotation)") + public void userDataRulePointcut() { + } + + @Before("userDataRulePointcut()") + public void doBefore(JoinPoint joinPoint) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + MallUserInfo user = (MallUserInfo) request.getSession().getAttribute(UserSession.userInfo); + if (user == null) { + logger.error("session 获取 user 失败"); + return; + } + + //得到用户的数据权限 + WxUserDataRule byUserId = wxUserDataRuleService.findByUserId(user.getId()); + if (byUserId == null) { + logger.info("用户的数据权限未配置"); + return; + } + String buildingFloor = byUserId.getBuildingFloor(); + if (StringUtils.isNotEmpty(buildingFloor)) { + Object[] data = JSONArray.parseArray(buildingFloor).toArray(); + buildingFloor = StringUtils.join(data, ","); + } + + String businessForRule = byUserId.getBusiness(); + if (StringUtils.isNotEmpty(businessForRule)) { + Object[] data = JSONArray.parseArray(businessForRule).toArray(); + businessForRule = StringUtils.join(data, ","); + } + + HashSet targetSet = new HashSet(); + String target = byUserId.getTarget(); + if (StringUtils.isNotEmpty(target)) { + JSONArray objects = JSONArray.parseArray(target); + for (int i = 0; i < objects.size(); i++) { + JSONObject jsonObject = objects.getJSONObject(i); + targetSet.add(jsonObject.getString("tag")); + } + } + + //得到注释的名称 + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + //判断tag是否在用户权限中 如果存在加入参数查询 + Method method = signature.getMethod(); + String value = method.getAnnotation(UserDataRuleAnnotation.class).value(); + if (targetSet.contains(value)) { + //得到方法的参数 + Object[] args = joinPoint.getArgs(); + if (args[0] instanceof BaseEntity) { + BaseEntity baseEntity = (BaseEntity) args[0]; + baseEntity.setFloorForRule(buildingFloor); + baseEntity.setBusinessForRule(businessForRule); + String contract = "contract"; + if (StringUtils.isNotEmpty(buildingFloor) && value.contains(contract)) { + int count = wxRentContractMapper.getShopCountMax(); + String[] tempShop = new String[count]; + baseEntity.setTempShop(tempShop); + } + } + + } + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java b/mallinkTTAdmin/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java new file mode 100644 index 000000000..f08030e1c --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java @@ -0,0 +1,27 @@ +package com.iformall.shiro; + +import com.iformall.enums.EnumLoginType; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyRetryLimitCredentialsMatcher extends HashedCredentialsMatcher { + + @Override + public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) { + if(authcToken instanceof UseriFormallToken) { + UseriFormallToken tk = (UseriFormallToken) authcToken; + if(tk.getType().equals(EnumLoginType.NOPASSWD)){ + // 获取用户的输入的账号. + String username = (String)tk.getPrincipal(); + return true; + } + boolean matches = super.doCredentialsMatch(authcToken, info); + return matches; + } + boolean matches =super.doCredentialsMatch(authcToken, info); + return matches; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/shiro/MyShiroRealm.java b/mallinkTTAdmin/src/main/java/com/iformall/shiro/MyShiroRealm.java new file mode 100644 index 000000000..2689cc3c8 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/shiro/MyShiroRealm.java @@ -0,0 +1,94 @@ +package com.iformall.shiro; + +import javax.annotation.Resource; + +import com.iformall.common.ErrorCode; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.service.MallUserInfoService; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.util.ByteSource; + +import com.iformall.domain.po.MallUserInfo; + +import java.util.Set; + +/** + * Created by yangqj on 2017/4/21. + */ +public class MyShiroRealm extends AuthorizingRealm { + + @Resource + private MallUserInfoService userService; + + //授权 + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { + MallUserInfo user= (MallUserInfo) SecurityUtils.getSubject().getPrincipal(); + Set permissionSet = userService.getUserPermissions(user, true); + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + info.setStringPermissions(permissionSet); + return info; + } + + //认证 + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + //获取用户的输入的账号. + String username = (String)token.getPrincipal(); + MallUserInfo user = userService.getByUsername(username); + if(user == null) { + throw new UnknownAccountException(ErrorCode.USER_IS_EMPTY.getMessage()); + } + // 租户1为预留系统管理端 +// if(user.getTenantId().equals("1")) { +// // 只支持租户为1的用户 +// throw new UnknownAccountException("租户不支持"); +// } + + if(user.getStatus()==null || + !EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) {//用户被禁用 + throw new DisabledAccountException(ErrorCode.USER_IS_LOCKED.getMessage()); + } + SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( + user, //用户 + user.getPassword(), //密码 + ByteSource.Util.bytes(username), + getName() //realm name + ); + // 当验证都通过后,把用户信息放在session里 + Session session = SecurityUtils.getSubject().getSession(); + session.setAttribute(UserSession.userInfo, user); + session.setAttribute(UserSession.userId, user.getId()); + session.setAttribute(UserSession.tenantId, user.getTenantId()); + if (StringUtils.isNotBlank(user.getParentTenantId())) { + session.setAttribute(UserSession.parentTenantId, user.getParentTenantId()); + }else{ + session.setAttribute(UserSession.parentTenantId, null); +// String parentTenantId = (String)session.getAttribute(UserSession.parentTenantId); +// if(StringUtils.isNotBlank(parentTenantId)){ +// session.removeAttribute(UserSession.parentTenantId); +// } + } + + return authenticationInfo; + } + + + /** + * 指定principalCollection 清除 + */ + /* public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) { + + SimplePrincipalCollection principals = new SimplePrincipalCollection( + principalCollection, getName()); + super.clearCachedAuthorizationInfo(principals); + } +*/ +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/shiro/PasswordHelper.java b/mallinkTTAdmin/src/main/java/com/iformall/shiro/PasswordHelper.java new file mode 100644 index 000000000..73b38e436 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/shiro/PasswordHelper.java @@ -0,0 +1,35 @@ +package com.iformall.shiro; + + +import com.iformall.domain.po.MallUserInfo; +import org.apache.shiro.crypto.hash.SimpleHash; +import org.apache.shiro.util.ByteSource; + + + +public class PasswordHelper { + //private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); + private String algorithmName = "md5"; + private int hashIterations = 2; + + public void encryptPassword(MallUserInfo user) { + //String salt=randomNumberGenerator.nextBytes().toHex(); + String newPassword = new SimpleHash(algorithmName, user.getPassword(), ByteSource.Util.bytes(user.getUsername()), hashIterations).toHex(); + //String newPassword = new SimpleHash(algorithmName, user.getPassword()).toHex(); + user.setPassword(newPassword); + + } + + + public static void main(String[] args) { + MallUserInfo user = new MallUserInfo(); + user.setUsername("fmoperator"); + user.setPassword("fm202008admin"); + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(user); + System.out.println(user); + System.out.println(user.getPassword()); + } + + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/shiro/ShiroService.java b/mallinkTTAdmin/src/main/java/com/iformall/shiro/ShiroService.java new file mode 100644 index 000000000..5c311ac54 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/shiro/ShiroService.java @@ -0,0 +1,127 @@ +package com.iformall.shiro; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager; +import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver; +import org.apache.shiro.web.servlet.AbstractShiroFilter; +import org.crazycake.shiro.RedisSessionDAO; +import org.springframework.beans.factory.annotation.Autowired; + +import com.iformall.service.MallPermissionService; + +/** + * Created by yangqj on 2017/4/30. + */ +//@Service +public class ShiroService { + @Autowired + private ShiroFilterFactoryBean shiroFilterFactoryBean; + @Autowired + private MallPermissionService resourcesService; + @Autowired + private RedisSessionDAO redisSessionDAO; + /** + * 初始化权限 + */ + public Map loadFilterChainDefinitions() { + // 权限控制map.从数据库获取 + Map filterChainDefinitionMap = new LinkedHashMap(); + filterChainDefinitionMap.put("/logout", "logout"); + filterChainDefinitionMap.put("/css/**","anon"); + filterChainDefinitionMap.put("/js/**","anon"); + filterChainDefinitionMap.put("/img/**","anon"); + filterChainDefinitionMap.put("/user/**","anon"); + filterChainDefinitionMap.put("/font-awesome/**","anon"); +// Map map = new HashMap<>(); +// List resourcesList = resourcesService.list(map); +// for(SysPermission resources:resourcesList){ +// +// if (StringUtil.isNotEmpty(resources.getUrl())) { +// String permission = "perms[" + resources.getUrl()+ "]"; +// filterChainDefinitionMap.put(resources.getUrl(),permission); +// } +// } + filterChainDefinitionMap.put("/**", "authc"); + return filterChainDefinitionMap; + } + + /** + * 重新加载权限 + */ + public void updatePermission() { + + synchronized (shiroFilterFactoryBean) { + + AbstractShiroFilter shiroFilter = null; + try { + shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean + .getObject(); + } catch (Exception e) { + throw new RuntimeException( + "get ShiroFilter from shiroFilterFactoryBean error!"); + } + + PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter + .getFilterChainResolver(); + DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver + .getFilterChainManager(); + + // 清空老的权限控制 + manager.getFilterChains().clear(); + + shiroFilterFactoryBean.getFilterChainDefinitionMap().clear(); + shiroFilterFactoryBean + .setFilterChainDefinitionMap(loadFilterChainDefinitions()); + // 重新构建生成 + Map chains = shiroFilterFactoryBean + .getFilterChainDefinitionMap(); + for (Map.Entry entry : chains.entrySet()) { + String url = entry.getKey(); + String chainDefinition = entry.getValue().trim() + .replace(" ", ""); + manager.createChain(url, chainDefinition); + } + + System.out.println("更新权限成功!!"); + } + } + + /** + * 根据userId 清除当前session存在的用户的权限缓存 + * @param userIds 已经修改了权限的userId + */ + /* public void clearUserAuthByUserId(List userIds){ + if(null == userIds || userIds.size() == 0) return ; + //获取所有session + Collection sessions = redisSessionDAO.getActiveSessions(); + //定义返回 + List list = new ArrayList(); + for (Session session:sessions){ + //获取session登录信息。 + Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + if(null != obj && obj instanceof SimplePrincipalCollection){ + //强转 + SimplePrincipalCollection spc = (SimplePrincipalCollection)obj; + //判断用户,匹配用户ID。 + obj = spc.getPrimaryPrincipal(); + if(null != obj && obj instanceof User){ + User user = (User) obj; + System.out.println("user:"+user); + //比较用户ID,符合即加入集合 + if(null != user && userIds.contains(user.getId())){ + list.add(spc); + } + } + } + } + RealmSecurityManager securityManager = + (RealmSecurityManager) SecurityUtils.getSecurityManager(); + MyShiroRealm realm = (MyShiroRealm)securityManager.getRealms().iterator().next(); + for (SimplePrincipalCollection simplePrincipalCollection : list) { + realm.clearCachedAuthorizationInfo(simplePrincipalCollection); + } + }*/ +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/shiro/UserSession.java b/mallinkTTAdmin/src/main/java/com/iformall/shiro/UserSession.java new file mode 100644 index 000000000..7d9a25e11 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/shiro/UserSession.java @@ -0,0 +1,13 @@ +package com.iformall.shiro; + +public class UserSession { + + public static String userInfo="userSession"; + + public static String userId ="userSessionId"; + + public static String tenantId ="TENANT_ID"; + + public static String parentTenantId ="PARENT_TENANT_ID"; + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/shiro/UseriFormallToken.java b/mallinkTTAdmin/src/main/java/com/iformall/shiro/UseriFormallToken.java new file mode 100644 index 000000000..04f525a73 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/shiro/UseriFormallToken.java @@ -0,0 +1,39 @@ +package com.iformall.shiro; + +import com.iformall.enums.EnumLoginType; +import org.apache.shiro.authc.UsernamePasswordToken; + +public class UseriFormallToken extends UsernamePasswordToken { + private static final long serialVersionUID = -2564928913725078138L; + + private EnumLoginType type; + + public UseriFormallToken() { + super(); + } + + public UseriFormallToken(String username, String password, EnumLoginType type, boolean rememberMe, String host) { + super(username, password, rememberMe, host); + this.type = type; + } + + /** 免密登录 */ + public UseriFormallToken(String username) { + super(username, "", false, null); + this.type = EnumLoginType.NOPASSWD; + } + /** 账号密码登录 */ + public UseriFormallToken(String username, String pwd) { + super(username, pwd, false, null); + this.type = EnumLoginType.PASSWORD; + } + + public EnumLoginType getType() { + return type; + } + + + public void setType(EnumLoginType type) { + this.type = type; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/tenant/TenantInfoImpl.java b/mallinkTTAdmin/src/main/java/com/iformall/tenant/TenantInfoImpl.java new file mode 100644 index 000000000..030d4a568 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/tenant/TenantInfoImpl.java @@ -0,0 +1,70 @@ +package com.iformall.tenant; + +import com.iformall.common.TenantThreadLocal; +import com.iformall.plugin.autoTenantId.TenantInfo; +import com.iformall.shiro.UserSession; + +import java.util.Arrays; +import java.util.List; + +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.InvalidSessionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TenantInfoImpl implements TenantInfo { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Override + public String getTenantId() { + String tenantId = null; +// try { +// //tenantId = (String) SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId); +// tenantId = TenantThreadLocal.getTenantId(); +// } catch (InvalidSessionException e) { +// logger.error("InvalidSession: " + e.getMessage()); +// } + return tenantId; + } + + @Override + public String getParentTenantId() { + String parentTenantId = null; +// try { +// //parentTenantId = (String) SecurityUtils.getSubject().getSession().getAttribute(UserSession.parentTenantId); +// parentTenantId = TenantThreadLocal.getParentTenantId(); +// } catch (InvalidSessionException e) { +// logger.error("InvalidSession: " + e.getMessage()); +// } + return parentTenantId; + } + + @Override + public boolean doTableFilter(String tableName) { + return true; + } + + @Override + public List filterTables() { + return null; + } + + @Override + public boolean doTableFilterSub(String tableName) { + return true; + } + + @Override + public List filterSubTables() { + return null; + } + + @Override + public boolean doMappedStatementFIlter(MappedStatement ms) { + + return true; + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java new file mode 100644 index 000000000..a8998d59e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java @@ -0,0 +1,119 @@ +package com.iformall.ueditor; + +import com.iformall.ueditor.define.ActionMap; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import com.iformall.ueditor.hunter.FileManager; +import com.iformall.ueditor.hunter.ImageHunter; +import com.iformall.ueditor.upload.Uploader; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +public class ActionEnter { + + private HttpServletRequest request = null; + + private String actionType = null; + + private ConfigManager configManager = null; + + public ActionEnter(ConfigManager configManager) { + this.configManager = configManager; + } + + public Object exec(HttpServletRequest request) { + this.request = request; + this.actionType = request.getParameter("action"); + String callbackName = this.request.getParameter("callback"); + + if (callbackName != null) { + + if (!validCallbackName(callbackName)) { + return new BaseState(false, AppInfo.ILLEGAL).toJSONString(); + } + + //return callbackName + "(" + this.invoke() + ");"; + return this.invoke(); + + } else { + return this.invoke(); + } + + } + + public Object invoke() { + + if (actionType == null || !ActionMap.mapping.containsKey(actionType)) { + return new BaseState(false, AppInfo.INVALID_ACTION).toJSONString(); + } + + if (this.configManager == null || !this.configManager.valid()) { + return new BaseState(false, AppInfo.CONFIG_ERROR).toJSONString(); + } + + State state = null; + + int actionCode = ActionMap.getType(this.actionType); + + Map conf = null; + + switch (actionCode) { + + case ActionMap.CONFIG: + return this.configManager.getAllConfig(); + + case ActionMap.UPLOAD_IMAGE: + case ActionMap.UPLOAD_SCRAWL: + case ActionMap.UPLOAD_VIDEO: + case ActionMap.UPLOAD_FILE: + conf = this.configManager.getConfig(actionCode); + state = new Uploader(request, conf, configManager.getMallResourceService(),configManager.getAliyunOSS()).doExec(); + break; + + case ActionMap.CATCH_IMAGE: + conf = configManager.getConfig(actionCode); + String[] list = this.request.getParameterValues((String) conf.get("fieldName")); + state = new ImageHunter(conf).capture(list); + break; + + case ActionMap.LIST_IMAGE: + case ActionMap.LIST_FILE: + conf = configManager.getConfig(actionCode); + int start = this.getStartIndex(); + state = new FileManager(conf).listFile(start); + break; + + } + + return state.toJSONString(); + + } + + public int getStartIndex() { + + String start = this.request.getParameter("start"); + + try { + return Integer.parseInt(start); + } catch (Exception e) { + return 0; + } + + } + + /** + * callback参数验证 + */ + public boolean validCallbackName(String name) { + + if (name.matches("^[a-zA-Z_]+[\\w0-9_]*$")) { + return true; + } + + return false; + + } + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java new file mode 100644 index 000000000..c71e46298 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java @@ -0,0 +1,245 @@ +package com.iformall.ueditor; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.iformall.config.AwsProperty; +import com.iformall.file.aliyun.AliyunOSS; +import com.iformall.service.MallResourceService; +import com.iformall.ueditor.define.ActionMap; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 配置管理器 + * + * @author hancong03@baidu.com + */ +public final class ConfigManager { + + private static final String configFileName = "config.json"; + private JSONObject jsonConfig = null; + // 涂鸦上传filename定义 + private final static String SCRAWL_FILE_NAME = "scrawl"; + // 远程图片抓取filename定义 + private final static String REMOTE_FILE_NAME = "remote"; + //配置信息 + private UEditorConfig uEditorConfig; + private AwsProperty awsProperty; + private MallResourceService mallResourceService; + private AliyunOSS aliyunOSS; + + /* + * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件 + */ + private ConfigManager(UEditorConfig uEditorConfig, AwsProperty awsProperty, MallResourceService mallResourceService, AliyunOSS aliyunOSS) throws IOException { + this.uEditorConfig = uEditorConfig; + this.awsProperty = awsProperty; + this.mallResourceService = mallResourceService; + this.aliyunOSS = aliyunOSS; + String configPath = uEditorConfig.getConfig(); + configPath = configPath == null || configPath.isEmpty() ? configFileName : configPath; + this.initEnv(configPath); + } + + /** + * 配置管理器构造工厂 + * + * @param uEditorConfig 配置文件 + * @return 配置管理器实例或者null + */ + public static ConfigManager getInstance(UEditorConfig uEditorConfig, AwsProperty awsProperty, MallResourceService mallResourceService, AliyunOSS aliyunOSS) { + + try { + return new ConfigManager(uEditorConfig, awsProperty, mallResourceService, aliyunOSS); + } catch (Exception e) { + System.err.println("UEditor ConfigManager load error~"); + return null; + } + + } + + public AliyunOSS getAliyunOSS() { + return aliyunOSS; + } + + public void setAliyunOSS(AliyunOSS aliyunOSS) { + this.aliyunOSS = aliyunOSS; + } + + public MallResourceService getMallResourceService() { + return mallResourceService; + } + + public void setMallResourceService(MallResourceService mallResourceService) { + this.mallResourceService = mallResourceService; + } + + // 验证配置文件加载是否正确 + public boolean valid() { + return this.jsonConfig != null; + } + + public JSONObject getAllConfig() { + + return this.jsonConfig; + + } + + public Map getConfig(int type) { + + Map conf = new HashMap(); + String savePath = null; + + try { + switch (type) { + + case ActionMap.UPLOAD_FILE: + conf.put("isBase64", "false"); + conf.put("maxSize", this.jsonConfig.getLong("fileMaxSize")); + conf.put("allowFiles", this.getArray("fileAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("fileFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("filePathFormat"); + break; + + case ActionMap.UPLOAD_IMAGE: + conf.put("isBase64", "false"); + conf.put("maxSize", this.jsonConfig.getLong("imageMaxSize")); + conf.put("allowFiles", this.getArray("imageAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("imageFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("imagePathFormat"); + break; + + case ActionMap.UPLOAD_VIDEO: + conf.put("maxSize", this.jsonConfig.getLong("videoMaxSize")); + conf.put("allowFiles", this.getArray("videoAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("videoFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("videoPathFormat"); + break; + + case ActionMap.UPLOAD_SCRAWL: + conf.put("filename", ConfigManager.SCRAWL_FILE_NAME); + conf.put("maxSize", this.jsonConfig.getLong("scrawlMaxSize")); + conf.put("fieldName", this.jsonConfig.getString("scrawlFieldName")); + conf.put("isBase64", "true"); + savePath = this.jsonConfig.getString("scrawlPathFormat"); + break; + + case ActionMap.CATCH_IMAGE: + conf.put("filename", ConfigManager.REMOTE_FILE_NAME); + conf.put("filter", this.getArray("catcherLocalDomain")); + conf.put("maxSize", this.jsonConfig.getLong("catcherMaxSize")); + conf.put("allowFiles", this.getArray("catcherAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("catcherFieldName") + "[]"); + savePath = this.jsonConfig.getString("catcherPathFormat"); + break; + + case ActionMap.LIST_IMAGE: + conf.put("allowFiles", this.getArray("imageManagerAllowFiles")); + conf.put("dir", this.jsonConfig.getString("imageManagerListPath")); + conf.put("count", this.jsonConfig.getIntValue("imageManagerListSize")); + break; + + case ActionMap.LIST_FILE: + conf.put("allowFiles", this.getArray("fileManagerAllowFiles")); + conf.put("dir", this.jsonConfig.getString("fileManagerListPath")); + conf.put("count", this.jsonConfig.getIntValue("fileManagerListSize")); + break; + + } + } catch (JSONException e) { + e.printStackTrace(); + } + + conf.put("savePath", savePath); + conf.put("rootPath", uEditorConfig.getUploadPath()); + conf.put("urlPrefix", uEditorConfig.getUrlPrefix()); + return conf; + + } + + private void initEnv(String configPath) throws IOException { + + String configContent = this.readFile(configPath); + + try { + JSONObject jsonConfig = JSON.parseObject(configContent); + //统一url访问前缀 + if (uEditorConfig.getUnified()) { + Set> entrySet = jsonConfig.entrySet(); + for (Map.Entry entry : entrySet) { + String key = entry.getKey(); + if(key.contains("UrlPrefix")) { + jsonConfig.put(key, uEditorConfig.getUrlPrefix()); + } + } + } + this.jsonConfig = jsonConfig; + } catch (Exception e) { + this.jsonConfig = null; + } + + } + + private String[] getArray(String key) throws JSONException { + + JSONArray jsonArray = this.jsonConfig.getJSONArray(key); + String[] result = new String[jsonArray.size()]; + + for (int i = 0, len = jsonArray.size(); i < len; i++) { + result[i] = jsonArray.getString(i); + } + + return result; + + } + + private String readFile(String path) throws IOException { + + StringBuilder builder = new StringBuilder(); + + try { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path); + InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8"); + BufferedReader bfReader = new BufferedReader(reader); + + String tmpContent = null; + + while ((tmpContent = bfReader.readLine()) != null) { + builder.append(tmpContent); + } + + bfReader.close(); + + } catch (UnsupportedEncodingException e) { + // 忽略 + } + + return this.filter(builder.toString()); + + } + + // 过滤输入字符串, 剔除多行注释以及替换掉反斜杠 + private String filter(String input) { + + return input.replaceAll("/\\*[\\s\\S]*?\\*/", ""); + + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/Encoder.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/Encoder.java new file mode 100644 index 000000000..7ce810b43 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/Encoder.java @@ -0,0 +1,24 @@ +package com.iformall.ueditor; + +public class Encoder { + + public static String toUnicode ( String input ) { + + StringBuilder builder = new StringBuilder(); + char[] chars = input.toCharArray(); + + for ( char ch : chars ) { + + if ( ch < 256 ) { + builder.append( ch ); + } else { + builder.append( "\\u" + Integer.toHexString( ch& 0xffff ) ); + } + + } + + return builder.toString(); + + } + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/PathFormat.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/PathFormat.java new file mode 100644 index 000000000..b388a2f2e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/PathFormat.java @@ -0,0 +1,157 @@ +package com.iformall.ueditor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PathFormat { + + private static final String TIME = "time"; + private static final String FULL_YEAR = "yyyy"; + private static final String YEAR = "yy"; + private static final String MONTH = "mm"; + private static final String DAY = "dd"; + private static final String HOUR = "hh"; + private static final String MINUTE = "ii"; + private static final String SECOND = "ss"; + private static final String RAND = "rand"; + + private static Date currentDate = null; + + public static String parse ( String input ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) ); + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + /** + * 格式化路径, 把windows路径替换成标准路径 + * @param input 待格式化的路径 + * @return 格式化后的路径 + */ + public static String format ( String input ) { + + return input.replace( "\\", "/" ); + + } + + public static String parse ( String input, String filename ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + String matchStr = null; + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matchStr = matcher.group( 1 ); + if ( matchStr.indexOf( "filename" ) != -1 ) { + filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" ); + matcher.appendReplacement(sb, filename ); + } else { + matcher.appendReplacement(sb, PathFormat.getString( matchStr ) ); + } + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + private static String getString ( String pattern ) { + + pattern = pattern.toLowerCase(); + + // time 处理 + if ( pattern.indexOf( PathFormat.TIME ) != -1 ) { + return PathFormat.getTimestamp(); + } else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) { + return PathFormat.getFullYear(); + } else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) { + return PathFormat.getYear(); + } else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) { + return PathFormat.getMonth(); + } else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) { + return PathFormat.getDay(); + } else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) { + return PathFormat.getHour(); + } else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) { + return PathFormat.getMinute(); + } else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) { + return PathFormat.getSecond(); + } else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) { + return PathFormat.getRandom( pattern ); + } + + return pattern; + + } + + private static String getTimestamp () { + return System.currentTimeMillis() + ""; + } + + private static String getFullYear () { + return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate ); + } + + private static String getYear () { + return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate ); + } + + private static String getMonth () { + return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate ); + } + + private static String getDay () { + return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate ); + } + + private static String getHour () { + return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate ); + } + + private static String getMinute () { + return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate ); + } + + private static String getSecond () { + return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate ); + } + + private static String getRandom ( String pattern ) { + + int length = 0; + pattern = pattern.split( ":" )[ 1 ].trim(); + + length = Integer.parseInt( pattern ); + + return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length ); + + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java new file mode 100644 index 000000000..8dcedbc4e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java @@ -0,0 +1,59 @@ +package com.iformall.ueditor; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Created by pangxiaofeng on 2017/9/27. + */ +@ConfigurationProperties(prefix = "ueditor") +public class UEditorConfig { + + /** + * config.json的文件存放地址 + */ + private String config; + /** + * 是否同统一上传地址:图片上传地址,视频上传地址... + */ + private boolean unified; + /** + * 文件上传路径 + */ + private String uploadPath; + /** + * 文件url前缀 + */ + private String urlPrefix; + + public String getConfig() { + return config; + } + + public void setConfig(String config) { + this.config = config; + } + + public String getUploadPath() { + return uploadPath; + } + + public void setUploadPath(String uploadPath) { + this.uploadPath = uploadPath; + } + + public String getUrlPrefix() { + return urlPrefix; + } + + public void setUrlPrefix(String urlPrefix) { + this.urlPrefix = urlPrefix; + } + + public boolean getUnified() { + return unified; + } + + public void setUnified(boolean unified) { + this.unified = unified; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java new file mode 100644 index 000000000..265425939 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java @@ -0,0 +1,42 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +/** + * 定义请求action类型 + * @author hancong03@baidu.com + * + */ +@SuppressWarnings("serial") +public final class ActionMap { + + public static final Map mapping; + // 获取配置请求 + public static final int CONFIG = 0; + public static final int UPLOAD_IMAGE = 1; + public static final int UPLOAD_SCRAWL = 2; + public static final int UPLOAD_VIDEO = 3; + public static final int UPLOAD_FILE = 4; + public static final int CATCH_IMAGE = 5; + public static final int LIST_FILE = 6; + public static final int LIST_IMAGE = 7; + + static { + mapping = new HashMap(){{ + put( "config", ActionMap.CONFIG ); + put( "uploadimage", ActionMap.UPLOAD_IMAGE ); + put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL ); + put( "uploadvideo", ActionMap.UPLOAD_VIDEO ); + put( "uploadfile", ActionMap.UPLOAD_FILE ); + put( "catchimage", ActionMap.CATCH_IMAGE ); + put( "listfile", ActionMap.LIST_FILE ); + put( "listimage", ActionMap.LIST_IMAGE ); + }}; + } + + public static int getType ( String key ) { + return ActionMap.mapping.get( key ); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java new file mode 100644 index 000000000..bfbcf3d97 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java @@ -0,0 +1,5 @@ +package com.iformall.ueditor.define; + +public enum ActionState { + UNKNOW_ERROR +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java new file mode 100644 index 000000000..a31425d6f --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java @@ -0,0 +1,77 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public final class AppInfo { + + public static final int SUCCESS = 0; + public static final int MAX_SIZE = 1; + public static final int PERMISSION_DENIED = 2; + public static final int FAILED_CREATE_FILE = 3; + public static final int IO_ERROR = 4; + public static final int NOT_MULTIPART_CONTENT = 5; + public static final int PARSE_REQUEST_ERROR = 6; + public static final int NOTFOUND_UPLOAD_DATA = 7; + public static final int NOT_ALLOW_FILE_TYPE = 8; + + public static final int INVALID_ACTION = 101; + public static final int CONFIG_ERROR = 102; + + public static final int PREVENT_HOST = 201; + public static final int CONNECTION_ERROR = 202; + public static final int REMOTE_FAIL = 203; + + public static final int NOT_DIRECTORY = 301; + public static final int NOT_EXIST = 302; + + public static final int ILLEGAL = 401; + + public static Map info = new HashMap(){{ + + put( AppInfo.SUCCESS, "SUCCESS" ); + + // 无效的Action + put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" ); + // 配置文件初始化失败 + put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" ); + // 抓取远程图片失败 + put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" ); + + // 被阻止的远程主机 + put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" ); + // 远程连接出错 + put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" ); + + // "文件大小超出限制" + put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" ); + // 权限不足, 多指写权限 + put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" ); + // 创建文件失败 + put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" ); + // IO错误 + put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" ); + // 上传表单不是multipart/form-data类型 + put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" ); + // 解析上传表单错误 + put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" ); + // 未找到上传数据 + put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" ); + // 不允许的文件类型 + put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" ); + + // 指定路径不是目录 + put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" ); + // 指定路径并不存在 + put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" ); + + // callback参数名不合法 + put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" ); + + }}; + + public static String getStateInfo ( int key ) { + return AppInfo.info.get( key ); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java new file mode 100644 index 000000000..db66dd2cc --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java @@ -0,0 +1,90 @@ +package com.iformall.ueditor.define; + +import com.iformall.ueditor.Encoder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class BaseState implements State { + + private boolean state = false; + private String info = null; + + private Map infoMap = new HashMap(); + + public BaseState () { + this.state = true; + } + + public BaseState ( boolean state ) { + this.setState( state ); + } + + public BaseState ( boolean state, String info ) { + this.setState( state ); + this.info = info; + } + + public BaseState ( boolean state, int infoCode ) { + this.setState( state ); + this.info = AppInfo.getStateInfo( infoCode ); + } + + public boolean isSuccess () { + return this.state; + } + + public void setState ( boolean state ) { + this.state = state; + } + + public void setInfo ( String info ) { + this.info = info; + } + + public void setInfo ( int infoCode ) { + this.info = AppInfo.getStateInfo( infoCode ); + } + + @Override + public String toJSONString() { + return this.toString(); + } + + public String toString () { + + String key = null; + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + Iterator iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + key = iterator.next(); + + builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" ); + + } + + builder.append( "}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public void putInfo(String name, long val) { + this.putInfo(name, val+""); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/FileType.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/FileType.java new file mode 100644 index 000000000..ebc432554 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/FileType.java @@ -0,0 +1,31 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class FileType { + + public static final String JPG = "JPG"; + + private static final Map types = new HashMap(){{ + + put( FileType.JPG, ".jpg" ); + + }}; + + public static String getSuffix ( String key ) { + return FileType.types.get( key ); + } + + /** + * 根据给定的文件名,获取其后缀信息 + * @param filename + * @return + */ + public static String getSuffixByFilename ( String filename ) { + + return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase(); + + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java new file mode 100644 index 000000000..d76bb621c --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java @@ -0,0 +1,20 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class MIMEType { + + public static final Map types = new HashMap(){{ + put( "image/gif", ".gif" ); + put( "image/jpeg", ".jpg" ); + put( "image/jpg", ".jpg" ); + put( "image/png", ".png" ); + put( "image/bmp", ".bmp" ); + }}; + + public static String getSuffix ( String mime ) { + return MIMEType.types.get( mime ); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java new file mode 100644 index 000000000..a1799cb2a --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java @@ -0,0 +1,108 @@ +package com.iformall.ueditor.define; + +import com.iformall.ueditor.Encoder; + +import java.util.*; + +/** + * 多状态集合状态 + * 其包含了多个状态的集合, 其本身自己也是一个状态 + * @author hancong03@baidu.com + * + */ +public class MultiState implements State { + + private boolean state = false; + private String info = null; + private Map intMap = new HashMap(); + private Map infoMap = new HashMap(); + private List stateList = new ArrayList(); + + public MultiState ( boolean state ) { + this.state = state; + } + + public MultiState ( boolean state, String info ) { + this.state = state; + this.info = info; + } + + public MultiState ( boolean state, int infoKey ) { + this.state = state; + this.info = AppInfo.getStateInfo( infoKey ); + } + + @Override + public boolean isSuccess() { + return this.state; + } + + public void addState ( State state ) { + stateList.add( state.toJSONString() ); + } + + /** + * 该方法调用无效果 + */ + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public String toJSONString() { + + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + // 数字转换 + Iterator iterator = this.intMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) ); + + } + + iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" ); + + } + + builder.append( ", list: [" ); + + + iterator = this.stateList.iterator(); + + while ( iterator.hasNext() ) { + + builder.append( iterator.next() + "," ); + + } + + if ( this.stateList.size() > 0 ) { + builder.deleteCharAt( builder.length() - 1 ); + } + + builder.append( " ]}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, long val) { + this.intMap.put( name, val ); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/State.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/State.java new file mode 100644 index 000000000..1a8ca2d94 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/define/State.java @@ -0,0 +1,18 @@ +package com.iformall.ueditor.define; + +/** + * 处理状态接口 + * @author hancong03@baidu.com + * + */ +public interface State { + + public boolean isSuccess(); + + public void putInfo(String name, String val); + + public void putInfo(String name, long val); + + public String toJSONString(); + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java new file mode 100644 index 000000000..a21590d60 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java @@ -0,0 +1,111 @@ +package com.iformall.ueditor.hunter; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.MultiState; +import com.iformall.ueditor.define.State; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +public class FileManager { + + private String dir = null; + private String rootPath = null; + private String[] allowFiles = null; + private int count = 0; + + public FileManager(Map conf) { + + this.rootPath = (String) conf.get("rootPath"); + this.dir = this.rootPath + (String) conf.get("dir"); + this.allowFiles = this.getAllowFiles(conf.get("allowFiles")); + this.count = (Integer) conf.get("count"); + + } + + public State listFile(int index) { + + File dir = new File(this.dir); + State state = null; + + if (!dir.exists()) { + return new BaseState(false, AppInfo.NOT_EXIST); + } + + if (!dir.isDirectory()) { + return new BaseState(false, AppInfo.NOT_DIRECTORY); + } + + Collection list = FileUtils.listFiles(dir, this.allowFiles, true); + + if (index < 0 || index > list.size()) { + state = new MultiState(true); + } else { + Object[] fileList = Arrays.copyOfRange(list.toArray(), index, index + this.count); + state = this.getState(fileList); + } + + state.putInfo("start", index); + state.putInfo("total", list.size()); + + return state; + + } + + private State getState(Object[] files) { + + MultiState state = new MultiState(true); + BaseState fileState = null; + + File file = null; + + for (Object obj : files) { + if (obj == null) { + break; + } + file = (File) obj; + fileState = new BaseState(true); + fileState.putInfo("url", PathFormat.format(this.getPath(file))); + state.addState(fileState); + } + + return state; + + } + + private String getPath(File file) { + + String path = file.getAbsolutePath(); + path = PathFormat.format(path); + return path.replace(this.rootPath, "/"); + + } + + private String[] getAllowFiles(Object fileExt) { + + String[] exts = null; + String ext = null; + + if (fileExt == null) { + return new String[0]; + } + + exts = (String[]) fileExt; + + for (int i = 0, len = exts.length; i < len; i++) { + + ext = exts[i]; + exts[i] = ext.replace(".", ""); + + } + + return exts; + + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java new file mode 100644 index 000000000..1cd68ee62 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java @@ -0,0 +1,140 @@ +package com.iformall.ueditor.hunter; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.*; +import com.iformall.ueditor.upload.StorageManager; + +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 图片抓取器 + * @author hancong03@baidu.com + * + */ +public class ImageHunter { + + private String filename = null; + private String savePath = null; + private String rootPath = null; + private List allowTypes = null; + private long maxSize = -1; + + private List filters = null; + + public ImageHunter ( Map conf ) { + + this.filename = (String)conf.get( "filename" ); + this.savePath = (String)conf.get( "savePath" ); + this.rootPath = (String)conf.get( "rootPath" ); + this.maxSize = (Long)conf.get( "maxSize" ); + this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) ); + this.filters = Arrays.asList( (String[])conf.get( "filter" ) ); + + } + + public State capture (String[] list ) { + + MultiState state = new MultiState( true ); + + for ( String source : list ) { + state.addState( captureRemoteData( source ) ); + } + + return state; + + } + + public State captureRemoteData ( String urlStr ) { + + HttpURLConnection connection = null; + URL url = null; + String suffix = null; + + try { + url = new URL( urlStr ); + + if ( !validHost( url.getHost() ) ) { + return new BaseState( false, AppInfo.PREVENT_HOST ); + } + + connection = (HttpURLConnection) url.openConnection(); + + connection.setInstanceFollowRedirects( true ); + connection.setUseCaches( true ); + + if ( !validContentState( connection.getResponseCode() ) ) { + return new BaseState( false, AppInfo.CONNECTION_ERROR ); + } + + suffix = MIMEType.getSuffix( connection.getContentType() ); + + if ( !validFileType( suffix ) ) { + return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE ); + } + + if ( !validFileSize( connection.getContentLength() ) ) { + return new BaseState( false, AppInfo.MAX_SIZE ); + } + + String savePath = this.getPath( this.savePath, this.filename, suffix ); + String physicalPath = this.rootPath + savePath; + + State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath ); + + if ( state.isSuccess() ) { + state.putInfo( "url", PathFormat.format( savePath ) ); + state.putInfo( "source", urlStr ); + } + + return state; + + } catch ( Exception e ) { + return new BaseState( false, AppInfo.REMOTE_FAIL ); + } + + } + + private String getPath ( String savePath, String filename, String suffix ) { + + return PathFormat.parse( savePath + suffix, filename ); + + } + + private boolean validHost ( String hostname ) { + try { + InetAddress ip = InetAddress.getByName(hostname); + + if (ip.isSiteLocalAddress()) { + return false; + } + } catch (UnknownHostException e) { + return false; + } + + return !filters.contains( hostname ); + + } + + private boolean validContentState ( int code ) { + + return HttpURLConnection.HTTP_OK == code; + + } + + private boolean validFileType ( String type ) { + + return this.allowTypes.contains( type ); + + } + + private boolean validFileSize ( int size ) { + return size < this.maxSize; + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java new file mode 100644 index 000000000..27b48b406 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java @@ -0,0 +1,51 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.FileType; +import com.iformall.ueditor.define.State; +import org.apache.commons.codec.binary.Base64; + +import java.util.Map; + +public final class Base64Uploader { + + public static State save(String content, Map conf) { + + byte[] data = decode(content); + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validSize(data, maxSize)) { + return new BaseState(false, AppInfo.MAX_SIZE); + } + + String suffix = FileType.getSuffix("JPG"); + + String savePath = PathFormat.parse((String) conf.get("savePath"), + (String) conf.get("filename")); + + savePath = savePath + suffix; + String physicalPath = (String) conf.get("rootPath") + savePath; + + State storageState = StorageManager.saveBinaryFile(data, physicalPath); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", ""); + } + + return storageState; + } + + private static byte[] decode(String content) { + return Base64.decodeBase64(content); + } + + private static boolean validSize(byte[] data, long length) { + return data.length <= length; + } + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java new file mode 100644 index 000000000..54e02de8e --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java @@ -0,0 +1,70 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.FileType; +import com.iformall.ueditor.define.State; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class BinaryUploader { + + public static final State save(HttpServletRequest request, Map conf) { + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + MultipartFile file = ((MultipartHttpServletRequest) request).getFile("upfile"); + try { + if (file == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + + String savePath = (String) conf.get("savePath"); + String originFileName = file.getOriginalFilename(); + String suffix = FileType.getSuffixByFilename(file.getOriginalFilename()); + + originFileName = originFileName.substring(0, + originFileName.length() - suffix.length()); + savePath = savePath + suffix; + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, originFileName); + String physicalPath = (String) conf.get("rootPath") + savePath; + + InputStream is = file.getInputStream(); + State storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("local", physicalPath); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + return storageState; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static boolean validType(String type, String[] allowTypes) { + List list = Arrays.asList(allowTypes); + + return list.contains(type); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java new file mode 100644 index 000000000..ca0cdc65b --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java @@ -0,0 +1,148 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import org.apache.commons.io.FileUtils; + +import java.io.*; + +public class StorageManager { + public static final int BUFFER_SIZE = 8192; + + public StorageManager() { + } + + public static State saveBinaryFile(byte[] data, String path) { + File file = new File(path); + + State state = valid(file); + + if (!state.isSuccess()) { + return state; + } + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file)); + bos.write(data); + bos.flush(); + bos.close(); + } catch (IOException ioe) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true, file.getAbsolutePath()); + state.putInfo("size", data.length); + state.putInfo("title", file.getName()); + return state; + } + + public static State saveFileByInputStream(InputStream is, String path, long maxSize) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[2048]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + if (tmpFile.length() > maxSize) { + tmpFile.delete(); + return new BaseState(false, AppInfo.MAX_SIZE); + } + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + public static State saveFileByInputStream(InputStream is, String path) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[2048]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static File getTmpFile() { + File tmpDir = FileUtils.getTempDirectory(); + String tmpFileName = (Math.random() * 10000 + "").replace(".", ""); + return new File(tmpDir, tmpFileName); + } + + private static State saveTmpFile(File tmpFile, String path) { + State state = null; + File targetFile = new File(path); + + if (targetFile.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + try { + FileUtils.moveFile(tmpFile, targetFile); + } catch (IOException e) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true); + state.putInfo("size", targetFile.length()); + state.putInfo("title", targetFile.getName()); + + return state; + } + + private static State valid(File file) { + File parentPath = file.getParentFile(); + + if ((!parentPath.exists()) && (!parentPath.mkdirs())) { + return new BaseState(false, AppInfo.FAILED_CREATE_FILE); + } + + if (!parentPath.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + + return new BaseState(true); + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java new file mode 100644 index 000000000..c545323ec --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java @@ -0,0 +1,92 @@ +package com.iformall.ueditor.upload; + +import com.iformall.common.ResultData; +import com.iformall.domain.po.MallResource; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.file.aliyun.AliyunOSS; +import com.iformall.service.MallResourceService; +import com.iformall.shiro.UserSession; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Map; + +public class Uploader { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private HttpServletRequest request = null; + private Map conf = null; + private MallResourceService mallResourceService = null; + + private AliyunOSS aliyunOSS; + + public Uploader(HttpServletRequest request, Map conf, MallResourceService mallResourceService, AliyunOSS aliyunOSS) { + this.request = request; + this.conf = conf; + this.mallResourceService = mallResourceService; + this.aliyunOSS = aliyunOSS; + } + + public final State doExec() { + String filedName = (String) this.conf.get("fieldName"); + State state = null; + + if ("true".equals(this.conf.get("isBase64"))) { + state = Base64Uploader.save(this.request.getParameter(filedName), + this.conf); + } else { + MultipartFile multiReq= ((MultipartHttpServletRequest) this.request).getFile("upfile"); + Session session = SecurityUtils.getSubject().getSession(); + String tenantId = (String)session.getAttribute(UserSession.tenantId); + String parentTenantId = (String)session.getAttribute(UserSession.parentTenantId); + if(StringUtils.isBlank(tenantId)){ + tenantId = parentTenantId; + parentTenantId = ""; + } + TenantEntity tenantEntity = new TenantEntity(); + tenantEntity.setTenantId(tenantId); + tenantEntity.setParentTenantId(parentTenantId); + if (StringUtils.isBlank(tenantId)) { + logger.error("TENANT is null"); + } + + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + String fileFormat = ""; + if (dot >= 0) { + fileFormat = multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } + + state = new BaseState(true); + state.putInfo("size", multiReq.getSize()); + state.putInfo("title", filedName); + + try { + + ResultData data = aliyunOSS.uploadFile(tenantEntity.getTenantId(), fileFormat, multiReq.getInputStream()); + Map map = (Map) data.data; + state.putInfo("url",map.get("url")); + + MallResource mr = new MallResource(); + mr.updateTenantInfo(tenantEntity); + mr.setBucket(map.get("bucketName")); + mr.setUrl(map.get("url")); + + mallResourceService.saveOrUpdate(mr); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + return state; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/utils/PayUtil.java b/mallinkTTAdmin/src/main/java/com/iformall/utils/PayUtil.java new file mode 100644 index 000000000..9776aad04 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/utils/PayUtil.java @@ -0,0 +1,37 @@ +package com.iformall.utils; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +import java.awt.image.BufferedImage; +import java.util.Hashtable; +import java.util.Map; + +public class PayUtil { + /** + * 根据url生成二位图片对象 + * + * @param codeUrl + * @return + * @throws WriterException + */ + public static BufferedImage getQRCodeImge(String codeUrl) throws WriterException { + Map hints = new Hashtable(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); + hints.put(EncodeHintType.CHARACTER_SET, "UTF8"); + int width = 256; + BitMatrix bitMatrix = (new MultiFormatWriter()).encode(codeUrl, BarcodeFormat.QR_CODE, width, width, hints); + BufferedImage image = new BufferedImage(width, width, 1); + for(int x = 0; x < width; ++x) { + for(int y = 0; y < width; ++y) { + image.setRGB(x, y, bitMatrix.get(x, y) ? -16777216 : -1); + } + } + + return image; + } +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/utils/ShiroUtils.java b/mallinkTTAdmin/src/main/java/com/iformall/utils/ShiroUtils.java new file mode 100644 index 000000000..02b66fc2d --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/utils/ShiroUtils.java @@ -0,0 +1,61 @@ +package com.iformall.utils; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.exception.MallinkException; +import com.iformall.shiro.UserSession; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; + +/** + * Shiro工具类 + * + * @author stormeye.wu + * @email wugq@mippoint.com + * @date 2016年11月12日 上午9:49:19 + */ +public class ShiroUtils { + + public static Session getSession() { + return SecurityUtils.getSubject().getSession(); + } + + public static Subject getSubject() { + return SecurityUtils.getSubject(); + } + + public static MallUserInfo getUserInfo() { + return (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + } + + public static Long getUserId() { + return getUserInfo().getId(); + } + + public static void setSessionAttribute(Object key, Object value) { + getSession().setAttribute(key, value); + } + + public static Object getSessionAttribute(Object key) { + return getSession().getAttribute(key); + } + + public static boolean isLogin() { + return SecurityUtils.getSubject().getPrincipal() != null; + } + + public static void logout() { + SecurityUtils.getSubject().logout(); + } + + public static String getKaptcha(String key) { + Object kaptcha = getSessionAttribute(key); + if (kaptcha == null) { + throw new MallinkException(ErrorCode.KAPCHA_NOT_VALID); + } + getSession().removeAttribute(key); + return kaptcha.toString(); + } + +} diff --git a/mallinkTTAdmin/src/main/java/com/iformall/utils/UrlCheck.java b/mallinkTTAdmin/src/main/java/com/iformall/utils/UrlCheck.java new file mode 100644 index 000000000..868116aa7 --- /dev/null +++ b/mallinkTTAdmin/src/main/java/com/iformall/utils/UrlCheck.java @@ -0,0 +1,28 @@ +package com.iformall.utils; + +/** + * @author gongbiao + */ +public class UrlCheck { + + public static boolean checkUrl(String url) { + return url.contains("awsFileUpload") + || url.contains("awsImgUpload") + || url.contains("awsFilesUpload") + || url.contains("downQrCode") + || url.contains("cimgUpload") + || url.contains("ueditor/exec") + || url.contains("/wxCUserBasicInfo/importTemplate") + || url.contains("/wxCUserBasicInfo/countByFilter") + || url.contains("/wxCUserBasicInfo/listByFilter") + || url.contains("wxMsgCallback") + || url.contains("notify") + || url.contains("pvlog") + || url.contains("/wxBillDaily/importTemplate") + || url.contains("/kwMeter/import") + || url.contains("/wxImportTemplate/importTemplate") + || url.contains("/invest/customer/importCustomer") + || url.contains("/alipay/imageUpload"); + } + +} diff --git a/mallinkTTAdmin/src/main/resources/application-dev.yml b/mallinkTTAdmin/src/main/resources/application-dev.yml new file mode 100644 index 000000000..65d5e37ea --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/application-dev.yml @@ -0,0 +1,199 @@ +spring: + profiles: + #include: aliyunRocketMQ + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://101.200.130.134:3306/mallink_tt?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true&allowMultiQueries=true + username: root + password: fm2020test + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=60000" + #jackson: + #date-format: yyyy-MM-dd HH:mm:ss + # REDIS + redis: + host: 101.200.130.134 + port: 6379 + password: iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 5 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 500 + max-wait: -1 + min-idle: 10 + + + aliyun: + sms: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + product: Dysmsapi + domain: dysmsapi.aliyuncs.com + regionId: cn-hangzhou + dateFormat: yyyyMMdd + endpointName: cn-hangzhou + + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyid: LTAI4G7ixY4AhvM35F8o3W3V + keysecret: VfWqGb83qIQrS9us45utskl8itd7ry + bucketname: formall + filehost: malinkadmin + filedomain: https://formall.oss-accelerate.aliyuncs.com + + # EMAIL + mail: + host: smtp.exmail.qq.com + username: service@iformall.com + password: jGvApygXN7wc5SzN # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + + # ROCKETMQ + rocketmq: + nameServer: 127.0.0.1:9876 + producer: + retry-times-when-send-async-failed: 0 + send-msg-timeout: 300000 + compress-msg-body-over-howmuch: 4096 + max-message-size: 4194304 + retry-another-broker-when-not-store-ok: false + retry-times-when-send-failed: 2 + # RABBITMQ + rabbitmq: + host: 101.200.130.134 + port: 5672 + username: fumao + password: f9l98 + publisher-confirms: true + publisher-returns: false + virtual-host: / + aliyunRocketmq: + accessKeyId: "LTAI4G7ixY4AhvM35F8o3W3V" + accessKeySecret: "VfWqGb83qIQrS9us45utskl8itd7ry" + groupId: "GID_P_1" + namesrvAddr: "http://MQ_INST_1796289517488555_Bcqaq2is.cn-beijing.mq-internal.aliyuncs.com:8080" + flyway: + enabled: false + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) + secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) + +#wechat: +# web: +# appId: "wxe31beafbfd8295ba" +# secret: "c689fabf3c4c9f5b6424ff2a36a26727" +# url: "https://mall.youlane.cn" +# open: +# componentAppId: "wx897e4673286c915d" +# componentSecret: "cdfdfda65c45689beb6766c4c427eed2" +# componentToken: "formall2018" +# componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" +# redis: +# host: 202.165.179.86 +# port: 6379 +# password: iF0rm@2l2ol9 +# timeout: 3600 +# expire: 1800 #30分钟 +# database: 2 +# defaultExpiration: 2592000 # 默认生命周期30天 +# jedis: +# pool: +# max-active: 100 +# max-idle: 500 +# max-wait: -1 +# min-idle: 10 + +wechat: + web: + appId: "wx091907dd0bfd3f6b" + secret: "2a2ca10738998b9ef92c1fe8a4d366a6" + url: "https://admintest.malls.iformall.com" + open: + componentAppId: wxdfc8fb4e62d6b52b + componentSecret: 98daa62b316dd6feabaad708327ce233 + componentToken: formall2018 + componentAesKey: htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN + redis: + host: 101.200.130.134 + port: 6379 + password: iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +alipay: + open: + appId: 2021002137663024 + appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCUfymV5J73QQMG52PVIGUbowkloYCO4B7TQoKbrTZf2YeYsg/To/o4PiXPMNwEUfEUU8NYQ6WwNhCd2fa1ei8WFXJUf3bfgswtBk1aOmHLeY9yoXFxIKMTQ9RcobnmBzKQZlaAPMTSr7t1QtKZKPuc2gEHGRFYKO/ZuL8gIpnsVidVtmi52yd7hzao/pI3ThLA0lreg4L3rYP5ESQZRytxIPgUQ4KI11pZxFgbe+uy28AGDYIQscSIb+SWOHPYKLvOEqqepIZ8M18w/U0lZzpzepzi/V/llekvXJ6UEf1lzl7x/4UIA3WPN1B40+NzbD/OxEGTuM0UctOG6ZTd4Te9AgMBAAECggEAPYksnHbvARspu/SrRCh2fatkIPn6Ijrxyy3mnch7neCw9i/jqxpqmF/4nxFqO0gRlRDZBHyT7p+Y5zDpsW5+kLI2fJmNkzXKkmXoLBnBaOZo8WHBdtXFfjg/iltig9Y7t+cQtXd5QK2eCwuz5dA75FXa0ywqKdRdAGY0nYZ5LpwrHVU8RXheUDCJyhKNj2+W6lIaSKDxLZU3laO1oBrv1agcy7Crd5E2ndb8O3Enga+z7wSz2h7A1BasC/Yl/Ro0Y21wLCH3s/R6qA0Paq12+WEF+xdodM7SrP43CCTVFGbC1TfEOdanJfixop8QuYsIp7pHrL925+vP4eY9RfckgQKBgQDQqLdpDzzU7Ot/L9Vc/r8d4iwXXbX8+HwVFV4oBuausgFyv8eJJpfrI+IlEoB1ubJcPpJBFqfmeYTW6/v6ioFljJAlWfFvesUVt/HszBMIOsU0Bzt7ex6WlwKOagb0q0ZPA4T0OY0K0lg0loaaaR8ZTr4ivDymaGBtTBYhslpc7QKBgQC2MBznGEc5r2dhyENvdPOR20PnXQcevGnPdqSus8m0VmDcHE72RVcckcZtwczsb3NaLSqmjAcWTn51/VFmlvhB3F34FcFTPZGq6sj7fWK8HuFq7l7mu5OzYuVr73zy9ggsUuaw10IqvvwIVxszNAF0hiRnSGH3z27CoRmz3s+8EQKBgQCK3o7atBJ3X4rIJiypbL4DhIB1uJ+jUjk6yvLUTut+fufp1+tTw0S+cS5UIAEw2Lr1G4u5F/v8rwmTBJG6SC4gSLGyui6uVBYRA1BWmedcxchzfRDAeMt9y9kesUAZ3Fe5xIzbAeZ1ulKMBVZmM+pHrJlsgr0Wv0bV1xqvqITtbQKBgBIsIGXopQoa9dvqBtfyOW1eCprkS5aEQqWf9vM6Ga90QjsSU8n6xqKh48IE57TZtQ7UnIF6TCasc66/MsRh4KdpHLJnMR5lcMc0nhF/wz5ychehaTPol+X3wlyOyc7OPah2KG6ROhdbb3ZBggQMduyxiKYIsUTvmuOtAAxR+DSRAoGADtuDzGQDOJYWiO2uuP6FpA5IJaiwlSfu3xncJVfhO8SVr6VBJFg88igbIB3w6nk/sv7j9VTXqXre9HMvp1flxaaLsdxM4HcTSALS9q6t/ajaveqte6S5kAtWx0WW8C6PtgWXHbxcD7LXARSsKLoEl2JXXyUVS/m2l/RzHBQ8GJI= + appPublicKeyCertPath: /opt/iformall/service/alipay/appCertPublicKey_2021002137663024.crt + alipayCertPath: /opt/iformall/service/alipay/alipayCertPublicKey_RSA2.crt + alipayRootCertPath: /opt/iformall/service/alipay/alipayRootCert.crt + callback: https://callbacktest.malls.iformall.com/api/alipay/notify/callback + +video: + aliyun: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + regionId: cn-beijing + + +jasypt: + encryptor: + password: oRqdnDbK5pj3eMmB + +fm: + exception: true + exception_emails: xuxiaohu@iformall.com + deploy: 1 + open: true + upload_dir: /home/test/server/uploads/ + ocr_data: /root/ocr_data/ + videoType: aliyun + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + com.iformall: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/resources/application-prod.yml b/mallinkTTAdmin/src/main/resources/application-prod.yml new file mode 100644 index 000000000..13a90a493 --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/application-prod.yml @@ -0,0 +1,154 @@ +spring: + profiles: + include: aliyunRocketMQ + # JDBC + datasource: + url: jdbc:mysql://zc349w82qvn56ftl5e64-rw4rm.rwlb.rds.aliyuncs.com:3306/mallink_tt?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&allowMultiQueries=true + username: ENC(nUefcxWYlMS/1cDxikIKwA==) + password: ENC(neToS+hzeFjgSFB/7UEl5qYnW2rUjrPq) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=60000" + # REDIS + redis: + host: r-2zeaglwf13qqmnllj5.redis.rds.aliyuncs.com + port: 6379 + password: mallone:iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + + # SMS + aliyun: + sms: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + product: Dysmsapi + domain: dysmsapi.aliyuncs.com + regionId: cn-hangzhou + dateFormat: yyyyMMdd + endpointName: cn-hangzhou + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyid: LTAI4G7ixY4AhvM35F8o3W3V + keysecret: VfWqGb83qIQrS9us45utskl8itd7ry + bucketname: formall + filehost: malinkadmin + filedomain: https://formall.oss-accelerate.aliyuncs.com + # EMAIL + mail: + host: smtp.exmail.qq.com + username: sysadministor@iformall.com # 登陆密码sysAd1231 + password: SWqPekCEmhUYuYCd # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: localhost + port: 5672 + username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) + password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) + publisher-confirms: true + publisher-returns: false + virtual-host: / + # + aliyunRocketmq: + accessKeyId: "LTAI4G7ixY4AhvM35F8o3W3V" + accessKeySecret: "VfWqGb83qIQrS9us45utskl8itd7ry" + groupId: "GID_P_1" + namesrvAddr: "http://MQ_INST_1796289517488555_Bcqaq2is.cn-beijing.mq-internal.aliyuncs.com:8080" + flyway: + enabled: false + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) + secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) + +wechat: + web: + appId: "wx9cc4ca09eb20fe03" + secret: "af1d7f7a1268022a73cb4ce0b9cf0985" + url: "https://admin.malls.iformall.com" + open: + componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) + componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) + componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) + componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) + redis: + host: r-2zeaglwf13qqmnllj5.redis.rds.aliyuncs.com + port: 6379 + password: mallone:iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +alipay: + open: + appId: 2021002137663024 + appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCUfymV5J73QQMG52PVIGUbowkloYCO4B7TQoKbrTZf2YeYsg/To/o4PiXPMNwEUfEUU8NYQ6WwNhCd2fa1ei8WFXJUf3bfgswtBk1aOmHLeY9yoXFxIKMTQ9RcobnmBzKQZlaAPMTSr7t1QtKZKPuc2gEHGRFYKO/ZuL8gIpnsVidVtmi52yd7hzao/pI3ThLA0lreg4L3rYP5ESQZRytxIPgUQ4KI11pZxFgbe+uy28AGDYIQscSIb+SWOHPYKLvOEqqepIZ8M18w/U0lZzpzepzi/V/llekvXJ6UEf1lzl7x/4UIA3WPN1B40+NzbD/OxEGTuM0UctOG6ZTd4Te9AgMBAAECggEAPYksnHbvARspu/SrRCh2fatkIPn6Ijrxyy3mnch7neCw9i/jqxpqmF/4nxFqO0gRlRDZBHyT7p+Y5zDpsW5+kLI2fJmNkzXKkmXoLBnBaOZo8WHBdtXFfjg/iltig9Y7t+cQtXd5QK2eCwuz5dA75FXa0ywqKdRdAGY0nYZ5LpwrHVU8RXheUDCJyhKNj2+W6lIaSKDxLZU3laO1oBrv1agcy7Crd5E2ndb8O3Enga+z7wSz2h7A1BasC/Yl/Ro0Y21wLCH3s/R6qA0Paq12+WEF+xdodM7SrP43CCTVFGbC1TfEOdanJfixop8QuYsIp7pHrL925+vP4eY9RfckgQKBgQDQqLdpDzzU7Ot/L9Vc/r8d4iwXXbX8+HwVFV4oBuausgFyv8eJJpfrI+IlEoB1ubJcPpJBFqfmeYTW6/v6ioFljJAlWfFvesUVt/HszBMIOsU0Bzt7ex6WlwKOagb0q0ZPA4T0OY0K0lg0loaaaR8ZTr4ivDymaGBtTBYhslpc7QKBgQC2MBznGEc5r2dhyENvdPOR20PnXQcevGnPdqSus8m0VmDcHE72RVcckcZtwczsb3NaLSqmjAcWTn51/VFmlvhB3F34FcFTPZGq6sj7fWK8HuFq7l7mu5OzYuVr73zy9ggsUuaw10IqvvwIVxszNAF0hiRnSGH3z27CoRmz3s+8EQKBgQCK3o7atBJ3X4rIJiypbL4DhIB1uJ+jUjk6yvLUTut+fufp1+tTw0S+cS5UIAEw2Lr1G4u5F/v8rwmTBJG6SC4gSLGyui6uVBYRA1BWmedcxchzfRDAeMt9y9kesUAZ3Fe5xIzbAeZ1ulKMBVZmM+pHrJlsgr0Wv0bV1xqvqITtbQKBgBIsIGXopQoa9dvqBtfyOW1eCprkS5aEQqWf9vM6Ga90QjsSU8n6xqKh48IE57TZtQ7UnIF6TCasc66/MsRh4KdpHLJnMR5lcMc0nhF/wz5ychehaTPol+X3wlyOyc7OPah2KG6ROhdbb3ZBggQMduyxiKYIsUTvmuOtAAxR+DSRAoGADtuDzGQDOJYWiO2uuP6FpA5IJaiwlSfu3xncJVfhO8SVr6VBJFg88igbIB3w6nk/sv7j9VTXqXre9HMvp1flxaaLsdxM4HcTSALS9q6t/ajaveqte6S5kAtWx0WW8C6PtgWXHbxcD7LXARSsKLoEl2JXXyUVS/m2l/RzHBQ8GJI= + appPublicKeyCertPath: /opt/iformall/service/alipay/appCertPublicKey_2021002137663024.crt + alipayCertPath: /opt/iformall/service/alipay/alipayCertPublicKey_RSA2.crt + alipayRootCertPath: /opt/iformall/service/alipay/alipayRootCert.crt + callback: https://callbacktest.malls.iformall.com/api/alipay/notify/callback + +video: + aliyun: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + regionId: cn-beijing + +fm: + exception: true + exception_emails: houtaikaifa@iformall.com + deploy: 3 + open: true + upload_dir: /root/uploads/ + ocr_data: /root/ocr_data/ + videoType: aliyun + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + com.iformall.mapper: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/resources/application-prodDetry.yml b/mallinkTTAdmin/src/main/resources/application-prodDetry.yml new file mode 100644 index 000000000..146bb43b0 --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/application-prodDetry.yml @@ -0,0 +1,145 @@ +spring: + profiles: + include: aliyunRocketMQ + # JDBC + datasource: + url: jdbc:mysql://rm-2zel9i9t555zy7lftmo.mysql.rds.aliyuncs.com:3306/mallink_tt?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&allowMultiQueries=true + username: mallone + password: m@l9oNEl20#@ + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=60000" + # REDIS + redis: + host: 101.201.103.81 + port: 6379 + password: iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + + # SMS + aliyun: + sms: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + product: Dysmsapi + domain: dysmsapi.aliyuncs.com + regionId: cn-hangzhou + dateFormat: yyyyMMdd + endpointName: cn-hangzhou + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyid: LTAI4G7ixY4AhvM35F8o3W3V + keysecret: VfWqGb83qIQrS9us45utskl8itd7ry + bucketname: formall + filehost: malinkadmin + filedomain: https://formall.oss-accelerate.aliyuncs.com + # EMAIL + mail: + host: smtp.exmail.qq.com + username: zhengfangyuan@iformall.com + password: xnydCeUzofB2h8qp # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: localhost + port: 5672 + username: admin + password: ibh2D9R3v2DEN3gk + #username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) + #password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) + publisher-confirms: true + publisher-returns: false + virtual-host: / + # + aliyunRocketmq: + accessKeyId: "LTAI4G7ixY4AhvM35F8o3W3V" + accessKeySecret: "VfWqGb83qIQrS9us45utskl8itd7ry" + groupId: "GID_P_1" + namesrvAddr: "http://MQ_INST_1796289517488555_Bcqaq2is.cn-beijing.mq-internal.aliyuncs.com:8080" + flyway: + enabled: false + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: AKIAOEHX2MJVBURWTB3Q + secret: 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 + #access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) + #secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) + +wechat: + web: + appId: "wx9cc4ca09eb20fe03" + secret: "af1d7f7a1268022a73cb4ce0b9cf0985" + url: "https://admin.malls.iformall.com" + open: + componentAppId: wx7f58f461ec1e2b4f + componentSecret: 7eb9b795606739b5526dd7f61d923f5a + componentToken: formall2018 + componentAesKey: htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN + #componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) + #componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) + #componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) + #componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) + redis: + host: 101.201.103.81 + port: 6379 + password: iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: houtaikaifa@iformall.com + deploy: 3 + open: true + upload_dir: /root/uploads/ + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + com.iformall.mapper: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/resources/application-test.yml-bak b/mallinkTTAdmin/src/main/resources/application-test.yml-bak new file mode 100644 index 000000000..1f4a5fdfe --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/application-test.yml-bak @@ -0,0 +1,113 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&allowMultiQueries=true + username: ENC(Uc0AjgkytxHHCwZrmDASWg==) + password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=60000" + # REDIS + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(TtJQE2C4cWo8CpVGMMl5hiy5eykepd96J5XjsW3Kj5fgP+6+5ctDNQ==) + password: ENC(Zh6A6kRtA2ABtH6nzdvsqQSO1/8p3mparJr8neI2BLU=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: 127.0.0.1 + port: 5672 + username: ENC(aSRr6mnSryEqzHHz1hJf1g==) + password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=) + publisher-confirms: true + publisher-returns: false + virtual-host: / + flyway: + enabled: true + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) + secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) + +wechat: + web: + appId: "wx091907dd0bfd3f6b" + secret: "2a2ca10738998b9ef92c1fe8a4d366a6" + url: "https://admintest.malls.iformall.com" + open: + componentAppId: ENC(hnH31XdNzArfMfikKgBFpqQuJUl6rVOPFFcAVyb595o=) + componentSecret: ENC(t/GUVX5L+U7LCwSvZ5WmxAnmTMrc/Uy1nljsrokuzzsBL2j6BEVnrS/n7DCdGc/G) + componentToken: ENC(gUF1m0YgCCI2IY54fX6sGLZVlCswA8tG) + componentAesKey: ENC(TYHcrIkICtfrCfGq4HW6s1b/pHf7OD2uyPN11SzJNB0acqJ/4JVX1nuljo/cAtgMG4O05TImLQc=) + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: houtaikaifa@iformall.com + deploy: 2 + open: true + upload_dir: /home/ec2-user/server/uploads/ + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + com.iformall: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/resources/application.yml b/mallinkTTAdmin/src/main/resources/application.yml new file mode 100644 index 000000000..ac85a1ef9 --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/application.yml @@ -0,0 +1,81 @@ +server: + port: 9001 + servlet: + context-path: / + +spring: + application: + name: mallink + profiles: + active: dev + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + default-property-inclusion: non_null + servlet: + multipart: + max-file-size: 20MB + max-request-size: 200MB + cache: + type: REDIS + cache-names: redis_cache #缓存的名字(可以不指定) + redis: + time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) +# rocketmq: +# nameServer: 202.165.179.86:9876 +# producer: +# retry-times-when-send-async-failed: 0 +# send-msg-timeout: 300000 +# compress-msg-body-over-howmuch: 4096 +# max-message-size: 4194304 +# retry-another-broker-when-not-store-ok: false +# retry-times-when-send-failed: 2 +# rabbitmq: +# host: 202.165.179.86 +# port: 5672 +# username: guest +# password: guest +# publisher-confirms: true +# virtual-host: / + # FLOWABLE + flowable: + async-executor-activate: false + aop: + proxy-target-class: true + auto: true + flyway: + locations: classpath:/db/migration + baseline-on-migrate: true + baseline-version: 1 + + +# MybatisPlus +mybatis-plus: + mapper-locations: classpath:mapper/*Mapper.xml + global-config: + db-config: + id-type: id_worker + field-strategy: not_null + db-type: mysql + configuration: + jdbc-type-for-null: 'null' + cache-enabled: false + call-setters-on-nulls: true + type-aliases-package: com.iformall.domain.po + type-enums-package: com.iformall.enums + +# PageHelper +pagehelper: + helperDialect: mysql + reasonable: false + supportMethodsArguments: true + params: count=countSql + offset-as-page-num: true + page-size-zero: true + row-bounds-with-count: true + +mapper: + mappers: + - com.iformall.common.CommonMapper + +version: @project.version@ diff --git a/mallinkTTAdmin/src/main/resources/config.json b/mallinkTTAdmin/src/main/resources/config.json new file mode 100644 index 000000000..f8062cf66 --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "", /* 图片访问路径前缀 */ + "imagePathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "/ueditor/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "/ueditor/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "/ueditor/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "/ueditor/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/mallinkTTAdmin/src/main/resources/logback-spring.xml b/mallinkTTAdmin/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..3a54d117d --- /dev/null +++ b/mallinkTTAdmin/src/main/resources/logback-spring.xml @@ -0,0 +1,100 @@ + + + + + + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] --%mdc{client}%msg%n + + + + + ${logPath}/trace.log + + ${logPath}/daily/trace.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + + + ${logPath}/info.log + + ${logPath}/daily/info.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + INFO + ACCEPT + DENY + + + + + ${logPath}/debug.log + + ${logPath}/daily/debug.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + DEBUG + ACCEPT + DENY + + + + + + ${logPath}/warn.log + + ${logPath}/daily/warn.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + WARN + ACCEPT + DENY + + + + + + + ${logPath}/error.log + + ${logPath}/daily/error.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mallinkTTCApi/pom.xml b/mallinkTTCApi/pom.xml new file mode 100644 index 000000000..8faff80e2 --- /dev/null +++ b/mallinkTTCApi/pom.xml @@ -0,0 +1,155 @@ + + + 4.0.0 + + mallink + com.iformall + 1.0 + + + mallinkTTCApi + + + + com.iformall + mallinkService + 1.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + ZIP + + antlr, + cn.afterturn, + ch.qos.logback, + com.alibaba, + com.amazonaws, + com.baomidou, + com.mchange, + com.fasterxml.jackson.core, + com.fasterxml.jackson.dataformat, + com.fasterxml.jackson.datatype, + com.fasterxml.jackson.module, + com.fasterxml.uuid, + com.fasterxml, + com.github.axet, + com.github.jsqlparser, + com.github.pagehelper, + com.github.ulisesbocchio, + com.github.virtuald, + com.google.code.findbugs, + com.google.code.gson, + com.google.errorprone, + com.google.guava, + com.google.protobuf, + com.google.zxing, + com.jayway.jsonpath, + com.jhlabs, + com.puppycrawl.tools, + com.rabbitmq, + com.squareup.okhttp3, + com.squareup.okio, + com.sun, + com.sun.mail, + com.thoughtworks.xstream, + com.zaxxer, + commons-beanutils, + commons-cli, + commons-codec, + commons-collections, + commons-fileupload, + commons-io, + commons-logging, + io.lettuce, + io.netty, + io.projectreactor, + io.springfox, + io.swagger, + io.undertow, + javax.activation, + javax.annotation, + javax.mail, + javax.persistence, + javax.servlet, + javax.validation, + javax.xml.bind, + javax.xml.soap, + javax.xml.ws, + joda-time, + junit, + mysql, + net.bytebuddy, + net.minidev, + net.sf.dozer, + net.sf.saxon, + ognl, + org.antlr, + org.apache.commons, + org.apache.httpcomponents, + org.apache.logging.log4j, + org.apache.poi, + org.apache.poi.wso2, + org.apache.rocketmq, + org.apache.shiro, + org.apache.tomcat.embed, + org.apache.xmlbeans, + org.aspectj, + org.assertj, + org.bouncycastle, + org.checkerframework, + org.codehaus.mojo, + org.crazycake, + org.dom4j, + org.flowable, + org.flywaydb, + org.glassfish, + org.hibernate.validator, + org.jasypt, + org.javassist, + org.jboss.logging, + org.jboss.spec.javax.annotation, + org.jboss.spec.javax.websocket, + org.jboss.xnio, + org.jdom, + org.jodd, + org.jvnet.mimepull, + org.jvnet.staxex, + org.mapstruct, + org.mockito, + org.mybatis, + org.mybatis.generator, + org.mybatis.spring.boot, + org.ow2.asm, + org.projectlombok, + org.quartz-scheduler, + org.reactivestreams, + org.reflections, + org.rocketmq.spring.boot, + org.slf4j, + org.springframework, + org.springframework.amqp, + org.springframework.boot, + org.springframework.data, + org.springframework.retry, + org.springframework.ws, + org.yaml, + redis.clients, + software.amazon.ion, + tk.mybatis, + xmlpull, + xpp3 + + + + + + \ No newline at end of file diff --git a/mallinkTTCApi/src/main/java/com/iformall/TTCApplication.java b/mallinkTTCApi/src/main/java/com/iformall/TTCApplication.java new file mode 100644 index 000000000..d2b7d46f4 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/TTCApplication.java @@ -0,0 +1,75 @@ +package com.iformall; + +import org.mybatis.spring.annotation.MapperScan; +import org.rocketmq.starter.annotation.EnableRocketMQ; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; + +/** + * @author chenkx + * @date 2017-12-26 + */ +@SpringBootApplication +@MapperScan(basePackages = {"com.iformall.mapper"}) +@EnableEncryptableProperties +@EnableRocketMQ +@EnableAspectJAutoProxy(exposeProxy = true) +public class TTCApplication { + + @Value("${fm.exception}") + private boolean fmException; + + @Value("${fm.exception_emails}") + private String fmExceptionEmails; + + @Value("${fm.open}") + private boolean fmOpen; + + @Value("${fm.upload_dir}") + private String uploadDir; + + @Value("${fm.ocr_data}") + private String ocrData; + + @Value("${fm.videoType}") + private String videoType; + + @Bean + public boolean isFmException() { + return fmException; + } + + @Bean + public String fmExceptionEmails() { + return fmExceptionEmails; + } + + @Bean + public boolean isFmOpen() { + return fmOpen; + } + + @Bean + public String fmUploadDir() { + return uploadDir; + } + + @Bean + public String ocrData() { + return ocrData; + } + + @Bean + public String videoType() { + return videoType; + } + + public static void main(String[] args) { + SpringApplication.run(TTCApplication.class, args); + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/annotation/AuthIgnore.java b/mallinkTTCApi/src/main/java/com/iformall/annotation/AuthIgnore.java new file mode 100644 index 000000000..f8d88a5a2 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/annotation/AuthIgnore.java @@ -0,0 +1,16 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +/** + * api接口,忽略Token验证 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:44 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AuthIgnore { + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/annotation/LoginUser.java b/mallinkTTCApi/src/main/java/com/iformall/annotation/LoginUser.java new file mode 100644 index 000000000..c5dc1646c --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/annotation/LoginUser.java @@ -0,0 +1,19 @@ +package com.iformall.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 登录用户信息 + * + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 20:39 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginUser { + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/annotation/RedisCache.java b/mallinkTTCApi/src/main/java/com/iformall/annotation/RedisCache.java new file mode 100644 index 000000000..185736606 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/annotation/RedisCache.java @@ -0,0 +1,53 @@ +package com.iformall.annotation; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.concurrent.TimeUnit; + + +/** + * - /api/wxCouponChannel/change + * - /api/user/userinfo + * - /api/wxBusiness/listAll + * - /api/wxCampaign/list + * - /api/mall/mallInfo + * - /api/mall/getAppIcon + * - /api/mall/getWeapNote + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface RedisCache { + + /** + * 缓存key的名称 + * @return + */ + String key() default ""; + + /** + * 自动生成key + * @return + */ + boolean autoKey() default true; + + /** + * 参数md5,解决key过长问题 + * @return + */ + boolean md5() default true ; + + /** + * key 过期日期默认60秒 + * @return + */ + int expireTime() default 60; + + /** + * 时间单位默认为秒 + * @return + */ + TimeUnit dateUnit() default TimeUnit.SECONDS; +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/annotation/TenantIgnore.java b/mallinkTTCApi/src/main/java/com/iformall/annotation/TenantIgnore.java new file mode 100644 index 000000000..2623b71e2 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/annotation/TenantIgnore.java @@ -0,0 +1,16 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +/** + * api接口,忽略Token验证 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:44 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TenantIgnore { + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/aop/RedisCacheAspect.java b/mallinkTTCApi/src/main/java/com/iformall/aop/RedisCacheAspect.java new file mode 100644 index 000000000..f001c7912 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/aop/RedisCacheAspect.java @@ -0,0 +1,161 @@ +package com.iformall.aop; + + +import com.alibaba.fastjson.JSONObject; +import com.iformall.annotation.RedisCache; +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.WxCUser; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.exception.MallinkException; +import com.iformall.service.CUserTokenService; +import com.iformall.utils.HashUtil; +import com.iformall.utils.RedisLock; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Objects; + +@Slf4j +@Aspect +@Component +public class RedisCacheAspect { + + /** + * 参数分隔符 param1|param2|param3 + **/ + private static final String DELIMITER_PARAMS = "|"; + + /** + * key 分隔符 + */ + private static final String DELIMITER_KEY = ":"; + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + @Autowired + RedisLock redisLock; + + @Autowired + private CUserTokenService cUserTokenService; + + @Pointcut("@annotation(com.iformall.annotation.RedisCache)") + public void cacheAspect() { + } + + @Around("cacheAspect()") + public Object round(ProceedingJoinPoint jp) throws Throwable { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + // 查询token信息 + //从header中获取token + String token = request.getHeader("token"); + //如果header中不存在token,则从参数中获取token + if (StringUtils.isBlank(token)) { + token = request.getParameter("token"); + } + if(StringUtils.isBlank(token) || "null".equals(token) || "undefined".equals(token)){ + token=""; + //throw new MallinkException(ErrorCode.NET_TOKEN_EMPTY.getCode(),"token为空["+token+"]"); + } + log.info("token>>>>>>>>>>>>>>>"+token); + String tenantId; + BaseCUserEntity cUser = null ; + if(StringUtils.isNotBlank(token)) { + cUser = cUserTokenService.getByToken(token); + } + if (Objects.isNull(cUser) || cUser.getExpireTime().getTime() < System.currentTimeMillis()) { + tenantId = "0"; + } else { + tenantId = cUser.getTenantId(); + } + + // 请求参数 + Object[] args = jp.getArgs(); + // 接口 返回结果 + Object result; + String redisKey; + + //得到注释的名称 + MethodSignature signature = (MethodSignature) jp.getSignature(); + //判断tag是否在用户权限中 如果存在加入参数查询 + Method method = signature.getMethod(); + RedisCache cache = method.getAnnotation(RedisCache.class) ; + if (cache.autoKey()) { + // 构建 redisKey => reqPath:tenantId:md5(param1_param2_param3) + String requestUrl = request.getRequestURI(); + // 接口路径 reqPath => /api/xxx + String reqPath = requestUrl.substring(requestUrl.indexOf("/api/")); + if (cache.md5()) { + String md5Before = StringUtils.join(args, DELIMITER_PARAMS); + redisKey = StringUtils.join(reqPath, DELIMITER_KEY, tenantId, DELIMITER_KEY, HashUtil.md5(StringUtils.join(token, md5Before, DELIMITER_PARAMS))); + } else { + redisKey = StringUtils.join(reqPath, DELIMITER_KEY, tenantId, DELIMITER_KEY, StringUtils.join(token,args, DELIMITER_PARAMS)); + } + } else { + redisKey = cache.key(); + } + + // redisKey 不存在,获取接口数据并返回 + if (StringUtils.isBlank(redisKey)) { + result = jp.proceed(args); + } else { + ValueOperations valueOperations = stringRedisTemplate.opsForValue(); + String value = valueOperations.get(redisKey); + if (value == null) { + String lockKey = StringUtils.join(redisKey, ":", "lock"); + long time = System.currentTimeMillis() + 2000; + String timeStr = String.valueOf(time); + try { + //分布式锁,保证一个线程读DB,其它线程排队 + if (redisLock.lock2(lockKey, timeStr)) { + log.debug("CacheAspect 读库中, key:{}: " + lockKey); + result = jp.proceed(args); + String json_data = JSONObject.toJSONString(result); + valueOperations.set(redisKey, json_data, cache.expireTime(), cache.dateUnit()); + log.debug("CacheAspect 缓存不存在,获取接口数据并放入缓存,key:{}, expire:{}", redisKey, cache.expireTime()); + } else { + log.debug("CacheAspect 读库等待中, key:{}: " + lockKey); + Thread.sleep(2000); + value = valueOperations.get(redisKey); + result = parseCache(jp, redisKey, value); + } + } catch (Throwable throwable) { + log.error("CacheAspect proceed error , Illegal argument: {} in {}.{}()", Arrays.toString(jp.getArgs()), + jp.getSignature().getDeclaringTypeName(), jp.getSignature().getName(), throwable); + throw throwable; + } finally { + redisLock.unlock(lockKey, timeStr); + } + } else { + result = parseCache(jp, redisKey, value); + } + // 计数器 + stringRedisTemplate.opsForHash().increment("hotapi", redisKey, 1); + } + return result; + } + + private Object parseCache(ProceedingJoinPoint jp, String redisKey, String value) { + if (StringUtils.isBlank(value)) { + log.debug("CacheAspect 缓存不存在,解析缓存数据为空:{},key:{}", value, redisKey); + return null; + } + Class returnType = ((MethodSignature) jp.getSignature()).getReturnType(); + log.debug("CacheAspect 缓存存在,解析缓存并返回,key:{}", redisKey); + return JSONObject.parseObject(value, returnType); + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/config/AwsProperty.java b/mallinkTTCApi/src/main/java/com/iformall/config/AwsProperty.java new file mode 100644 index 000000000..0329f1d6d --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/config/AwsProperty.java @@ -0,0 +1,52 @@ +package com.iformall.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author Stormeye + */ +@Component +@ConfigurationProperties(prefix = "aws") +public class AwsProperty { + // AWS ACCESS KEY + private String access; + + private String secret; + + private String clientRegion; + + private String bucketName; + + public String getAccess() { + return access; + } + + public void setAccess(String access) { + this.access = access; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getClientRegion() { + return clientRegion; + } + + public void setClientRegion(String clientRegion) { + this.clientRegion = clientRegion; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/config/MyBatisConfiguration.java b/mallinkTTCApi/src/main/java/com/iformall/config/MyBatisConfiguration.java new file mode 100644 index 000000000..3727de0a3 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/config/MyBatisConfiguration.java @@ -0,0 +1,14 @@ +package com.iformall.config; + +import com.iformall.plugin.MyBatisItercepters; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyBatisConfiguration extends BaseMyBatisConfiguration { + + @Bean + public MyBatisItercepters intercepters() { + return new MyBatisItercepters(); + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/config/RedisConfig.java b/mallinkTTCApi/src/main/java/com/iformall/config/RedisConfig.java new file mode 100644 index 000000000..02e61114a --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/config/RedisConfig.java @@ -0,0 +1,335 @@ +package com.iformall.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.pagehelper.PageInfo; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.domain.vo.WxCouponCVo; +import com.iformall.domain.vo.WxCouponChannelVo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Stormeye on 2018/10/1. + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + //缓存管理器 + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + //user信息缓存配置 + RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user"); + Map redisCacheConfigurationMap = new HashMap<>(); + redisCacheConfigurationMap.put("user", userCacheConfiguration); + //初始化一个RedisCacheWriter + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + // 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现 + // ClassLoader loader = this.getClass().getClassLoader(); + // JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader); + // RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer); + // RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); + RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); + //设置默认超过期时间是30秒 + defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); + //初始化RedisCacheManager + RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); + return cacheManager; + } + + @Bean("pushLimitRedisTemplate") + public RedisTemplate getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(PushLimit.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("scoreRuleRedisTemplate") + public RedisTemplate getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxScoreRules.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("cuserTokenRedisTemplate") + public RedisTemplate getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCUser.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("baseCUserTokenRedisTemplate") + public RedisTemplate getBaseCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(BaseCUserEntity.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("cUserBasicInfoRedisTemplate") + public RedisTemplate getCUserBasicInfoRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCUserBasicInfo.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("mallRedisTemplate") + public RedisTemplate getMallRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxMall.class); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("subMallListRedisTemplate") + public RedisTemplate> getSubMallListRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate> template = new RedisTemplate>(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(List.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("couponDetailRedisTemplate") + public RedisTemplate getCouponDetailRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCouponCVo.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("couponChannelRedisTemplate") + public RedisTemplate> getCouponChannelRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate> template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(PageInfo.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("buserTokenRedisTemplate") + public RedisTemplate getBuserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxBuser.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("pressOrderRedisTemplate") + public RedisTemplate getPressOrderRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxOrder.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + + return template; + } + + @Bean("stringValueOperations") + public ValueOperations getStringValueOperations(RedisConnectionFactory connectionFactory) { + StringRedisTemplate template = new StringRedisTemplate(); + template.setConnectionFactory(connectionFactory); + template.afterPropertiesSet(); + return template.opsForValue(); + } + + @Bean("objectCommonRedisTemplate") + public RedisTemplate getObjectValueOperations(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + j.setObjectMapper(om); + + // value值的序列化 + template.setValueSerializer(j); + template.setHashValueSerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + return template; + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/config/Swagger2Config.java b/mallinkTTCApi/src/main/java/com/iformall/config/Swagger2Config.java new file mode 100644 index 000000000..2118b9dbd --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/config/Swagger2Config.java @@ -0,0 +1,61 @@ +package com.iformall.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Parameter; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.RelativePathProvider; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import javax.servlet.ServletContext; +import java.util.ArrayList; +import java.util.List; + +//参考:http://blog.csdn.net/catoop/article/details/50668896 +@Configuration +@EnableSwagger2 +public class Swagger2Config { + + @Autowired + private ServletContext servletContext; + + @Bean + public Docket createRestApi() { + ParameterBuilder tokenPar = new ParameterBuilder(); + List pars = new ArrayList(); + //增加一个request的header参数 + tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); + pars.add(tokenPar.build()); + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.iformall.controller")) + .paths(PathSelectors.any()) + .build() + .globalOperationParameters(pars) + .pathProvider(new RelativePathProvider(servletContext) { + @Override + public String getApplicationBasePath() { + return "/api"; + } + }); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("c端 api") + .description("c api") + .termsOfServiceUrl("http://localhost:7000") + .version("2.0") + .build(); + } + +} \ No newline at end of file diff --git a/mallinkTTCApi/src/main/java/com/iformall/config/WebMvcConfig.java b/mallinkTTCApi/src/main/java/com/iformall/config/WebMvcConfig.java new file mode 100644 index 000000000..c4064057a --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/config/WebMvcConfig.java @@ -0,0 +1,114 @@ +package com.iformall.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.iformall.interceptor.AuthorizationInterceptor; +import com.iformall.interceptor.HttpServletRequestWrapperFilter; +import com.iformall.interceptor.RequestInterceptor; +import com.iformall.resolver.LoginUserHandlerMethodArgumentResolver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.*; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.List; + +/** + * MVC配置 + * + * @author stormeye.wu + * @email wugq@mippoint.com + * @date 2017-04-20 22:30 + */ +@Configuration +@EnableWebMvc +public class WebMvcConfig implements WebMvcConfigurer { + @Autowired + private AuthorizationInterceptor authorizationInterceptor; + @Autowired + private RequestInterceptor requestInterceptor; + @Autowired + private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authorizationInterceptor).addPathPatterns("/api/**"); + registry.addInterceptor(requestInterceptor).addPathPatterns("/api/**"); + } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + argumentResolvers.add(loginUserHandlerMethodArgumentResolver); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("swagger-ui.html") + .addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + //registry.addResourceHandler("/app/**").addResourceLocations("classpath:/app/"); + + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/api/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + + @Override + public void configureMessageConverters(List> converters) { + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + //ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然 + ObjectMapper objectMapper = new ObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + + //不显示为null的字段 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + DeserializationConfig dc = objectMapper.getDeserializationConfig(); + // 设置反序列化日期格式、忽略不存在get、set的属性 + objectMapper.setConfig( + dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) + .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + ); + //序列化将Long转String类型 + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + SimpleModule bigIntegerModule = new SimpleModule(); + //序列化将BigInteger转String类型 + bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance); + SimpleModule bigDecimalModule = new SimpleModule(); + //序列化将BigDecimal转String类型 + bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + objectMapper.registerModule(bigDecimalModule); + objectMapper.registerModule(bigIntegerModule); + jackson2HttpMessageConverter.setObjectMapper(objectMapper); + converters.add(jackson2HttpMessageConverter); + } + + @Bean + public FilterRegistrationBean Filters() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(new HttpServletRequestWrapperFilter()); + registrationBean.addUrlPatterns("/*"); + registrationBean.setName("koalaSignFilter"); + return registrationBean; + } +} \ No newline at end of file diff --git a/mallinkTTCApi/src/main/java/com/iformall/controller/BaseController.java b/mallinkTTCApi/src/main/java/com/iformall/controller/BaseController.java new file mode 100644 index 000000000..3d841cfbc --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/controller/BaseController.java @@ -0,0 +1,240 @@ +package com.iformall.controller; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.TtCUser; +import com.iformall.domain.po.WxAppinfo; +import com.iformall.domain.po.WxCUserBasicInfo; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.douyin.miniapp.api.TtMaService; +import com.iformall.exception.MallinkException; +import com.iformall.service.CUserTokenService; +import com.iformall.service.WxAppinfoService; +import com.iformall.service.WxCUserBasicInfoService; +import com.iformall.utils.Constant; +import com.iformall.utils.IPUtil; +import com.iformall.utils.MaUtil; +import com.iformall.utils.RedisCacheUtils; +import me.chanjar.weixin.common.error.WxErrorException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.beans.PropertyEditorSupport; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +@RestController +public class BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private CUserTokenService cUserTokenService; + + @Autowired + private WxAppinfoService wxAppinfoService; + + @Autowired + private WxCUserBasicInfoService wxCUserBasicInfoService; + + @Autowired + @Qualifier("objectCommonRedisTemplate") + RedisTemplate objectCommonRedisTemplate; + + @InitBinder + public void InitBinder(WebDataBinder dataBinder) { + dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { + public void setAsText(String value) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)); + } catch (ParseException e) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value)); + } catch (ParseException e1) { + setValue(null); + } + } + } + + public String getAsText() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue()); + } + + }); + } + + public TenantEntity getTenantInfo() { + TenantEntity tenantEntity = new TenantEntity() ; + tenantEntity.setTenantId("1"); + return tenantEntity; + } + + public TtMaService getWeappServiceByAppInfo(WxAppinfo appinfo) { + TtMaService ttMaService = MaUtil.getTtappService(appinfo); + if (StringUtils.isBlank(appinfo.getAccessToken())) { + // 如果没有accessToken,主动获取保存到数据库中,下次访问可以拿来使用 + updateAppAccessToken(appinfo, ttMaService); + + } else { + // 检查token是否已过期, 1小时就重新获取 + Date curDate = new Date(); + if (curDate.getTime() > appinfo.getLastTokenTime().getTime() + Constant.H_EXPIRE) { + updateAppAccessToken(appinfo, ttMaService); + } + } + return ttMaService; + } + + /** + * WxAppInfo更新accessToken + * + * @param wxAppinfo + * @param TtMaService + */ + private void updateAppAccessToken(WxAppinfo wxAppinfo, TtMaService TtMaService) { + try { + String accessToken = TtMaService.getAccessToken(true); + WxAppinfo updateApp = new WxAppinfo(); + updateApp.setId(wxAppinfo.getId()); + updateApp.setAccessToken(accessToken); + updateApp.setLastTokenTime(new Date()); + updateApp.setExpiresIn(7200); + wxAppinfo.setAccessToken(updateApp.getAccessToken()); + wxAppinfo.setLastTokenTime(updateApp.getLastTokenTime()); + wxAppinfo.setExpiresIn(updateApp.getExpiresIn()); + wxAppinfoService.saveOrUpdate(updateApp); + + } catch (WxErrorException e) { + logger.error(e.getMessage()); + } catch (Exception e) { + logger.error(e.getMessage()); + } + } + + /** + * 微信端获取当前用户 wx_c_user,非会员 + * 请尽量多用getTenantId, getUserId + */ + public TtCUser getTtCUser() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + BaseCUserEntity baseuser = (BaseCUserEntity) request.getAttribute(Constant.REQUEST_C_USER_KEY); + + if (baseuser == null) { + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + if (baseuser.getRealUser() == null) { + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + TtCUser user = RedisCacheUtils.getFieldObject(baseuser, "realUser", TtCUser.class); + return user; + } + + public void removeCacheCUser() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + BaseCUserEntity baseuser = (BaseCUserEntity) request.getAttribute(Constant.REQUEST_C_USER_KEY); + cUserTokenService.removeTokenCache(baseuser.getToken()); + } + + public void updateCacheCUser(String token,Object cuser) { + cUserTokenService.updateTokenCache(token, cuser); + } + + public void removeCacheMember(Long memberId) { + String key = "webapp:member:"+memberId; + RedisCacheUtils.removeCache(objectCommonRedisTemplate, key); + String shortKey = "webapp:short:member:"+memberId; + RedisCacheUtils.removeCache(objectCommonRedisTemplate, shortKey); + } + + public Long saveToBasicInfoByCUser(String userPhone,String userName,String avatarUrl,Integer sex,Long userId) { + TenantEntity tenantEntity = getTenantInfo(); + if (StringUtils.isBlank(userPhone)) + return null; + + WxCUserBasicInfo byId = null; + if (null != userId) { + byId = wxCUserBasicInfoService.getById(userId,getTenantInfo().getFinalTenantId()); + } + + WxCUserBasicInfo basicInfo = wxCUserBasicInfoService.findInfoByPhone(tenantEntity, userPhone); + + if (basicInfo != null) { + if (byId != null) { + if (!byId.getId().equals(basicInfo.getId())) { + //数据库存在此手机号的会员,并且当前微信存在另一手机号会员 + logger.error("会员" + userId + "更换手机号时,当前手机号会员表已存在:" + userPhone); + return Long.valueOf(-1); + } + } + if (!basicInfo.getTenantId().contains("," + tenantEntity.getTenantId() + ",")) { + basicInfo.setTenantId(basicInfo.getTenantId() + tenantEntity.getTenantId() + ","); + } + basicInfo.setNickName(userName); + basicInfo.setAvatarUrl(avatarUrl); + basicInfo.setSex(sex); + wxCUserBasicInfoService.update(basicInfo); + removeCacheMember(basicInfo.getId()); + return basicInfo.getId(); + } else { + if (byId != null) { + if (!byId.getTenantId().contains("," + tenantEntity.getTenantId() + ",")) { + byId.setTenantId(byId.getTenantId() + tenantEntity.getTenantId() + ","); + } + byId.setPhone(userPhone); + byId.setNickName(userName); + byId.setAvatarUrl(avatarUrl); + byId.setSex(sex); + wxCUserBasicInfoService.update(byId); + removeCacheMember(basicInfo.getId()); + return byId.getId(); + } else { + basicInfo = new WxCUserBasicInfo(); + basicInfo.setTenantId("," + tenantEntity.getTenantId() + ","); + basicInfo.setFinalTenantId(tenantEntity.getFinalTenantId()); + basicInfo.setPhone(userPhone); + basicInfo.setNickName(userName); + basicInfo.setAvatarUrl(avatarUrl); + basicInfo.setSex(sex); + wxCUserBasicInfoService.save(basicInfo); + removeCacheMember(basicInfo.getId()); + return basicInfo.getId(); + } + } + } + + public WxCUserBasicInfo getShortCacheMember(Long memberId,String finalTenantId) throws Exception { + String key = "webapp:short:member:"+memberId; + return getCacheMember(memberId,finalTenantId, key, 100); + } + + private WxCUserBasicInfo getCacheMember(Long memberId,String finalTenantId,String key,long seconds) throws MallinkException { + // 缓存 + WxCUserBasicInfo member = RedisCacheUtils.getCacheObject(objectCommonRedisTemplate, key, WxCUserBasicInfo.class); + if(null == member) { + member = wxCUserBasicInfoService.getById(memberId,finalTenantId); + if (member == null) { + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + + RedisCacheUtils.cache(objectCommonRedisTemplate, key, member, seconds); + } + return member; + } + + public String getIpAddr() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String ipaddress = IPUtil.getIpAddr(request); + return ipaddress; + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/controller/HomeController.java b/mallinkTTCApi/src/main/java/com/iformall/controller/HomeController.java new file mode 100644 index 000000000..f7be5bdd8 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/controller/HomeController.java @@ -0,0 +1,28 @@ +package com.iformall.controller; + +import com.iformall.annotation.AuthIgnore; +import com.iformall.common.ResultData; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Api(description = "") +public class HomeController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Value("${version}") + private String version; + + @AuthIgnore + @ApiOperation("获取后端版本号") + @GetMapping("/version") + public ResultData version() { + logger.debug("[" + getIpAddr() + "] HomeController::version"); + return new ResultData(version); + } +} \ No newline at end of file diff --git a/mallinkTTCApi/src/main/java/com/iformall/controller/WxUserGrantController.java b/mallinkTTCApi/src/main/java/com/iformall/controller/WxUserGrantController.java new file mode 100644 index 000000000..2184e7571 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/controller/WxUserGrantController.java @@ -0,0 +1,495 @@ +package com.iformall.controller; + +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import com.alibaba.fastjson.JSONObject; +import com.iformall.annotation.AuthIgnore; +import com.iformall.annotation.TenantIgnore; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.domain.po.*; +import com.iformall.domain.po.base.TenantEntity; +import com.iformall.domain.vo.WxCUserVo; +import com.iformall.douyin.miniapp.api.TtMaService; +import com.iformall.enums.*; +import com.iformall.service.*; +import com.iformall.utils.Constant; +import com.iformall.utils.IPUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import me.chanjar.weixin.common.error.WxErrorException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/user") +@Api(description = "用户登陆授权相关接口") +public class WxUserGrantController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private TtCUserService ttCUserService; + + @Autowired + private WxCUserBasicInfoService wxCUserBasicInfoService; + + @Autowired + private WxAppinfoService wxAppinfoService; + + /** + * 用户登录 + * + * @param map + * @return + */ + @AuthIgnore + @TenantIgnore + @PostMapping("/login") + @ApiOperation(value = "用户登录", notes = "{\"appId\":\"string\",\"code\":\"string\",\"scene\":\"string\",\"sceneAddress\":\"string\",\"latitude\":\"string\",\"longitude\":\"string\",\"systemInfo\":\"string\"}") + public ResultData userLogin(@RequestBody Map map) { + logger.info("dologin >>>>>>>>>>>>>>>>>"+map.toString()); + + Map resultMap = new HashMap(); + + String appId = map.get("appId"); + String code = map.get("code"); + + //登录凭证不能为空 + if (StringUtils.isBlank(appId)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空"); + } + if (StringUtils.isBlank(code)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "code不能为空"); + } + + WxAppinfo wxAppinfo = wxAppinfoService.getByAppId(appId); + if(wxAppinfo == null){ + return new ResultData(ErrorCode.APP_ID_NOT_FOUND); + } + if(!wxAppinfo.getEnable().equals(EnumEnableType.Enable.getCode())){ + return new ResultData(ErrorCode.APP_ID_NOT_ENABLE); + } + + TtMaService ttMaService = getWeappServiceByAppInfo(wxAppinfo); + + String token = null; + String session_key = null; + String openId = null; + String unionId = null; + + try { + WxMaJscode2SessionResult session = ttMaService.jsCode2SessionInfo(code); + logger.info("sessionResult: " + session); + if (null != session) { + logger.info("sessionResultDetail: [openid]" + session.getOpenid()+",[sessionkey]"+session.getSessionKey()+",[unionid]"+session.getUnionid()); + } + + //获取会话密钥(session_key) + session_key = session.getSessionKey(); + openId = session.getOpenid(); + unionId = session.getUnionid(); + + logger.info("session_key: " + session_key + ", openId: " + openId + ", unionId: " + unionId); + resultMap.put("openId", openId); + } catch (WxErrorException e) { + logger.error(e.getMessage(), e); + return new ResultData(ErrorCode.SESSION_KEY_DECODE_ERR, resultMap); + } + + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String ipaddress = IPUtil.getIpAddr(request); + + TtCUser newUser = new TtCUser(); + newUser.updateTenantInfo(getTenantInfo()); + newUser.setAppId(appId); + newUser.setOpenId(openId); + + TtCUser oldUser = ttCUserService.getByOpenId(newUser); + + if (oldUser != null) { + // 已有用户 + token = oldUser.createToken(new Date(),null); + resultMap.put("token", token); + + oldUser.setRegisterIp(ipaddress); + oldUser.setSessionKey(session_key); + oldUser.setAppId(appId); + oldUser.setOpenId(openId); + oldUser.setUnionId(unionId); + + oldUser.setLoginCount(oldUser.getLoginCount() + 1); + oldUser.setActiveTime(new Date()); + ttCUserService.saveOrUpdate(oldUser); + request.setAttribute(Constant.LOGIN_USER_KEY, oldUser.getId()); + + updateCacheCUser(token, oldUser); + + // 登录后处理------- + + } else { + // 新用户 + token = newUser.createToken(new Date(),null); + resultMap.put("token", token); + + newUser.setRegisterIp(ipaddress); + newUser.setSessionKey(session_key); + newUser.setLoginCount(1); + newUser.setActiveTime(new Date()); + ttCUserService.saveOrUpdate(newUser); + request.setAttribute(Constant.LOGIN_USER_KEY, newUser.getId()); + + updateCacheCUser(token, newUser); + + // 登录后处理 + + } + + if (StringUtils.isBlank(token) || "null".equals(token) || "undefined".equals(token) ) { + return new ResultData(Result.ERROR,"token无效"+token); + } + return new ResultData(resultMap); + } + + + @PostMapping("/updateScene") + @ApiOperation(value = "用户更新scene", notes = "{\"scene\":\"string\"}") + public ResultData updateScene(@RequestBody Map map) { + logger.debug(map.toString()); + + String scene = map.get("scene"); + + TtCUser user = getTtCUser(); + if (StringUtils.isBlank(user.getScene()) || + user.getScene().equalsIgnoreCase(Constant.UNDEFINED)) { + if(StringUtils.isNotBlank(scene) && scene.equalsIgnoreCase(Constant.UNDEFINED)) { + user.setScene(scene); + ttCUserService.updateScene(user); + removeCacheCUser(); + } + } + return new ResultData(); + } + + @PostMapping("/updateLBS") + @ApiOperation(value = "用户更新位置信息", notes = "{\"latitude\":\"string\",\"longitude\":\"string\"}") + public ResultData updateLBS(@RequestBody Map map) { + logger.debug(map.toString()); + + String longitude = map.get("longitude"); + String latitude = map.get("latitude"); + + TtCUser user = getTtCUser(); + if (!StringUtils.isBlank(longitude)) + user.setLongitude(BigDecimal.valueOf(Double.valueOf(longitude))); + if (!StringUtils.isBlank(latitude)) + user.setLatitude(BigDecimal.valueOf(Double.valueOf(latitude))); + ttCUserService.updateLBS(user); + removeCacheCUser(); + return new ResultData(); + } + + @PostMapping("/updateExtInfo") + @ApiOperation(value = "用户更新扩展信息(手机)", notes = "{\"systemInfo\":\"string\"}") + public ResultData updateExtInfo(@RequestBody Map map) { + logger.debug(map.toString()); + + String systemInfo = map.get("systemInfo"); + + TtCUser user = getTtCUser(); + if (StringUtils.isNotBlank(systemInfo)) { + JSONObject extraInfo = new JSONObject(); + extraInfo.put("systemInfo", JSONObject.parseObject(systemInfo)); + user.setExtraInfo(extraInfo.toJSONString()); + } + ttCUserService.updateExtInfo(user); + removeCacheCUser(); + return new ResultData(); + } + + + + /** + * 获取用户的昵称等信息 + * + * @param map + * @return + */ + @PostMapping("/getUserInfo") + @ApiOperation(value = "授权后获取用户的昵称,unionId等信息", notes = "{\"encryptedData\":\"string\",\"iv\":\"string\"}") + public ResultData getUserInfo(@RequestBody Map map) { + // signature = sha1(`${rawData}${session_key}`) 数据完整性暂不做验证 + logger.debug(map.toString()); + Map resultMap = new HashMap(); + + String encryptedData = map.get("encryptedData"); + String iv = map.get("iv"); + + if (StringUtils.isBlank(encryptedData)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData不能为空"); + } + if (StringUtils.isBlank(iv)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv不能为空"); + } + + TtCUser user = getTtCUser(); + + if (user != null) { + logger.debug(user.toString()); + WxAppinfo wxAppinfo = wxAppinfoService.getByAppId(user.getAppId()); + TtMaService ttMaService = getWeappServiceByAppInfo(wxAppinfo); + + String session_key = user.getSessionKey(); + try { + // 解密用户信息 + WxMaUserInfo userInfo = ttMaService.getUserService().getUserInfo(session_key, encryptedData, iv); + if (userInfo != null) { + logger.debug(userInfo.toString()); + TtCUser updateUser = new TtCUser(); + updateUser.setId(user.getId()); + updateUser.setUnionId(userInfo.getUnionId()); + updateUser.setNickName(userInfo.getNickName()); + updateUser.setGender(Integer.parseInt(userInfo.getGender())); + updateUser.setAvatarUrl(userInfo.getAvatarUrl()); + updateUser.setProvince(userInfo.getProvince()); + updateUser.setCity(userInfo.getCity()); + updateUser.setLanguage(userInfo.getLanguage()); + user.setUnionId(userInfo.getUnionId()); + user.setNickName(userInfo.getNickName()); + user.setGender(Integer.parseInt(userInfo.getGender())); + user.setAvatarUrl(userInfo.getAvatarUrl()); + user.setProvince(userInfo.getProvince()); + user.setCity(userInfo.getCity()); + user.setLanguage(userInfo.getLanguage()); + ttCUserService.saveOrUpdate(updateUser); + + if(user.getUserId() != null){ + WxCUserBasicInfo wxCUserBasicInfo = new WxCUserBasicInfo(); + wxCUserBasicInfo.setId(user.getUserId()); + wxCUserBasicInfo.setSex(user.getGender()); + wxCUserBasicInfo.setAvatarUrl(user.getAvatarUrl()); + wxCUserBasicInfo.setFinalTenantId(user.getFinalTenantId()); + wxCUserBasicInfoService.update(wxCUserBasicInfo); + removeCacheMember(user.getUserId()); + } + + removeCacheCUser(); + + resultMap.put("openId", user.getOpenId()); + resultMap.put("unionId", user.getUnionId()); + resultMap.put("msg", "获取用户信息成功!"); + return new ResultData(resultMap); + } else { + return new ResultData(ErrorCode.NICK_NAME_DECODE_ERR, resultMap); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + return new ResultData(ErrorCode.DB_FAIL.getCode(), "解密并保存出错", resultMap); + } + } else { + return new ResultData(ErrorCode.USER_LOGIN_FAILED); + } + } + + /** + * 授权后获取用户的手机号等信息 + * + * @param map + * @return + */ + @PostMapping("/getUserPhone") + @ApiOperation(value = "授权后获取用户的手机号", notes = "{\"encryptedData\":\"string\",\"iv\":\"string\"}") + public ResultData getUserPhone(@RequestBody Map map) { + logger.info(map.toString()); + TenantEntity tenantEntity = getTenantInfo(); + + String encryptedData = map.get("encryptedData"); + String iv = map.get("iv"); + + //登录凭证不能为空 + if (StringUtils.isBlank(encryptedData)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData 不能为空"); + } + if (StringUtils.isBlank(iv)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv 不能为空"); + } + + Map resultMap = new HashMap(); + + TtCUser user = getTtCUser(); + + if (user == null) { + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + + WxAppinfo wxAppinfo = wxAppinfoService.getByAppId(user.getAppId()); + TtMaService ttMaService = getWeappServiceByAppInfo(wxAppinfo); + + String session_key = user.getSessionKey(); + try { + // 解密 + WxMaPhoneNumberInfo phoneNoInfo = ttMaService.getUserService().getPhoneNoInfo(session_key, encryptedData, iv); + logger.info(phoneNoInfo.toString()); + if (null != phoneNoInfo) { + logger.debug(phoneNoInfo.toString()); + user.setPhone(phoneNoInfo.getPhoneNumber()); + user.setPurePhone(phoneNoInfo.getPurePhoneNumber()); + user.setCountryCode(phoneNoInfo.getCountryCode()); + + if (!user.getPhone().contains("*")) { // 用户手机非加密 + String phone = user.getPhone(); + if (phone != null && phone.contains("*")) { + phone = user.getVerifyCodePhone(); + } + // 更新到basicinfo + Long userBasicId = saveToBasicInfoByCUser(phone, user.getNickName(), user.getAvatarUrl(), user.getGender(), user.getUserId()); + if (null != userBasicId) { + if(userBasicId.intValue() == -1){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND); + } + user.setUserId(userBasicId); + }else{ + return new ResultData(ErrorCode.PHONE_DECODE_ERR, resultMap); + } + ttCUserService.saveOrUpdate(user); + ttCUserService.delForUserIdOnly(user.getId(),user.getUserId(),user.getTenantId()); + } + + removeCacheCUser(); + + resultMap.put("msg", "授权手机成功!"); + resultMap.put("phone", phoneNoInfo.getPhoneNumber()); + } else { + return new ResultData(ErrorCode.PHONE_DECODE_ERR, resultMap); + } + } catch (Exception e) { + this.logger.error(e.getMessage(), e); + return new ResultData(ErrorCode.DB_FAIL.getCode(), "解密并保存出错", resultMap); + } + + return new ResultData(resultMap); + } + + /** + * 检查微信用户状态 + * + * @return + */ + @RequestMapping("/checkWechatStatus") + @ApiOperation(value = "判断用户是否完成授权", notes = "") + public ResultData checkWechatStatus() { + Map resultMap = new HashMap(); + TtCUser user = getTtCUser(); + if (StringUtils.isNoneEmpty(user.getNickName())) { + resultMap.put("nickName", user.getNickName()); + } else { + logger.warn("用户昵称未授权,跳转到用户授权页!"); + return new ResultData(ErrorCode.NICK_NAME_NOT_FOUND.getCode(), "用户昵称未授权,请跳转到用户昵称授权页!", resultMap); + } + if (StringUtils.isNotBlank(user.getPhone())) { + resultMap.put("phone", user.getPhone()); + } else { + if (StringUtils.isBlank(user.getPhone())) { + logger.warn("用户手机号未授权,跳转到授权手机号页!"); + return new ResultData(ErrorCode.PHONE_NOT_FOUND.getCode(), "用户手机号未授权,请跳转到授权手机号页!", resultMap); + } + if (user.getPhone().contains("*")) { + logger.warn("用户手机号已加密,跳转到手工输入手机号页!"); + return new ResultData(ErrorCode.PHONE_IS_ENCRYPTED.getCode(), "用户手机号已加密,手工输入手机号页!", resultMap); + } + } + return new ResultData(Result.SUCCESS, "是老用户,已完成用户昵称/手机号授权", resultMap); + } + + /** + * 检查用户状态 + * + * @return + */ + @RequestMapping("/checkUserStatus") + @ApiOperation(value = "判断用户是否完成昵称授权", notes = "") + public ResultData checkUserStatus() { + Map resultMap = new HashMap(); + TtCUser user = getTtCUser(); + if (StringUtils.isNoneEmpty(user.getNickName())) { + resultMap.put("nickName", user.getNickName()); + } else { + logger.warn("用户昵称未授权,跳转到用户授权页!"); + return new ResultData(ErrorCode.NICK_NAME_NOT_FOUND.getCode(), "用户昵称未授权,请跳转到用户昵称授权页!", resultMap); + } + return new ResultData(Result.SUCCESS, "是老用户,已完成用户昵称授权", resultMap); + } + + /** + * 检查用户状态 + * + * @return + */ + @RequestMapping("/checkPhoneStatus") + @ApiOperation(value = "判断用户是否完成手机授权", notes = "") + public ResultData checkPhoneStatus() { + Map resultMap = new HashMap(); + TtCUser user = getTtCUser(); + if (StringUtils.isNotBlank(user.getPhone())) { + resultMap.put("phone", user.getPhone()); + } else { + if (StringUtils.isBlank(user.getPhone())) { + logger.warn("用户手机号未授权,跳转到授权手机号页!"); + return new ResultData(ErrorCode.PHONE_NOT_FOUND.getCode(), "用户手机号未授权,请跳转到授权手机号页!", resultMap); + } + if (user.getPhone().contains("*")) { + logger.warn("用户手机号已加密,跳转到手工输入手机号页!"); + return new ResultData(ErrorCode.PHONE_IS_ENCRYPTED.getCode(), "用户手机号已加密,手工输入手机号页!", resultMap); + } + } + return new ResultData(Result.SUCCESS, "是老用户,已完成手机号授权", resultMap); + } + +// @RedisCache //导致更改手机号后数据更新不及时 + @ApiOperation("获取当前用户信息") + @GetMapping("/userinfo") + public ResultData getUserInfo() { + TtCUser user = getTtCUser(); + + WxCUserVo userVo = new WxCUserVo(); + org.springframework.beans.BeanUtils.copyProperties(user, userVo); + userVo.setScore(0); + userVo.setCredit(0); + if(user.basicInfoIs()){ + WxCUserBasicInfo wxCUserBasicInfo; + try { + wxCUserBasicInfo = getShortCacheMember(user.getUserId(),getTenantInfo().getFinalTenantId()); + //WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(user.getUserId()); + if (wxCUserBasicInfo != null) { + userVo.setScore(wxCUserBasicInfo.getPoins()); + userVo.setCredit(wxCUserBasicInfo.getCredit()); + userVo.setName(wxCUserBasicInfo.getName()); + userVo.setBirthdate(wxCUserBasicInfo.getBirthdate()); + userVo.setSex(wxCUserBasicInfo.getSex()); + userVo.setAddress(wxCUserBasicInfo.getAddress()); + userVo.setStatus(wxCUserBasicInfo.getStatus()); + userVo.setChildrenList(wxCUserBasicInfo.getChildrenList()); + } + } catch (Exception e) { + logger.error("userinfo error.",e); + } + + } + + return new ResultData(userVo); + } + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java b/mallinkTTCApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java new file mode 100644 index 000000000..4b2cb33b5 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java @@ -0,0 +1,76 @@ +package com.iformall.interceptor; + + +import com.iformall.annotation.AuthIgnore; +import com.iformall.annotation.TenantIgnore; +import com.iformall.common.ErrorCode; +import com.iformall.common.TenantThreadLocal; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.exception.MallinkException; +import com.iformall.service.CUserTokenService; +import com.iformall.utils.Constant; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 权限(Token)验证 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:38 + */ +@Component +public class AuthorizationInterceptor extends HandlerInterceptorAdapter { + @Autowired + private CUserTokenService cUserTokenService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + System.out.println(" requesturi......"+request.getRequestURL()); + + AuthIgnore annotation; + if(handler instanceof HandlerMethod) { + annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class); + }else{ + return true; + } + + //如果有@IgnoreAuth注解,则不验证token + if(annotation != null){ + return true; + } + + //从header中获取token + String token = request.getHeader("token"); + //如果header中不存在token,则从参数中获取token + if(StringUtils.isBlank(token)){ + token = request.getParameter("token"); + } + + //token为空 + if(StringUtils.isBlank(token) || "null".equals(token) || "undefined".equals(token)){ + throw new MallinkException(ErrorCode.NET_TOKEN_EMPTY.getCode(),"token为空["+token+"]"); + } + + // 查询token信息 + BaseCUserEntity cUser = cUserTokenService.getByToken(token); + if(cUser == null || cUser.getExpireTime().getTime() < System.currentTimeMillis()){ + throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), "URL:" + request.getRequestURL() + " token失效,请重新登录"); + } + + //设置userId到request里,后续根据userId,获取用户信息 + request.setAttribute(Constant.LOGIN_USER_KEY, cUser.getId()); + request.setAttribute(Constant.REQUEST_C_USER_KEY, cUser); + if(cUser.basicInfoIs()){ + request.setAttribute(Constant.LOGIN_MEMBER_KEY, cUser.getUserId()); + } + + return true; + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkTTCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java new file mode 100644 index 000000000..38aec3039 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -0,0 +1,76 @@ +package com.iformall.interceptor; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.*; + +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { + private final String body; + + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + try { + InputStream inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); + char[] charBuffer = new char[1024]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + throw ex; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ex) { + throw ex; + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(body.getBytes("utf-8")); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkTTCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java new file mode 100644 index 000000000..ec4e7cb7d --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -0,0 +1,70 @@ +package com.iformall.interceptor; + +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +public class HttpServletRequestWrapperFilter implements Filter { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + logger.debug("doFilter start"); + long start = System.currentTimeMillis(); + ServletRequest requestWrapper = null; + + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + String url = ""; + if (request instanceof HttpServletRequest) { + url = ((HttpServletRequest) request).getRequestURI(); + if (!UrlCheck.checkUrl(url)) { + requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request); + } + } + if (null == requestWrapper) { + chain.doFilter(xssHttpServletRequestWrapper, response); + } else { + chain.doFilter(requestWrapper, response); + } + logger.debug("doFilter end: " + url + " "+ (System.currentTimeMillis()- start) + "ms"); + } + + @Override + public void destroy() { + + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/interceptor/RequestInterceptor.java b/mallinkTTCApi/src/main/java/com/iformall/interceptor/RequestInterceptor.java new file mode 100644 index 000000000..ff7e81880 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/interceptor/RequestInterceptor.java @@ -0,0 +1,123 @@ +package com.iformall.interceptor; + +import com.iformall.common.ErrorCode; +import com.iformall.exception.MallinkException; +import com.iformall.utils.HashUtil; +import com.iformall.utils.IPUtil; +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.util.SafeEncoder; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.concurrent.TimeUnit; + +/** + * 幂等检查 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:38 + */ +@Component +public class RequestInterceptor extends HandlerInterceptorAdapter { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + private RedisTemplate redisTemplate; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + logger.debug("preHandle start"); + if ("GET".equalsIgnoreCase(request.getMethod())) { + // 获取不检查幂等 + logger.debug("preHandle start 1"); + return true; + } + String ipaddress = IPUtil.getIpAddr(request); + String url = request.getRequestURL().toString(); + if (UrlCheck.checkUrl(url)) { + // pvlog不检查幂等 + // awsFileUpload不检查幂等 + // stopFee + return true; + } + StringBuilder sb = new StringBuilder(); + + sb.append(url); + + sb.append("method=").append(request.getMethod()).append("&"); + + sb.append("ip=").append(ipaddress).append("&"); + + final Enumeration parameterNames = request.getParameterNames(); + while (parameterNames.hasMoreElements()) { + String key = (String) parameterNames.nextElement(); + if(key.equalsIgnoreCase("ran")) // 跳过ran + continue; + String parameter = request.getParameter(key); + sb.append(key).append("=").append(parameter).append("&"); + } + + InputStream inStream = request.getInputStream(); + ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while ((len = inStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + String resultBody = new String(outSteam.toByteArray(), Charset.forName("UTF-8")); + inStream.close(); + outSteam.close(); + + sb.append(resultBody); + + String key = "request:C:" + HashUtil.md5(sb.toString()); + Boolean isAbsent = redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + RedisSerializer valueSerializer = redisTemplate.getValueSerializer(); + RedisSerializer keySerializer = redisTemplate.getKeySerializer(); + Object obj = connection.execute("set", keySerializer.serialize(key), + valueSerializer.serialize(key), + SafeEncoder.encode("NX"), + SafeEncoder.encode("EX"), + Protocol.toByteArray(3)); // 3s + return obj != null; + } + }); + if (isAbsent) { + logger.info(key + ": 第一次提交"); + logger.debug("preHandle start 2"); + return true; + } + logger.info(key + ": 第二次提交"); + logger.debug("preHandle start 3"); + throw new MallinkException(ErrorCode.SYS_REPEAT_SUBMIT_EXCEPTION); + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + logger.debug("postHandle"); + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + logger.debug("afterCompletion"); + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/interceptor/WebLogAspect.java b/mallinkTTCApi/src/main/java/com/iformall/interceptor/WebLogAspect.java new file mode 100644 index 000000000..c66aeef83 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/interceptor/WebLogAspect.java @@ -0,0 +1,72 @@ +package com.iformall.interceptor; + +import com.iformall.utils.IPUtil; +import lombok.Data; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; + +@Aspect +@Component +public class WebLogAspect { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Data + private class MethodInfo { + Long startTime; + String url; + String ip; + String method; + String classMethod; + } + + ThreadLocal startInfo = new ThreadLocal<>(); + + + @Pointcut("execution(public * com.iformall.controller..*.*(..))") + public void webLog() {} + + @Before("webLog()") + public void doBefore(JoinPoint joinPoint) throws Throwable { + logger.debug("aspect start"); + // 接收到请求,记录请求内容 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = attributes.getRequest(); + + MethodInfo info = new MethodInfo(); + info.setUrl(request.getRequestURL().toString()); + info.setStartTime(System.currentTimeMillis()); + info.setIp(IPUtil.getIpAddr(request)); + info.setMethod(request.getMethod()); + info.setClassMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); + startInfo.set(info); + logger.debug("aspect start ..."); + } + + @AfterReturning(returning = "ret", pointcut = "webLog()") + public void doAfterReturning(Object ret) throws Throwable { + logger.debug("aspect after"); + // 处理完请求,返回内容 + MethodInfo info = startInfo.get(); + StringBuilder sb = new StringBuilder(); + sb.append("URL: ").append(info.getUrl()) + .append(", METHOD: ").append(info.getMethod()) + .append(", DO: ").append(info.getClassMethod()) + .append(", IP: ").append(info.getIp()) + .append(", SPEND TIME: ").append(System.currentTimeMillis() -info.getStartTime()).append("ms"); + logger.info(sb.toString()); + logger.debug("aspect after .."); + } + + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkTTCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..1d954d163 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,125 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + if(name.equalsIgnoreCase("user-agent")) { + return super.getHeader(name); + } + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); + value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); + value = value.replaceAll("'", "& #39;"); + value = value.replaceAll("eval\\((.*)\\)", ""); + value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); + value = value.replaceAll("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/resolver/LoginUserHandlerMethodArgumentResolver.java b/mallinkTTCApi/src/main/java/com/iformall/resolver/LoginUserHandlerMethodArgumentResolver.java new file mode 100644 index 000000000..db7f5b15a --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/resolver/LoginUserHandlerMethodArgumentResolver.java @@ -0,0 +1,48 @@ +package com.iformall.resolver; + +import com.iformall.annotation.LoginUser; +import com.iformall.domain.po.WxCUserBasicInfo; +import com.iformall.domain.po.base.BaseCUserEntity; +import com.iformall.service.CUserTokenService; +import com.iformall.service.WxCUserBasicInfoService; +import com.iformall.utils.Constant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +/** + * 有@LoginUser注解的方法参数,注入当前登录用户 + * @author stormeye.wu + * @email wugq@mippoint.com + * @date 2017-03-23 22:02 + */ +@Component +public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { + + @Autowired + private WxCUserBasicInfoService wxCUserBasicInfoService; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().isAssignableFrom(BaseCUserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container, + NativeWebRequest request, WebDataBinderFactory factory) throws Exception { +// //获取会员ID +// Object object = request.getAttribute(Constant.LOGIN_MEMBER_KEY, RequestAttributes.SCOPE_REQUEST); +// if(object == null){ +// return null; +// } +// +// //WxCUserBasicInfo user = wxCUserBasicInfoService.getById((Long) object); +// return user; + return null; + } +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java b/mallinkTTCApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java new file mode 100644 index 000000000..9a12ed205 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/tenant/TenantInfoImpl.java @@ -0,0 +1,72 @@ +package com.iformall.tenant; + +import com.iformall.common.TenantThreadLocal; +import com.iformall.plugin.autoTenantId.TenantInfo; +import com.iformall.utils.Constant; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.shiro.session.InvalidSessionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Arrays; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +public class TenantInfoImpl implements TenantInfo { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Override + public String getTenantId() { + String tenantId = null; +// try { +// //tenantId = (String) SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId); +// tenantId = TenantThreadLocal.getTenantId(); +// } catch (InvalidSessionException e) { +// logger.error("InvalidSession: " + e.getMessage()); +// } + return tenantId; + } + + @Override + public String getParentTenantId() { + String parentTenantId = null; +// try { +// //parentTenantId = (String) SecurityUtils.getSubject().getSession().getAttribute(UserSession.parentTenantId); +// parentTenantId = TenantThreadLocal.getParentTenantId(); +// } catch (InvalidSessionException e) { +// logger.error("InvalidSession: " + e.getMessage()); +// } + return parentTenantId; + } + + @Override + public boolean doTableFilter(String tableName) { + return true; + } + + @Override + public List filterTables() { + return null; + } + + @Override + public boolean doTableFilterSub(String tableName) { + return true; + } + + @Override + public List filterSubTables() { + return null; + } + + @Override + public boolean doMappedStatementFIlter(MappedStatement ms) { + + return true; + } + +} diff --git a/mallinkTTCApi/src/main/java/com/iformall/utils/UrlCheck.java b/mallinkTTCApi/src/main/java/com/iformall/utils/UrlCheck.java new file mode 100644 index 000000000..e3961ad71 --- /dev/null +++ b/mallinkTTCApi/src/main/java/com/iformall/utils/UrlCheck.java @@ -0,0 +1,14 @@ +package com.iformall.utils; + +/** + * @author gongbiao + */ +public class UrlCheck { + + public static boolean checkUrl(String url) { + return url.contains("awsFileUpload") + || url.contains("awsFilesUpload") + || url.contains("getCarStopFee"); + } + +} diff --git a/mallinkTTCApi/src/main/resources/application-dev.yml b/mallinkTTCApi/src/main/resources/application-dev.yml new file mode 100644 index 000000000..57aab4bda --- /dev/null +++ b/mallinkTTCApi/src/main/resources/application-dev.yml @@ -0,0 +1,184 @@ +spring: + profiles: + #include: aliyunRocketMQ + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://101.200.130.134:3306/mallink_tt?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true + username: root + password: fm2020test + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + #jackson: + #date-format: yyyy-MM-dd HH:mm:ss + + # REDIS + redis: + host: 101.200.130.134 + port: 6379 + password: iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 5 + jedis: + pool: + max-active: 200 + max-idle: 100 + max-wait: -1 + min-idle: 0 + + # SMS + aliyun: + sms: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + product: Dysmsapi + domain: dysmsapi.aliyuncs.com + regionId: cn-hangzhou + dateFormat: yyyyMMdd + endpointName: cn-hangzhou + + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyid: LTAI4G7ixY4AhvM35F8o3W3V + keysecret: VfWqGb83qIQrS9us45utskl8itd7ry + bucketname: formall + filehost: malinkcapi + filedomain: https://formall.oss-accelerate.aliyuncs.com + + # EMAIL + mail: + host: smtp.exmail.qq.com + username: service@iformall.com + password: jGvApygXN7wc5SzN # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # ROCKETMQ + rocketmq: + nameServer: 127.0.0.1:9876 + producer: + retry-times-when-send-async-failed: 0 + send-msg-timeout: 300000 + compress-msg-body-over-howmuch: 4096 + max-message-size: 4194304 + retry-another-broker-when-not-store-ok: false + retry-times-when-send-failed: 2 + # RABBITMQ + rabbitmq: + host: 101.200.130.134 + port: 5672 + username: fumao + password: f9l98 + publisher-confirms: true + publisher-returns: false + virtual-host: / + aliyunRocketmq: + accessKeyId: "LTAI4G7ixY4AhvM35F8o3W3V" + accessKeySecret: "VfWqGb83qIQrS9us45utskl8itd7ry" + groupId: "GID_P_1" + namesrvAddr: "http://MQ_INST_1796289517488555_Bcqaq2is.cn-beijing.mq-internal.aliyuncs.com:8080" + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) + secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) + +#wechat: +# open: +# componentAppId: "wxdfc8fb4e62d6b52b" +# componentSecret: "98daa62b316dd6feabaad708327ce233" +# componentToken: "formall2018" +# componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" +# redis: +# host: 101.201.103.81 +# port: 6379 +# password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) +# timeout: 3600 +# expire: 1800 #30分钟 +# database: 2 +# defaultExpiration: 2592000 # 默认生命周期30天 +# jedis: +# pool: +# max-active: 100 +# max-idle: 500 +# max-wait: -1 +# min-idle: 10 + +wechat: + web: + appId: "wx091907dd0bfd3f6b" + secret: "2a2ca10738998b9ef92c1fe8a4d366a6" + url: "https://admintest.malls.iformall.com" + open: + componentAppId: wxdfc8fb4e62d6b52b + componentSecret: 98daa62b316dd6feabaad708327ce233 + componentToken: formall2018 + componentAesKey: htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN + redis: + host: 101.200.130.134 + port: 6379 + password: iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +alipay: + open: + appId: 2021002137663024 + appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCUfymV5J73QQMG52PVIGUbowkloYCO4B7TQoKbrTZf2YeYsg/To/o4PiXPMNwEUfEUU8NYQ6WwNhCd2fa1ei8WFXJUf3bfgswtBk1aOmHLeY9yoXFxIKMTQ9RcobnmBzKQZlaAPMTSr7t1QtKZKPuc2gEHGRFYKO/ZuL8gIpnsVidVtmi52yd7hzao/pI3ThLA0lreg4L3rYP5ESQZRytxIPgUQ4KI11pZxFgbe+uy28AGDYIQscSIb+SWOHPYKLvOEqqepIZ8M18w/U0lZzpzepzi/V/llekvXJ6UEf1lzl7x/4UIA3WPN1B40+NzbD/OxEGTuM0UctOG6ZTd4Te9AgMBAAECggEAPYksnHbvARspu/SrRCh2fatkIPn6Ijrxyy3mnch7neCw9i/jqxpqmF/4nxFqO0gRlRDZBHyT7p+Y5zDpsW5+kLI2fJmNkzXKkmXoLBnBaOZo8WHBdtXFfjg/iltig9Y7t+cQtXd5QK2eCwuz5dA75FXa0ywqKdRdAGY0nYZ5LpwrHVU8RXheUDCJyhKNj2+W6lIaSKDxLZU3laO1oBrv1agcy7Crd5E2ndb8O3Enga+z7wSz2h7A1BasC/Yl/Ro0Y21wLCH3s/R6qA0Paq12+WEF+xdodM7SrP43CCTVFGbC1TfEOdanJfixop8QuYsIp7pHrL925+vP4eY9RfckgQKBgQDQqLdpDzzU7Ot/L9Vc/r8d4iwXXbX8+HwVFV4oBuausgFyv8eJJpfrI+IlEoB1ubJcPpJBFqfmeYTW6/v6ioFljJAlWfFvesUVt/HszBMIOsU0Bzt7ex6WlwKOagb0q0ZPA4T0OY0K0lg0loaaaR8ZTr4ivDymaGBtTBYhslpc7QKBgQC2MBznGEc5r2dhyENvdPOR20PnXQcevGnPdqSus8m0VmDcHE72RVcckcZtwczsb3NaLSqmjAcWTn51/VFmlvhB3F34FcFTPZGq6sj7fWK8HuFq7l7mu5OzYuVr73zy9ggsUuaw10IqvvwIVxszNAF0hiRnSGH3z27CoRmz3s+8EQKBgQCK3o7atBJ3X4rIJiypbL4DhIB1uJ+jUjk6yvLUTut+fufp1+tTw0S+cS5UIAEw2Lr1G4u5F/v8rwmTBJG6SC4gSLGyui6uVBYRA1BWmedcxchzfRDAeMt9y9kesUAZ3Fe5xIzbAeZ1ulKMBVZmM+pHrJlsgr0Wv0bV1xqvqITtbQKBgBIsIGXopQoa9dvqBtfyOW1eCprkS5aEQqWf9vM6Ga90QjsSU8n6xqKh48IE57TZtQ7UnIF6TCasc66/MsRh4KdpHLJnMR5lcMc0nhF/wz5ychehaTPol+X3wlyOyc7OPah2KG6ROhdbb3ZBggQMduyxiKYIsUTvmuOtAAxR+DSRAoGADtuDzGQDOJYWiO2uuP6FpA5IJaiwlSfu3xncJVfhO8SVr6VBJFg88igbIB3w6nk/sv7j9VTXqXre9HMvp1flxaaLsdxM4HcTSALS9q6t/ajaveqte6S5kAtWx0WW8C6PtgWXHbxcD7LXARSsKLoEl2JXXyUVS/m2l/RzHBQ8GJI= + appPublicKeyCertPath: /opt/iformall/service/alipay/appCertPublicKey_2021002137663024.crt + alipayCertPath: /opt/iformall/service/alipay/alipayCertPublicKey_RSA2.crt + alipayRootCertPath: /opt/iformall/service/alipay/alipayRootCert.crt + callback: https://callbacktest.malls.iformall.com/api/alipay/notify/callback + +video: + aliyun: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + regionId: cn-beijing + +jasypt: + encryptor: + password: oRqdnDbK5pj3eMmB + +fm: + exception: true + exception_emails: xuxiaohu@iformall.com + deploy: 1 + open: true + upload_dir: /home/test/server/uploads/ + ocr_data: /root/ocr_data/ + videoType: aliyun + +logging: + level: + com.iformall: debug + path: ./logs/c \ No newline at end of file diff --git a/mallinkTTCApi/src/main/resources/application-prod.yml b/mallinkTTCApi/src/main/resources/application-prod.yml new file mode 100644 index 000000000..46faa5409 --- /dev/null +++ b/mallinkTTCApi/src/main/resources/application-prod.yml @@ -0,0 +1,139 @@ +spring: + profiles: + include: aliyunRocketMQ + # JDBC + datasource: + url: jdbc:mysql://zc349w82qvn56ftl5e64-rw4rm.rwlb.rds.aliyuncs.com:3306/mallink_tt?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true + username: ENC(nUefcxWYlMS/1cDxikIKwA==) + password: ENC(neToS+hzeFjgSFB/7UEl5qYnW2rUjrPq) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + # REDIS + redis: + host: r-2zeaglwf13qqmnllj5.redis.rds.aliyuncs.com + port: 6379 + password: mallone:iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + # SMS + aliyun: + sms: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + product: Dysmsapi + domain: dysmsapi.aliyuncs.com + regionId: cn-hangzhou + dateFormat: yyyyMMdd + endpointName: cn-hangzhou + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyid: LTAI4G7ixY4AhvM35F8o3W3V + keysecret: VfWqGb83qIQrS9us45utskl8itd7ry + bucketname: formall + filehost: malinkadmin + filedomain: https://formall.oss-accelerate.aliyuncs.com + + # EMAIL + mail: + host: smtp.exmail.qq.com + username: sysadministor@iformall.com # 登陆密码sysAd1231 + password: SWqPekCEmhUYuYCd # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: localhost + port: 5672 + username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) + password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) + publisher-confirms: true + publisher-returns: false + virtual-host: / + aliyunRocketmq: + accessKeyId: "LTAI4G7ixY4AhvM35F8o3W3V" + accessKeySecret: "VfWqGb83qIQrS9us45utskl8itd7ry" + groupId: "GID_P_1" + namesrvAddr: "http://MQ_INST_1796289517488555_Bcqaq2is.cn-beijing.mq-internal.aliyuncs.com:8080" +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) + secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) + +wechat: + open: + componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) + componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) + componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) + componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) + redis: + host: r-2zeaglwf13qqmnllj5.redis.rds.aliyuncs.com + port: 6379 + password: mallone:iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +alipay: + open: + appId: 2021002137663024 + appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCUfymV5J73QQMG52PVIGUbowkloYCO4B7TQoKbrTZf2YeYsg/To/o4PiXPMNwEUfEUU8NYQ6WwNhCd2fa1ei8WFXJUf3bfgswtBk1aOmHLeY9yoXFxIKMTQ9RcobnmBzKQZlaAPMTSr7t1QtKZKPuc2gEHGRFYKO/ZuL8gIpnsVidVtmi52yd7hzao/pI3ThLA0lreg4L3rYP5ESQZRytxIPgUQ4KI11pZxFgbe+uy28AGDYIQscSIb+SWOHPYKLvOEqqepIZ8M18w/U0lZzpzepzi/V/llekvXJ6UEf1lzl7x/4UIA3WPN1B40+NzbD/OxEGTuM0UctOG6ZTd4Te9AgMBAAECggEAPYksnHbvARspu/SrRCh2fatkIPn6Ijrxyy3mnch7neCw9i/jqxpqmF/4nxFqO0gRlRDZBHyT7p+Y5zDpsW5+kLI2fJmNkzXKkmXoLBnBaOZo8WHBdtXFfjg/iltig9Y7t+cQtXd5QK2eCwuz5dA75FXa0ywqKdRdAGY0nYZ5LpwrHVU8RXheUDCJyhKNj2+W6lIaSKDxLZU3laO1oBrv1agcy7Crd5E2ndb8O3Enga+z7wSz2h7A1BasC/Yl/Ro0Y21wLCH3s/R6qA0Paq12+WEF+xdodM7SrP43CCTVFGbC1TfEOdanJfixop8QuYsIp7pHrL925+vP4eY9RfckgQKBgQDQqLdpDzzU7Ot/L9Vc/r8d4iwXXbX8+HwVFV4oBuausgFyv8eJJpfrI+IlEoB1ubJcPpJBFqfmeYTW6/v6ioFljJAlWfFvesUVt/HszBMIOsU0Bzt7ex6WlwKOagb0q0ZPA4T0OY0K0lg0loaaaR8ZTr4ivDymaGBtTBYhslpc7QKBgQC2MBznGEc5r2dhyENvdPOR20PnXQcevGnPdqSus8m0VmDcHE72RVcckcZtwczsb3NaLSqmjAcWTn51/VFmlvhB3F34FcFTPZGq6sj7fWK8HuFq7l7mu5OzYuVr73zy9ggsUuaw10IqvvwIVxszNAF0hiRnSGH3z27CoRmz3s+8EQKBgQCK3o7atBJ3X4rIJiypbL4DhIB1uJ+jUjk6yvLUTut+fufp1+tTw0S+cS5UIAEw2Lr1G4u5F/v8rwmTBJG6SC4gSLGyui6uVBYRA1BWmedcxchzfRDAeMt9y9kesUAZ3Fe5xIzbAeZ1ulKMBVZmM+pHrJlsgr0Wv0bV1xqvqITtbQKBgBIsIGXopQoa9dvqBtfyOW1eCprkS5aEQqWf9vM6Ga90QjsSU8n6xqKh48IE57TZtQ7UnIF6TCasc66/MsRh4KdpHLJnMR5lcMc0nhF/wz5ychehaTPol+X3wlyOyc7OPah2KG6ROhdbb3ZBggQMduyxiKYIsUTvmuOtAAxR+DSRAoGADtuDzGQDOJYWiO2uuP6FpA5IJaiwlSfu3xncJVfhO8SVr6VBJFg88igbIB3w6nk/sv7j9VTXqXre9HMvp1flxaaLsdxM4HcTSALS9q6t/ajaveqte6S5kAtWx0WW8C6PtgWXHbxcD7LXARSsKLoEl2JXXyUVS/m2l/RzHBQ8GJI= + appPublicKeyCertPath: /opt/iformall/service/alipay/appCertPublicKey_2021002137663024.crt + alipayCertPath: /opt/iformall/service/alipay/alipayCertPublicKey_RSA2.crt + alipayRootCertPath: /opt/iformall/service/alipay/alipayRootCert.crt + callback: https://callbacktest.malls.iformall.com/api/alipay/notify/callback + +video: + aliyun: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + regionId: cn-beijing + +fm: + exception: true + exception_emails: houtaikaifa@iformall.com + deploy: 3 + open: true + upload_dir: /root/uploads/ + ocr_data: /root/ocr_data/ + videoType: aliyun + +logging: + level: + com.iformall: debug + path: ./logs/c \ No newline at end of file diff --git a/mallinkTTCApi/src/main/resources/application-prodDetry.yml b/mallinkTTCApi/src/main/resources/application-prodDetry.yml new file mode 100644 index 000000000..624217aec --- /dev/null +++ b/mallinkTTCApi/src/main/resources/application-prodDetry.yml @@ -0,0 +1,145 @@ +spring: + profiles: + include: aliyunRocketMQ + # JDBC + datasource: + url: jdbc:mysql://rm-2zel9i9t555zy7lftmo.mysql.rds.aliyuncs.com:3306/mallink_tt?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&allowMultiQueries=true + username: mallone + password: m@l9oNEl20#@ + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=60000" + # REDIS + redis: + host: r-2zeaglwf13qqmnllj5pd.redis.rds.aliyuncs.com + port: 6379 + password: mallone:iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + + # SMS + aliyun: + sms: + accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V + accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry + product: Dysmsapi + domain: dysmsapi.aliyuncs.com + regionId: cn-hangzhou + dateFormat: yyyyMMdd + endpointName: cn-hangzhou + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyid: LTAI4G7ixY4AhvM35F8o3W3V + keysecret: VfWqGb83qIQrS9us45utskl8itd7ry + bucketname: formall + filehost: malinkadmin + filedomain: https://formall.oss-accelerate.aliyuncs.com + # EMAIL + mail: + host: smtp.exmail.qq.com + username: zhengfangyuan@iformall.com + password: xnydCeUzofB2h8qp # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: localhost + port: 5672 + username: admin + password: ibh2D9R3v2DEN3gk + #username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) + #password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) + publisher-confirms: true + publisher-returns: false + virtual-host: / + # + aliyunRocketmq: + accessKeyId: "LTAI4G7ixY4AhvM35F8o3W3V" + accessKeySecret: "VfWqGb83qIQrS9us45utskl8itd7ry" + groupId: "GID_P_1" + namesrvAddr: "http://MQ_INST_1796289517488555_Bcqaq2is.cn-beijing.mq-internal.aliyuncs.com:8080" + flyway: + enabled: false + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: AKIAOEHX2MJVBURWTB3Q + secret: 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 + #access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) + #secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) + +wechat: + web: + appId: "wx9cc4ca09eb20fe03" + secret: "af1d7f7a1268022a73cb4ce0b9cf0985" + url: "https://admin.malls.iformall.com" + open: + componentAppId: wx7f58f461ec1e2b4f + componentSecret: 7eb9b795606739b5526dd7f61d923f5a + componentToken: formall2018 + componentAesKey: htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN + #componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) + #componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) + #componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) + #componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) + redis: + host: r-2zeaglwf13qqmnllj5pd.redis.rds.aliyuncs.com + port: 6379 + password: mallone:iF0rm@2l2ol9 + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: houtaikaifa@iformall.com + deploy: 3 + open: true + upload_dir: /root/uploads/ + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + com.iformall.mapper: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkTTCApi/src/main/resources/application-test.yml-bak b/mallinkTTCApi/src/main/resources/application-test.yml-bak new file mode 100644 index 000000000..e75ea2d83 --- /dev/null +++ b/mallinkTTCApi/src/main/resources/application-test.yml-bak @@ -0,0 +1,101 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true + username: ENC(Uc0AjgkytxHHCwZrmDASWg==) + password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + # REDIS + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 8 + max-idle: 8 + max-wait: -1 + min-idle: 0 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(TtJQE2C4cWo8CpVGMMl5hiy5eykepd96J5XjsW3Kj5fgP+6+5ctDNQ==) + password: ENC(Zh6A6kRtA2ABtH6nzdvsqQSO1/8p3mparJr8neI2BLU=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: 127.0.0.1 + port: 5672 + username: ENC(aSRr6mnSryEqzHHz1hJf1g==) + password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=) + publisher-confirms: true + publisher-returns: false + virtual-host: / + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) + secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) + +wechat: + open: + componentAppId: ENC(hnH31XdNzArfMfikKgBFpqQuJUl6rVOPFFcAVyb595o=) + componentSecret: ENC(t/GUVX5L+U7LCwSvZ5WmxAnmTMrc/Uy1nljsrokuzzsBL2j6BEVnrS/n7DCdGc/G) + componentToken: ENC(gUF1m0YgCCI2IY54fX6sGLZVlCswA8tG) + componentAesKey: ENC(TYHcrIkICtfrCfGq4HW6s1b/pHf7OD2uyPN11SzJNB0acqJ/4JVX1nuljo/cAtgMG4O05TImLQc=) + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: houtaikaifa@iformall.com + deploy: 2 + open: true + upload_dir: /home/ec2-user/server/uploads/ + ocr_data: /home/ec2-user/server/ocr_data/ + +logging: + level: + com.iformall: debug + path: ./logs/c \ No newline at end of file diff --git a/mallinkTTCApi/src/main/resources/application.yml b/mallinkTTCApi/src/main/resources/application.yml new file mode 100644 index 000000000..ecdd64011 --- /dev/null +++ b/mallinkTTCApi/src/main/resources/application.yml @@ -0,0 +1,54 @@ +server: + port: 7001 + servlet: + context-path: /tt + +spring: + application: + name: mallink + profiles: + active: dev + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + default-property-inclusion: non_null +# rocketmq: +# nameServer: 127.0.0.1:9876 +# producer: +# retry-times-when-send-async-failed: 0 +# send-msg-timeout: 300000 +# compress-msg-body-over-howmuch: 4096 +# max-message-size: 4194304 +# retry-another-broker-when-not-store-ok: false +# retry-times-when-send-failed: 2 + +# MybatisPlus +mybatis-plus: + mapper-locations: classpath:mapper/*Mapper.xml + global-config: + db-config: + id-type: id_worker + field-strategy: not_null + db-type: mysql + configuration: + jdbc-type-for-null: 'null' + cache-enabled: false + call-setters-on-nulls: true + type-aliases-package: com.iformall.domain.po + type-enums-package: com.iformall.enums + +# PageHelper +pagehelper: + helperDialect: mysql + reasonable: false + supportMethodsArguments: true + params: count=countSql + offset-as-page-num: true + page-size-zero: true + row-bounds-with-count: true + +mapper: + mappers: + - com.iformall.common.CommonMapper + +version: @project.version@ \ No newline at end of file diff --git a/mallinkTTCApi/src/main/resources/logback-spring.xml b/mallinkTTCApi/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..3a54d117d --- /dev/null +++ b/mallinkTTCApi/src/main/resources/logback-spring.xml @@ -0,0 +1,100 @@ + + + + + + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] --%mdc{client}%msg%n + + + + + ${logPath}/trace.log + + ${logPath}/daily/trace.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + + + ${logPath}/info.log + + ${logPath}/daily/info.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + INFO + ACCEPT + DENY + + + + + ${logPath}/debug.log + + ${logPath}/daily/debug.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + DEBUG + ACCEPT + DENY + + + + + + ${logPath}/warn.log + + ${logPath}/daily/warn.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + WARN + ACCEPT + DENY + + + + + + + ${logPath}/error.log + + ${logPath}/daily/error.%d{yyyy-MM-dd}.log + 30 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5a1185622..3c75506eb 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,9 @@ mallinkSchedule mallinkMQConsumer mallinkWebSocketServer - mallinkPublicApi + mallinkPublicApi + mallinkTTCApi + mallinkTTAdmin