Commit 45a240ff authored by shihuajun's avatar shihuajun

资金路由第一版提交代码

parent 07de323a
......@@ -372,5 +372,10 @@
<artifactId>aviator</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.3</version>
</dependency>
</dependencies>
</project>
package com.quantgroup.asset.distribution.config.code;
import lombok.Data;
import java.io.Serializable;
/**
* @author :hongzhi
*/
@Data
public class AreaCode implements Serializable {
private String adcode;
private String lng;
private String lat;
private String name;
private String level;
private String parent;
private String country;
@Override
public String toString() {
return "AreaCode{" +
"adcode='" + adcode + '\'' +
", lng='" + lng + '\'' +
", lat='" + lat + '\'' +
", name='" + name + '\'' +
", level='" + level + '\'' +
", parent='" + parent + '\'' +
", country='" + country + '\'' +
'}';
}
}
package com.quantgroup.asset.distribution.config.code;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author :hongzhi
*/
@Data
public class AreaCodeList implements Serializable {
private List<AreaCode> list;
}
package com.quantgroup.asset.distribution.config.code;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Data
public class InitAreaCode {
private Logger logger= LoggerFactory.getLogger(this.getClass());
public ConcurrentHashMap<String,AreaCode> concurrentHashMap=new ConcurrentHashMap<String,AreaCode>();
public ConcurrentHashMap<String,AreaCode> concurrentNameHashMap=new ConcurrentHashMap<String,AreaCode>();
@PostConstruct
public void init() throws Exception{
logger.info("初始化区域码");
InputStream in = this.getClass().getResourceAsStream("phone/gbt.txt");
String var4 = getString(in);
List<AreaCode> list = new ArrayList<AreaCode>();
list = JSONObject.parseArray(var4, AreaCode.class);
for(AreaCode code:list){
concurrentHashMap.put(code.getAdcode(),code);
concurrentNameHashMap.put(code.getName(),code);
}
logger.info("初始化区域码end:code{},name{}",concurrentHashMap.size(),concurrentNameHashMap.size());
}
private static String getString(InputStream in) throws IOException {
Throwable var3 = null;
String var4;
try {
var4 = IOUtils.toString(in, Charsets.toCharset(StandardCharsets.UTF_8));
} catch (Throwable var13) {
var3 = var13;
throw var13;
} finally {
if (in != null) {
if (var3 != null) {
try {
in.close();
} catch (Throwable var12) {
var3.addSuppressed(var12);
}
} else {
in.close();
}
}
}
return var4;
}
public static void main(String[] args) throws Exception {
// URL url = InitAreaCode.class.getClassLoader().getResource("gbt.txt");
// String content = FileUtils.readFileToString(new File(url.getPath()), StandardCharsets.UTF_8);
// System.out.println(content);
InputStream in = InitAreaCode.class.getClass().getResourceAsStream("/gbt.txt");
String var4 = getString(in);
System.out.println(var4);
List<AreaCode> list = new ArrayList<AreaCode>();
list = JSONObject.parseArray(var4, AreaCode.class);
}
}
......@@ -17,8 +17,8 @@ public enum MiddleOfficeCommonResponseEnum {
AUTH_ERROR("401", "权限校验失败"),
// 402-流量限制, 请求频繁
REQUEST_LIMIT("402", "请求次数过多"),
// 403-参数错误
REQUEST_PARAMS_ERROR("403", "参数有误"),
// 400-参数错误
REQUEST_PARAMS_ERROR("400", "参数有误"),
// 404-请求地址错误
REQUEST_URL_ERROR("404", "请求地址错误"),
// 405-并发错误, 客户端在一定维度单线程调用
......
package com.quantgroup.asset.distribution.exception;
import com.quantgroup.asset.distribution.enums.response.MiddleOfficeCommonResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
/**
* 全局异常捕获
*
......@@ -25,4 +26,12 @@ public class GlobalControllerHandler {
log.error("系统出现异常, ", ex);
return new GlobalResponse(QGException.wrap(ex));
}
@ExceptionHandler(BindException.class)
@ResponseBody
public GlobalResponse handleMissingServletRequestParameter(BindException ex) {
log.error("参数有问题, ", ex);
return GlobalResponse.create(MiddleOfficeCommonResponseEnum.REQUEST_PARAMS_ERROR);
}
}
......@@ -79,9 +79,9 @@ public enum QGExceptionType {
USER_OCR_INFO_IS_EMPTY(3019, "用户OCR信息为空, uuid : %s"),
LIVE_DATA_ERROR(3020, "活体数据获取失败, uuid : %s"),
USER_LOAN_TYPE_IS_EMPTY(3021, "用户类型为空, uuid : %s");
USER_LOAN_TYPE_IS_EMPTY(3021, "用户类型为空, uuid : %s"),
NOTIFY_BIZ_ERROR(4005, "通知业务系统出错");
public int code;
......
......@@ -4,6 +4,8 @@ import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import com.google.common.base.Strings;
import com.quantgroup.asset.distribution.enums.response.MiddleOfficeCommonResponseEnum;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
......@@ -61,6 +63,10 @@ public class GlobalResponse {
public static GlobalResponse create(GlobalResponseEnum responseEnum) {
return new GlobalResponse(responseEnum.getCode(), responseEnum.getBusinessCode(), responseEnum.getMsg(), responseEnum.getBody());
}
public static GlobalResponse create(MiddleOfficeCommonResponseEnum responseEnum) {
return new GlobalResponse(Integer.parseInt(responseEnum.getCode()), Strings.padStart(responseEnum.getCode(), 6, '0') , responseEnum.getMsg(),null);
}
public static GlobalResponse create(GlobalResponseEnum responseEnum, Object object) {
return new GlobalResponse(responseEnum.getCode(), responseEnum.getBusinessCode(), responseEnum.getMsg(), object);
......
package com.quantgroup.asset.distribution.service.alarm;
public interface DingTalkMessage {
/**
* 返回消息的Json格式字符串
*
* @return 消息的Json格式字符串
*/
Object toJsonString();
/**
* 返回@All的字符串
*
* @return
*/
Object toJsonStringWithAlert();
}
......@@ -14,5 +14,7 @@ public interface IAlarmService {
* @param msgTitle
* @param msgContent
*/
public void dingtalkAlarm(String alarmLevel, String msgTitle, String msgContent);
void dingtalkAlarm(String alarmLevel, String msgTitle, String msgContent);
void sendMsgWithAlert(DingTalkMessage dingTalkMessage);
}
......@@ -3,6 +3,8 @@ package com.quantgroup.asset.distribution.service.alarm.impl;
import java.util.HashMap;
import java.util.Map;
import cn.quantgroup.tech.util.TechEnvironment;
import com.quantgroup.asset.distribution.service.alarm.DingTalkMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
......@@ -24,6 +26,8 @@ public class AlarmServiceImpl implements IAlarmService{
private static final String ALARM_HTTP_URL = "http://alertserv-dataservice.quantgroup.cn/common/alert/dingtalk";
private static final String ROBOT_WEB_HOOK = "https://oapi.dingtalk.com/robot/send?access_token=f616b4f0892a98a20e8d989ec4f49b59075c3097143daa23eb54b6bb19337969";
private static final String NEW_ALARM_URL = "https://oapi.dingtalk.com/robot/send?access_token=4af8824959a9f949b977ec67026d0404aa8152241c8c9722cc611726d6d33443";
@Value("${alarmOpen}")
private Boolean alarmOpen;
......@@ -45,4 +49,25 @@ public class AlarmServiceImpl implements IAlarmService{
log.error("钉钉机器人报警异常, msg : {}", msgContent, e);
}
}
@Async
@Override
public void sendMsgWithAlert(DingTalkMessage dingTalkMessage) {
try {
if (!TechEnvironment.isPro()){
log.info("测试环境就别发送钉钉报警通知了,挺烦的,消息内容是: {}",dingTalkMessage.toJsonString());
return;
}
if (dingTalkMessage instanceof MarkdownMessage){
MarkdownMessage talkMessage = (MarkdownMessage) dingTalkMessage;
talkMessage.addFirst("assert\n");
}
Map<String, String> params = new HashMap<>();
String postJson = httpService.postJson(NEW_ALARM_URL, params);
log.info("报警返回结果是 {}", postJson);
} catch (Exception e) {
log.error("[警告] 向钉钉发送消息异常.", e);
}
}
}
package com.quantgroup.asset.distribution.service.alarm.impl;
import com.quantgroup.asset.distribution.service.alarm.DingTalkMessage;
import lombok.Data;
import lombok.Getter;
/**
* 钉钉链接消息
*/
@Getter
public class LinkMessage implements DingTalkMessage {
private String msgtype = "link";
private Link link;
private LinkMessage() {
}
/**
* 构建url消息
*
* @param title
* @param text
* @param url
* @return
*/
public static LinkMessage buildMessage(String title, String text, String url) {
Link link = new Link();
link.setText(text);
link.setTitle(title);
link.setMessageUrl(url);
LinkMessage linkMessage = new LinkMessage();
linkMessage.link = link;
return linkMessage;
}
/**
* 返回消息的Json格式字符串
*
* @return 消息的Json格式字符串
*/
@Override
public Object toJsonString() {
return this;
}
/**
* 返回@All的字符串
*
* @return
*/
@Override
public Object toJsonStringWithAlert() {
return this;
}
@Data
public static class Link {
private String text;
private String title;
private String picUrl = "http://jdimage.q-gp.com/w3.png";
private String messageUrl;
}
}
package com.quantgroup.asset.distribution.service.alarm.impl;
import com.quantgroup.asset.distribution.service.alarm.DingTalkMessage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* MarkdownMessage
*
* @author Feng
*/
public class MarkdownMessage implements DingTalkMessage {
private String title;
private List<String> items = new ArrayList<>();
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void add(String text) {
items.add(text);
}
public void addFirst(String text){
items.add(0,text);
}
public static String getBoldText(String text) {
return "**" + text + "**";
}
public static String getItalicText(String text) {
return "*" + text + "*";
}
public static String getLinkText(String text, String href) {
return "[" + text + "](" + href + ")";
}
public static String getImageText(String imageUrl) {
return "![image](" + imageUrl + ")";
}
public static String getHeaderText(int headerType, String text) {
if (headerType < 1 || headerType > 6) {
throw new IllegalArgumentException("headerType should be in [1, 6]");
}
StringBuffer numbers = new StringBuffer();
for (int i = 0; i < headerType; i++) {
numbers.append("#");
}
return numbers + " " + text;
}
public static String getReferenceText(String text) {
return "> " + text;
}
public static String getOrderListText(List<String> orderItem) {
if (orderItem.isEmpty()) {
return "";
}
StringBuffer sb = new StringBuffer();
for (int i = 1; i <= orderItem.size() - 1; i++) {
sb.append(String.valueOf(i) + ". " + orderItem.get(i - 1) + "\n");
}
sb.append(String.valueOf(orderItem.size()) + ". " + orderItem.get(orderItem.size() - 1));
return sb.toString();
}
public static String getUnorderListText(List<String> unorderItem) {
if (unorderItem.isEmpty()) {
return "";
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < unorderItem.size() - 1; i++) {
sb.append("- " + unorderItem.get(i) + "\n");
}
sb.append("- " + unorderItem.get(unorderItem.size() - 1));
return sb.toString();
}
@Override
public Map<String, Object> toJsonString() {
Map<String, Object> result = new HashMap<String, Object>();
result.put("msgtype", "markdown");
Map<String, Object> markdown = new HashMap<String, Object>();
markdown.put("title", title);
StringBuffer markdownText = new StringBuffer();
for (String item : items) {
markdownText.append(item + "\n");
}
markdown.put("text", markdownText.toString());
result.put("markdown", markdown);
return result;
}
@Override
public Object toJsonStringWithAlert() {
Map<String, Object> result = new HashMap<String, Object>();
result.put("msgtype", "markdown");
Map<String, Object> markdown = new HashMap<String, Object>();
markdown.put("title", title);
StringBuffer markdownText = new StringBuffer();
for (String item : items) {
markdownText.append(item + "\n");
}
markdown.put("text", markdownText.toString());
result.put("markdown", markdown);
Map<String, Object> at = new HashMap<String, Object>();
at.put("isAtAll", "true");
result.put("at", at);
return result;
}
}
......@@ -220,8 +220,9 @@ public class HttpServiceImpl implements IHttpService {
httpEntity = httpResponse.getEntity();
response = EntityUtils.toString(httpEntity, "UTF-8");
}
if(isLog)
if(isLog) {
LOGGER.info("{}, uri:{},parameters:{},response:{},statusCode:{}", method, uri, parameters,response,statusCode);
}
return response;
} catch (Exception e) {
LOGGER.error("{}, uri:{}, parameters:{}", method, uri, parameters, e);
......
......@@ -6,18 +6,18 @@ import java.util.Objects;
/**
* @author shihuajun
* @date 2021/8/26 17:57
* @date 2021/9/2 15:02
* @ describing
*/
@Entity
@Table(name = "channel_rule", schema = "asset-distribution")
@Table(name = "channel_rule", schema = "asset-distribution", catalog = "")
public class ChannelRuleEntity {
private long id;
private long fundProductId;
private long channelId;
private Byte publishStatus;
private long fundId;
private long fundCorpId;
private long fundProId;
private String fundName;
private String fundType;
private String orgType;
......@@ -26,8 +26,8 @@ public class ChannelRuleEntity {
private String userTag;
private String userLevel;
private int priority;
private Byte enable;
private Byte routeWait;
private Byte enable;
private Timestamp createdAt;
private Timestamp updatedAt;
......@@ -82,13 +82,13 @@ public class ChannelRuleEntity {
}
@Basic
@Column(name = "fund_corp_id", nullable = false)
public long getFundCorpId() {
return fundCorpId;
@Column(name = "fund_pro_id", nullable = false)
public long getFundProId() {
return fundProId;
}
public void setFundCorpId(long fundCorpId) {
this.fundCorpId = fundCorpId;
public void setFundProId(long fundProId) {
this.fundProId = fundProId;
}
@Basic
......@@ -171,16 +171,6 @@ public class ChannelRuleEntity {
this.priority = priority;
}
@Basic
@Column(name = "enable", nullable = true)
public Byte getEnable() {
return enable;
}
public void setEnable(Byte enable) {
this.enable = enable;
}
@Basic
@Column(name = "route_wait", nullable = true)
public Byte getRouteWait() {
......@@ -191,6 +181,16 @@ public class ChannelRuleEntity {
this.routeWait = routeWait;
}
@Basic
@Column(name = "enable", nullable = true)
public Byte getEnable() {
return enable;
}
public void setEnable(Byte enable) {
this.enable = enable;
}
@Basic
@Column(name = "created_at", nullable = false)
public Timestamp getCreatedAt() {
......@@ -213,18 +213,14 @@ public class ChannelRuleEntity {
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ChannelRuleEntity that = (ChannelRuleEntity) o;
return id == that.id && fundProductId == that.fundProductId && channelId == that.channelId && fundId == that.fundId && fundCorpId == that.fundCorpId && creditResult == that.creditResult && priority == that.priority && Objects.equals(publishStatus, that.publishStatus) && Objects.equals(fundName, that.fundName) && Objects.equals(fundType, that.fundType) && Objects.equals(orgType, that.orgType) && Objects.equals(businessType, that.businessType) && Objects.equals(userTag, that.userTag) && Objects.equals(userLevel, that.userLevel) && Objects.equals(enable, that.enable) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
return id == that.id && fundProductId == that.fundProductId && channelId == that.channelId && fundId == that.fundId && fundProId == that.fundProId && creditResult == that.creditResult && priority == that.priority && Objects.equals(publishStatus, that.publishStatus) && Objects.equals(fundName, that.fundName) && Objects.equals(fundType, that.fundType) && Objects.equals(orgType, that.orgType) && Objects.equals(businessType, that.businessType) && Objects.equals(userTag, that.userTag) && Objects.equals(userLevel, that.userLevel) && Objects.equals(routeWait, that.routeWait) && Objects.equals(enable, that.enable) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
}
@Override
public int hashCode() {
return Objects.hash(id, fundProductId, channelId, publishStatus, fundId, fundCorpId, fundName, fundType, orgType, businessType, creditResult, userTag, userLevel, priority, enable, createdAt, updatedAt);
return Objects.hash(id, fundProductId, channelId, publishStatus, fundId, fundProId, fundName, fundType, orgType, businessType, creditResult, userTag, userLevel, priority, routeWait, enable, createdAt, updatedAt);
}
}
......@@ -6,7 +6,7 @@ import java.util.Objects;
/**
* @author shihuajun
* @date 2021/8/30 17:34
* @date 2021/9/2 16:20
* @ describing
*/
@Entity
......@@ -21,6 +21,8 @@ public class FundProductEntity {
private String businessType;
private String systermType;
private String basicRule;
private int areaTerm;
private String areaRule;
private String ruleList;
private Byte enable;
private Timestamp createdAt;
......@@ -116,6 +118,26 @@ public class FundProductEntity {
this.basicRule = basicRule;
}
@Basic
@Column(name = "area_term", nullable = false)
public int getAreaTerm() {
return areaTerm;
}
public void setAreaTerm(int areaTerm) {
this.areaTerm = areaTerm;
}
@Basic
@Column(name = "area_rule", nullable = false, length = 500)
public String getAreaRule() {
return areaRule;
}
public void setAreaRule(String areaRule) {
this.areaRule = areaRule;
}
@Basic
@Column(name = "rule_list", nullable = false, length = 500)
public String getRuleList() {
......@@ -161,11 +183,11 @@ public class FundProductEntity {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FundProductEntity that = (FundProductEntity) o;
return id == that.id && fundId == that.fundId && fundProId == that.fundProId && Objects.equals(fundName, that.fundName) && Objects.equals(fundType, that.fundType) && Objects.equals(orgType, that.orgType) && Objects.equals(businessType, that.businessType) && Objects.equals(systermType, that.systermType) && Objects.equals(basicRule, that.basicRule) && Objects.equals(ruleList, that.ruleList) && Objects.equals(enable, that.enable) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
return id == that.id && fundId == that.fundId && fundProId == that.fundProId && areaTerm == that.areaTerm && Objects.equals(fundName, that.fundName) && Objects.equals(fundType, that.fundType) && Objects.equals(orgType, that.orgType) && Objects.equals(businessType, that.businessType) && Objects.equals(systermType, that.systermType) && Objects.equals(basicRule, that.basicRule) && Objects.equals(areaRule, that.areaRule) && Objects.equals(ruleList, that.ruleList) && Objects.equals(enable, that.enable) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
}
@Override
public int hashCode() {
return Objects.hash(id, fundId, fundProId, fundName, fundType, orgType, businessType, systermType, basicRule, ruleList, enable, createdAt, updatedAt);
return Objects.hash(id, fundId, fundProId, fundName, fundType, orgType, businessType, systermType, basicRule, areaTerm, areaRule, ruleList, enable, createdAt, updatedAt);
}
}
......@@ -6,18 +6,18 @@ import java.util.Objects;
/**
* @author shihuajun
* @date 2021/8/31 11:29
* @date 2021/9/2 16:26
* @ describing
*/
@Entity
@Table(name = "product_rule", schema = "asset-distribution")
@Table(name = "product_rule", schema = "asset-distribution", catalog = "")
public class ProductRuleEntity {
private long id;
private String ruleName;
private String ruleVal;
private String ruleEngine;
private String ruleChinese;
private String textType;
private String ruleType;
private Byte enable;
private Timestamp createdAt;
private Timestamp updatedAt;
......@@ -52,6 +52,16 @@ public class ProductRuleEntity {
this.ruleVal = ruleVal;
}
@Basic
@Column(name = "rule_engine", nullable = false, length = 100)
public String getRuleEngine() {
return ruleEngine;
}
public void setRuleEngine(String ruleEngine) {
this.ruleEngine = ruleEngine;
}
@Basic
@Column(name = "rule_chinese", nullable = false, length = 50)
public String getRuleChinese() {
......@@ -72,16 +82,6 @@ public class ProductRuleEntity {
this.textType = textType;
}
@Basic
@Column(name = "rule_type", nullable = true, length = 50)
public String getRuleType() {
return ruleType;
}
public void setRuleType(String ruleType) {
this.ruleType = ruleType;
}
@Basic
@Column(name = "enable", nullable = true)
public Byte getEnable() {
......@@ -117,11 +117,11 @@ public class ProductRuleEntity {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProductRuleEntity that = (ProductRuleEntity) o;
return id == that.id && Objects.equals(ruleName, that.ruleName) && Objects.equals(ruleVal, that.ruleVal) && Objects.equals(ruleChinese, that.ruleChinese) && Objects.equals(textType, that.textType) && Objects.equals(ruleType, that.ruleType) && Objects.equals(enable, that.enable) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
return id == that.id && Objects.equals(ruleName, that.ruleName) && Objects.equals(ruleVal, that.ruleVal) && Objects.equals(ruleEngine, that.ruleEngine) && Objects.equals(ruleChinese, that.ruleChinese) && Objects.equals(textType, that.textType) && Objects.equals(enable, that.enable) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
}
@Override
public int hashCode() {
return Objects.hash(id, ruleName, ruleVal, ruleChinese, textType, ruleType, enable, createdAt, updatedAt);
return Objects.hash(id, ruleName, ruleVal, ruleEngine, ruleChinese, textType, enable, createdAt, updatedAt);
}
}
......@@ -124,4 +124,17 @@ public class RoutingRecordEntity {
public int hashCode() {
return Objects.hash(id, phone, uuid, creditNo, status, routedResult, routedAt, createdAt, updatedAt);
}
@PrePersist
public void prePersist() {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
createdAt = timestamp;
updatedAt = timestamp;
routedAt = timestamp;
}
@PreUpdate
public void preUpdate() {
updatedAt = new Timestamp(System.currentTimeMillis());
}
}
......@@ -6,17 +6,17 @@ import java.util.Objects;
/**
* @author shihuajun
* @date 2021/8/26 17:57
* @date 2021/9/2 15:02
* @ describing
*/
@Entity
@Table(name = "white_list", schema = "asset-distribution")
@Table(name = "white_list", schema = "asset-distribution", catalog = "")
public class WhiteListEntity {
private long id;
private long fundProductId;
private String phone;
private long fundId;
private long fundCorpId;
private long fundProId;
private String fundName;
private String fundType;
private String orgType;
......@@ -66,13 +66,13 @@ public class WhiteListEntity {
}
@Basic
@Column(name = "fund_corp_id", nullable = false)
public long getFundCorpId() {
return fundCorpId;
@Column(name = "fund_pro_id", nullable = false)
public long getFundProId() {
return fundProId;
}
public void setFundCorpId(long fundCorpId) {
this.fundCorpId = fundCorpId;
public void setFundProId(long fundProId) {
this.fundProId = fundProId;
}
@Basic
......@@ -150,11 +150,11 @@ public class WhiteListEntity {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WhiteListEntity that = (WhiteListEntity) o;
return id == that.id && fundProductId == that.fundProductId && fundId == that.fundId && fundCorpId == that.fundCorpId && Objects.equals(phone, that.phone) && Objects.equals(fundName, that.fundName) && Objects.equals(fundType, that.fundType) && Objects.equals(orgType, that.orgType) && Objects.equals(businessType, that.businessType) && Objects.equals(status, that.status) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
return id == that.id && fundProductId == that.fundProductId && fundId == that.fundId && fundProId == that.fundProId && Objects.equals(phone, that.phone) && Objects.equals(fundName, that.fundName) && Objects.equals(fundType, that.fundType) && Objects.equals(orgType, that.orgType) && Objects.equals(businessType, that.businessType) && Objects.equals(status, that.status) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt);
}
@Override
public int hashCode() {
return Objects.hash(id, fundProductId, phone, fundId, fundCorpId, fundName, fundType, orgType, businessType, status, createdAt, updatedAt);
return Objects.hash(id, fundProductId, phone, fundId, fundProId, fundName, fundType, orgType, businessType, status, createdAt, updatedAt);
}
}
......@@ -3,7 +3,11 @@ package com.quantgroup.asset.distribution.service.jpa.repository;
import com.quantgroup.asset.distribution.service.jpa.entity.ChannelRuleEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface IChannelRuleRepository extends JpaRepository<ChannelRuleEntity, Long>{
ChannelRuleEntity getByFundProductIdEquals(long fundProductId);
List<ChannelRuleEntity> getByChannelId(long channelId);
}
package com.quantgroup.asset.distribution.service.newrule;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
/**
* @author shihuajun
* @date 2021/8/27 10:58
* @ describing
*/
@Component
public class RuleHandleFactory {
@Resource
private Map<String, IRuleVerifyService> ruleVerifyServiceMap;
public IRuleVerifyService getRuleVerifyServiceMap(String className) {
if (StringUtils.isBlank(className)){
throw new RuntimeException("获取IRuleVerifyService入参有问题");
}
if (ruleVerifyServiceMap.containsKey(className)){
return ruleVerifyServiceMap.get(className);
}else {
throw new RuntimeException("获取IRuleVerifyService入参有问题,没有对应的实现类");
}
}
}
package com.quantgroup.asset.distribution.service.newrule.pojo;
import lombok.Data;
/**
* @author shihuajun
* @date 2021/9/2 14:56
* @ describing
*/
@Data
public class RoutingRecordVO {
private long fundId;
private long fundProId;
private String fundName;
private String orgType;
private int priority;
}
package com.quantgroup.asset.distribution.service.newrule.pojo;
/**
* @author shihuajun
* @date 2021/8/31 11:34
* @ describing
*/
public class RuleConstant {
public final static String AMOUNT = "amount";
public final static String TERM = "term";
public final static String AGE = "age";
public final static String NOT_PERMIT_TELS = "tel";
}
package com.quantgroup.asset.distribution.service.newrule.pojo.enums;
import lombok.Getter;
/**
* @author shihuajun
* @date 2021/9/2 17:01
* @ describing
*/
@Getter
public enum AreaEnum {
NO_DEMAND(0,"无地区限制"),
CHOOSE_ONE_MORE(1,"地区限制多选一"),
TWO_OUT_OF_MANY(2,"地区限制多选二"),
ALL_DEMAND(3,"地区限制全选");
private final Integer code;
private final String desc;
AreaEnum(Integer code,String desc){
this.code = code;
this.desc = desc;
}
public static AreaEnum parse(int code){
for (AreaEnum ae : AreaEnum.values()) {
if (code == ae.getCode()){
return ae;
}
}
throw new RuntimeException("解析AreaEnum出问题了,没有对应的枚举类型");
}
}
package com.quantgroup.asset.distribution.service.newrule.pojo.enums;
/**
* @author shihuajun
* @date 2021/8/27 14:33
* @ describing
*/
public enum CooperationEnum {
/**
* 助贷
*/
DIVERSION,
/**
* 导流
*/
ASSISTANCE
}
package com.quantgroup.asset.distribution.service.newrule.pojo.enums;
import lombok.Getter;
/**
* @author shihuajun
* @date 2021/8/28 10:33
* @ describing
*/
@Getter
public enum SpecialRuleEnum {
CONTACT_NAME_SAME_VERIFY("联系人姓名相同"),
CONTACT_TEL_SAME_VERIFY("联系人手机号相同"),
AREA_VERIFY("各种区域的组合校验"),
CONTACT_TEL_ERROR_VERIFY("联系人手机号不正确");
private String desc;
SpecialRuleEnum(String desc){
this.desc = desc;
}
}
package com.quantgroup.asset.distribution.service.newrule.pojo.funds;
import com.quantgroup.asset.distribution.service.newrule.third.AuditResponce;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author shihuajun
* @date 2021/8/27 14:13
* @ describing
*/
@Data
public class FilterResult {
String financeProducts; //金融产品集
public Map<String, String> get(AuditResponce responce) {
return new HashMap<String, String>(32) {{
put("code", responce.getCode().toString());
put("msg", responce.getMsg());
put("uuid", responce.getUuid());
put("bizChannel", responce.getBizChannel());
put("bizNo", responce.getBizNo());
put("bizType", responce.getBizType());
put("auditResult", responce.getAuditResult().toString());
put("deadLine", responce.getDeadLine().toString());
put("validity", responce.getValidity());
put("openingDeadLine", responce.getOpeningDeadLine() == null ? null : String.valueOf(responce.getOpeningDeadLine()));
put("openingValidity", responce.getOpeningValidity());
put("otherInformation", responce.getOtherInformation());
put("financeProducts", financeProducts);
put("xycreditScore", String.valueOf(responce.getXycreditScore()));
put("creditLevel", responce.getCreditLevel());
put("callbackUrl", responce.getCallbackUrl());
put("refuseReason", responce.getRefuseReason());
put("amount", responce.getAmount());
put("term", responce.getTerm());
put("sceneId", String.valueOf(responce.getMethod()));
put("exData", responce.getExData());
put("amountTermLimits", responce.getAmountTermLimits());
put("fundRate", responce.getFundRate());
put("amountRate", responce.getAmountRate());
put("exportVccTag", responce.getExportVccTag());
put("allowInstalment", responce.getAllowInstalment());
put("allowInstalmentTerms", responce.getAllowInstalmentTerms());
put("isWhiteBlackListHit", responce.getIsWhiteBlackListHit());
put("isFuseModuleHit", responce.getIsFuseModuleHit());
put("secondaryValidation",responce.getSecondaryValidation());
if (StringUtils.isNotEmpty(responce.getQuotaPaymentAmount())) {
put("quotaPaymentAmount", responce.getQuotaPaymentAmount());
}
}};
}
}
package com.quantgroup.asset.distribution.service.newrule.pojo.funds;
import com.alibaba.fastjson.annotation.JSONField;
import com.quantgroup.asset.distribution.service.jpa.entity.ChannelRuleEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* @author shihuajun
* @date 2021/8/27 14:30
* @ describing
*/
@Data
public class FinanceProduct {
private BigDecimal min;
private BigDecimal max;
@JSONField(name = "terms")
private List<Terms> terms;
/**
* 是否等待
*/
private Boolean waitFlg;
private transient ChannelRuleEntity channelRuleEntity;
}
package com.quantgroup.asset.distribution.service.newrule.pojo.funds;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.CooperationEnum;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author shihuajun
* @date 2021/8/27 14:32
* @ describing
*/
@Data
public class FundInfo {
private Long fundId;
private BigDecimal rate = BigDecimal.ZERO;
private Integer rateType = 1;
private Integer feeType = 1;
private Integer priority;
private CooperationEnum cooperation;
/**
* 产品
*/
private String fundProductId;
}
package com.quantgroup.asset.distribution.service.newrule.pojo.funds;
import cn.quantgroup.motan.bean.UserAssociationBean;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.AreaEnum;
import lombok.Data;
/**
* @author shihuajun
* @date 2021/8/27 11:23
* @ describing 规则校验的入参
*/
@Data
public class RuleParam {
private UserAssociationBean userInfo;
private AreaEnum areaNum;
private String area;
/**
* @author shihuajun
* @date 2021/9/2 17:36
* @ describing
*/
@Data
public static class AreaRuleConcrete {
// 手机号区域限制
private String telAreaNameList;
// 居住地
private String residenceList;
// 籍贯
private String nativeList;
}
}
package com.quantgroup.asset.distribution.service.newrule.pojo.funds;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.List;
/**
* @author shihuajun
* @date 2021/8/27 14:31
* @ describing
*/
@Data
public class Terms {
@JSONField(name = "term")
private Integer term;
@JSONField(name = "fundInfo")
private List<FundInfo> fundInfos;
}
......@@ -28,8 +28,8 @@ public class ProductRuleServiceImpl implements IProductRuleService{
private IProductRuleRepository productRuleRepository;
private static List<ProductRuleEntity> CACHE = Lists.newArrayList();
private static ReentrantReadWriteLock RW = new ReentrantReadWriteLock();
private static Lock R = RW.readLock();
private static final ReentrantReadWriteLock RW = new ReentrantReadWriteLock();
private static final Lock R = RW.readLock();
@PostConstruct
public void loadProductRule(){
......
package com.quantgroup.asset.distribution.service.newrule.specialrules;
import com.quantgroup.asset.distribution.service.jpa.entity.ProductRuleEntity;
import com.quantgroup.asset.distribution.service.newrule.IRuleVerifyService;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.SpecialRuleEnum;
import com.quantgroup.asset.distribution.service.newrule.pojo.funds.RuleParam;
import com.quantgroup.asset.distribution.service.newrule.service.IProductRuleService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author shihuajun
* @date 2021/8/28 12:00
* @ describing
*/
@Service
public class AbstractProductRuleVerifyImpl implements IRuleVerifyService {
@Resource
private IProductRuleService productRuleService;
@Override
public boolean pass(RuleParam param) {
return false;
}
@Override
public ProductRuleEntity getRuleDetail() {
return productRuleService.getProductRuleEntityByRuleMame(this.specialRuleName().name());
}
@Override
public SpecialRuleEnum specialRuleName() {
return null;
}
}
package com.quantgroup.asset.distribution.service.newrule.specialrules;
import cn.quantgroup.motan.bean.UserAssociationBean;
import com.quantgroup.asset.distribution.model.entity.user.SDKUserInfo;
import com.quantgroup.asset.distribution.model.entity.user.UserAddressInfo;
import com.quantgroup.asset.distribution.service.alarm.IAlarmService;
import com.quantgroup.asset.distribution.service.alarm.impl.MarkdownMessage;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.AreaEnum;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.SpecialRuleEnum;
import com.quantgroup.asset.distribution.service.newrule.pojo.funds.RuleParam;
import com.quantgroup.asset.distribution.service.user.IUserCenterService;
import com.quantgroup.asset.distribution.util.IdCardUtil;
import com.quantgroup.asset.distribution.util.JacksonUtil;
import com.quantgroup.asset.distribution.util.PhoneNumberGeo;
import com.quantgroup.asset.distribution.util.PhoneNumberInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author shihuajun
* @date 2021/9/2 16:28
* @ describing
*/
@Slf4j
@Component
public class AreaVerifyImpl extends AbstractProductRuleVerifyImpl{
private static final String PROVINCE = "省";
private static final String TEL_ALERM_TEXT = "用户的手机号是 %s";
@Resource
private IAlarmService alarmService;
@Resource
private IUserCenterService userCenterService;
@Override
public boolean pass(RuleParam param) {
if (StringUtils.isBlank(param.getArea()) && !AreaEnum.NO_DEMAND.equals(param.getAreaNum())){
throw new RuntimeException("区域配置有问题");
}else if (AreaEnum.NO_DEMAND.equals(param.getAreaNum())){
return Boolean.TRUE;
}
RuleParam.AreaRuleConcrete ruleConcrete = JacksonUtil.deserialize(param.getArea(), RuleParam.AreaRuleConcrete.class);
if (ruleConcrete == null){
throw new RuntimeException("反序列化对象AreaRuleConcrete出问题了");
}
UserAssociationBean userInfo = param.getUserInfo();
AtomicInteger hit = new AtomicInteger(0);
if (StringUtils.isNotBlank(ruleConcrete.getNativeList())){
List<Integer> nativeList = JacksonUtil.deserializeList(ruleConcrete.getNativeList(), Integer.class);
String nativeCode = IdCardUtil.getCityCodeByIdCard(userInfo.getIdNo());
if (StringUtils.isNotBlank(nativeCode) && nativeList.contains(Integer.parseInt(nativeCode))){
hit.incrementAndGet();
}
if (AreaEnum.CHOOSE_ONE_MORE.equals(param.getAreaNum())){
return true;
}
}
if (StringUtils.isNotBlank(ruleConcrete.getResidenceList())){
List<Integer> residenceList = JacksonUtil.deserializeList(ruleConcrete.getResidenceList(), Integer.class);
SDKUserInfo userExtInfo = userCenterService.getSDKUserExtInfo(userInfo.getPhoneNo(), null);
List<UserAddressInfo> addressList = userExtInfo.getAddressList();
if (CollectionUtils.isEmpty(addressList)){
UserAddressInfo userAddressInfo = addressList.get(0);
boolean residenceResult = (userAddressInfo.getDistrictCode() != null && residenceList.contains(userAddressInfo.getDistrictCode()))
|| (userAddressInfo.getCityCode() != null && residenceList.contains(userAddressInfo.getCityCode()))
|| (userAddressInfo.getProvinceCode() != null && residenceList.contains(userAddressInfo.getProvinceCode()));
if (residenceResult){
hit.incrementAndGet();
}
}
if (AreaEnum.TWO_OUT_OF_MANY.equals(param.getAreaNum())
|| AreaEnum.CHOOSE_ONE_MORE.equals(param.getAreaNum())){
return true;
}
}
if (StringUtils.isNotBlank(ruleConcrete.getTelAreaNameList())){
List<String> telAreaNameList = JacksonUtil.deserializeList(ruleConcrete.getTelAreaNameList(), String.class);
PhoneNumberGeo phoneNumberGeo = new PhoneNumberGeo();
PhoneNumberInfo numberInfo = phoneNumberGeo.lookup(userInfo.getPhoneNo());
if (numberInfo == null){
log.error("解析手机号出现问题,用户的手机号是 {}",userInfo.getPhoneNo());
MarkdownMessage markdownMessage = new MarkdownMessage();
markdownMessage.setTitle("解析手机号出现问题");
markdownMessage.add(String.format(TEL_ALERM_TEXT,userInfo.getPhoneNo()));
alarmService.sendMsgWithAlert(markdownMessage);
return Boolean.TRUE;
}
String province = numberInfo.getProvince() + PROVINCE;
if (telAreaNameList.contains(province)){
hit.incrementAndGet();
}
if (AreaEnum.ALL_DEMAND.equals(param.getAreaNum())
|| AreaEnum.TWO_OUT_OF_MANY.equals(param.getAreaNum())
|| AreaEnum.CHOOSE_ONE_MORE.equals(param.getAreaNum())){
return true;
}
}
return Boolean.FALSE;
}
@Override
public SpecialRuleEnum specialRuleName() {
return SpecialRuleEnum.AREA_VERIFY;
}
}
package com.quantgroup.asset.distribution.service.newrule.specialrules;
import cn.quantgroup.motan.bean.UserAssociationBean;
import cn.quantgroup.motan.retbean.XContactInfo;
import com.alibaba.fastjson.JSON;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.SpecialRuleEnum;
import com.quantgroup.asset.distribution.service.newrule.pojo.funds.RuleParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author shihuajun
* @date 2021/8/26 19:42
* @ describing
*/
@Slf4j
@Component
public class ContactsNameSameVerifyImpl extends AbstractProductRuleVerifyImpl {
@Override
public boolean pass(RuleParam param) {
if (param == null){
throw new RuntimeException("联系人姓名相同入参param有问题");
}
UserAssociationBean userInfo = param.getUserInfo();
if (userInfo == null){
throw new RuntimeException("联系人姓名相同入参userInfo有问题");
}
List<XContactInfo> contractResults = userInfo.getContractResults();
if (CollectionUtils.isEmpty(contractResults)){
log.warn("校验联系人姓名相同时发现联系人为空");
return true;
}
for (XContactInfo info : contractResults) {
if (StringUtils.isBlank(info.getName())){
log.warn("校验联系人姓名相同时发现联系人姓名为空,联系人信息 {}", JSON.toJSONString(info));
continue;
}
if (info.getName().equals(param.getUserInfo().getName())){
log.warn("校验联系人姓名相同时发现当前用户与联系人姓名相同,联系人信息 {}", JSON.toJSONString(info));
return true;
}
}
return false;
}
@Override
public SpecialRuleEnum specialRuleName() {
return SpecialRuleEnum.CONTACT_NAME_SAME_VERIFY;
}
}
package com.quantgroup.asset.distribution.service.newrule.specialrules;
import cn.quantgroup.motan.bean.UserAssociationBean;
import cn.quantgroup.motan.retbean.XContactInfo;
import com.alibaba.fastjson.JSON;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.SpecialRuleEnum;
import com.quantgroup.asset.distribution.service.newrule.pojo.funds.RuleParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author shihuajun
* @date 2021/8/26 19:44
* @ describing
*/
@Slf4j
@Component
public class ContactsTelErrorVerifyImpl extends AbstractProductRuleVerifyImpl{
@Override
public boolean pass(RuleParam param) {
if (param == null){
throw new RuntimeException("联系人手机号校验入参param有问题");
}
UserAssociationBean userInfo = param.getUserInfo();
if (userInfo == null){
throw new RuntimeException("联系人手机号校验入参userInfo有问题");
}
List<XContactInfo> contractResults = userInfo.getContractResults();
if (CollectionUtils.isEmpty(contractResults)){
log.warn("联系人手机号校验时发现联系人为空");
return true;
}
for (XContactInfo info : contractResults) {
if (StringUtils.isBlank(info.getPhoneNo())){
log.warn("联系人手机号校验时发现联系人手机号为空,联系人信息 {}", JSON.toJSONString(info));
continue;
}
if (this.telVerify(info.getPhoneNo())){
log.warn("联系人手机号校验时发现当前用户手机号有问题,联系人信息 {}", JSON.toJSONString(info));
return true;
}
}
return false;
}
@Override
public SpecialRuleEnum specialRuleName() {
return SpecialRuleEnum.CONTACT_TEL_ERROR_VERIFY;
}
private boolean telVerify(String tel){
if (tel.length() != 11){
return false;
}
if (!tel.startsWith("1")){
return false;
}
if (tel.startsWith("170") || tel.startsWith("171")){
return false;
}
return true;
}
}
package com.quantgroup.asset.distribution.service.newrule.specialrules;
import cn.quantgroup.motan.bean.UserAssociationBean;
import cn.quantgroup.motan.retbean.XContactInfo;
import com.alibaba.fastjson.JSON;
import com.quantgroup.asset.distribution.service.newrule.pojo.enums.SpecialRuleEnum;
import com.quantgroup.asset.distribution.service.newrule.pojo.funds.RuleParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author shihuajun
* @date 2021/8/26 19:42
* @ describing
*/
@Slf4j
@Component
public class ContactsTelSameVerifyImpl extends AbstractProductRuleVerifyImpl{
@Override
public boolean pass(RuleParam param) {
if (param == null){
throw new RuntimeException("联系人手机号校验入参param有问题");
}
UserAssociationBean userInfo = param.getUserInfo();
if (userInfo == null){
throw new RuntimeException("联系人手机号校验入参userInfo有问题");
}
List<XContactInfo> contractResults = userInfo.getContractResults();
if (CollectionUtils.isEmpty(contractResults)){
log.warn("联系人手机号校验发现联系人为空");
return true;
}
for (XContactInfo info : contractResults) {
if (StringUtils.isBlank(info.getPhoneNo())){
log.warn("联系人手机号校验发现联系人手机号为空,联系人信息 {}", JSON.toJSONString(info));
continue;
}
if (info.getPhoneNo().equals(param.getUserInfo().getPhoneNo())){
log.warn("联系人手机号校验发现当前用户与联系人手机号相同,联系人信息 {}", JSON.toJSONString(info));
return true;
}
}
return false;
}
@Override
public SpecialRuleEnum specialRuleName() {
return SpecialRuleEnum.CONTACT_TEL_SAME_VERIFY;
}
}
package com.quantgroup.asset.distribution.service.newrule.third;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
/**
* @author shihuajun
* @date 2021/8/26 19:28
* @ describing http://yapi.quantgroups.com/project/49/interface/api/5685
*/
@Data
public class AuditResponce {
private Integer code;
private String msg;
//用户UUID
@NotNull
@Length(min = 1)
private String uuid;
@NotNull
private String bizChannel;
//业务唯一编号
@NotNull
private String bizNo;
//业务类型 0-循环额度现金分期 1-循环额度白条 2-现金分期 3-白条
private String bizType;
//扩展参数
private String exData;
//其他信息
private String otherInformation;
//审核结果
@NotNull
private Boolean auditResult;
//额度
@NotNull
private String amount;
//期数
@NotNull
private String term;
// 有效期, int类型, 天数
@NotNull
private String validity;
//有效截止时间
@NotNull
private Long deadLine;
// vcc-开户有效天数, int类型
private String openingValidity;
// vcc-开户有效截止时间
@NotNull
private Long openingDeadLine;
//金融产品集
private String financeProducts;
//新颜分
private Integer xycreditScore;
//用户等级
private String creditLevel;
//回调通知地址
@NotNull
@Length(min = 1)
private String callbackUrl;
private String refuseReason;
// 额度、期数限制列表
private String amountTermLimits;
// 额度变化率
private String amountRate;
// 渠道方要求利率,目前只给乐信渠道用
private String fundRate;
// 是否导流VCC,1-导流, 0-不导流
private String exportVccTag;
/**
* 是否允许账单分期
*/
private String allowInstalment;
/**
* 允许账单分期数
*/
private String allowInstalmentTerms;
/**
* 场景id:
* 0-授信额度审核
* 1-下单审核
* 2-KA进件准入审核
* 3-多订单筛选审核
* 4-微店快速额度审核
* 5-vcc贷中商户预警审核
* 6-vcc贷中交易反欺诈审核
* ...
*/
@NotNull
private Integer method;
private String isWhiteBlackListHit;
/**
* 是否命中熔断模块
*/
private String isFuseModuleHit;
/**
* 二次验证规则
*/
private String secondaryValidation;
/**
* 额度支付金额
*/
private String quotaPaymentAmount;
/**
* 特殊用户名单
*/
private String specialUserList;
private String userTag;
}
package com.quantgroup.asset.distribution.service.newrule.third;
/**
* @author shihuajun
* @date 2021/8/26 19:24
* @ describing
*/
public interface RuleEngine {
}
package com.quantgroup.asset.distribution.util;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
......@@ -14,6 +16,24 @@ import java.util.Date;
@Slf4j
public class DateUtil {
public enum DateTimeUtilFormat {
yyyyMMdd("yyyyMMdd"),
yyyyMMddHHmm("yyyyMMddHHmm"),
yyyyMMddHHmmss("yyyyMMddHHmmss"),
yyyy_MM_dd("yyyy-MM-dd"),
MM_dd("MM-dd"),
yyyy_MM_dd_HH_mm("yyyy-MM-dd HH:mm"),
yyyy_MM_dd_HH_mm_ss("yyyy-MM-dd HH:mm:ss"),
yyyy_MM_dd_cn("yyyy年MM月dd日"),
yyyy_MM("yyyy-MM"),
MM_dd_HH_mm_cn("MM月dd日 HH:mm");
String format;
DateTimeUtilFormat(String format) {
this.format = format;
}
}
/**
* 获取当前日期(天)
......@@ -62,4 +82,12 @@ public class DateUtil {
return null;
}
}
public static String toString(Date date, DateTimeUtilFormat dateTimeUtilFormat) {
return new DateTime(date).toString(dateTimeUtilFormat.format);
}
public static DateTime toDateTime(String dateTime, DateTimeUtilFormat dateTimeUtilFormat) {
return DateTimeFormat.forPattern(dateTimeUtilFormat.format).parseLocalDate(dateTime).toDateTimeAtStartOfDay();
}
}
package com.quantgroup.asset.distribution.util;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.Years;
import java.util.Calendar;
import java.util.Date;
/**
* @author shihuajun
* @date 2021/8/31 12:33
* @ describing
*/
public class IdCardUtil {
/**
* 从身份证号中获取生日 xxxx-xx-xx
*
* @param idcard
* @return
*/
public static String getBirthday(String idcard) {
if (StringUtils.isBlank(idcard)) {
return null;
}
Date date = null;
int len = StringUtils.trim(idcard).length();
if (len == 15) {
date = getBrithBy15IdCard(idcard);
} else if (len == 18) {
date = getBrithBy18IdCard(idcard);
} else {
return null;
}
return DateUtil.toString(date, DateUtil.DateTimeUtilFormat.yyyy_MM_dd);
}
/**
* 根据身份证号获取年龄
*
* @param idcard
* @return
*/
public static int getAge(String idcard) {
String birthday = getBirthday(idcard);
return getAgeByBirthday(birthday);
}
/**
* 根据生日获取周岁
*
* @param birthday yyyy-MM-dd
* @return
*/
public static int getAgeByBirthday(String birthday) {
if (StringUtils.isEmpty(birthday)) {
return -1;
}
return Years.yearsBetween(
DateUtil.toDateTime(birthday, DateUtil.DateTimeUtilFormat.yyyy_MM_dd).toLocalDate(),
new LocalDate()).getYears();
}
private static Date getBrithBy18IdCard(String idcard18) {
try {
Integer year = Integer.valueOf(idcard18.substring(6, 10));
Integer month = Integer.valueOf(idcard18.substring(10, 12));
Integer day = Integer.valueOf(idcard18.substring(12, 14));
return constructDate(year, month, day);
} catch (Exception e) {
return null;
}
}
private static Date getBrithBy15IdCard(String idCard15) {
try {
Integer year = Integer.valueOf(idCard15.substring(6, 8)) + 1900;
Integer month = Integer.valueOf(idCard15.substring(8, 10));
Integer day = Integer.valueOf(idCard15.substring(10, 12));
return constructDate(year, month, day);
} catch (Exception e) {
return null;
}
}
private static Date constructDate(Integer year, Integer month, Integer day) {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month - 1);
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return c.getTime();
}
public static String getCityCodeByIdCard(String idcard) {
int len = idcard.length();
return len != 15 && len != 18 ? null : idcard.substring(0, 6);
}
public static void main(String[] args) {
System.out.println(getCityCodeByIdCard("412822199407226911"));
}
}
package com.quantgroup.asset.distribution.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author : shj
* TIME: 2020/7/1 14:31
* DESCRIPTION:
*/
@Slf4j
public class JacksonUtil {
public static final ObjectMapper mapper = new ObjectMapper();
static {
mapper.disable(SerializationFeature.INDENT_OUTPUT);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
mapper.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
mapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 序列化不需要null的
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
}
public static String serialize(Object data) {
try {
return mapper.writeValueAsString(data);
} catch (IOException e) {
log.error("serialize data error", e);
return null;
}
}
public static <T> T deserialize(String content, Class<T> clazz) {
try {
if (StringUtils.isEmpty(content)) {
return null;
}
return mapper.readValue(content, clazz);
} catch (IOException e) {
log.error("deserialize object error: {}", content, e);
return null;
}
}
public static <T> T deserialize(String content, TypeReference<T> clazz) {
try {
return mapper.readValue(content, clazz);
} catch (IOException e) {
log.error("deserialize object error: {}", content, e);
return null;
}
}
public static void main(String[] args) {
String s = "{ \"guarantee\": {\n" +
" \"3\": \"0.014179\",\n" +
" \"6\": \"0.012641\",\n" +
" \"9\": \"0.012263\",\n" +
" \"12\": \"0.012173\"\n" +
" }\n" +
"}";
Map<String, Object> guaranteeMap = JacksonUtil.deserialize(s, new TypeReference<Map<String, Object>>() {
});
System.out.println((LinkedHashMap<Integer,BigDecimal>)guaranteeMap.get("guarantee"));
}
public static <K, V> Map<K, V> deserializeMap(String content, Class<K> clazzKey, Class<V> clazzValue) {
try {
JavaType javaType = mapper.getTypeFactory().constructParametricType(Map.class, clazzKey, clazzValue);
return mapper.readValue(content, javaType);
} catch (IOException e) {
log.error("deserialize with java type object error: {}", content, e);
return null;
}
}
public static <T> List<T> deserializeList(String content, Class<T> elementClass) {
JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, elementClass);
List<T> t = Lists.newArrayList();
try {
t = mapper.readValue(content, javaType);
} catch (Exception e) {
log.error("deserialize list with java type object error: {}", content, e);
}
return t;
}
public static <T> Set<T> deserializeSet(String content, Class<T> elementClass) {
JavaType javaType = mapper.getTypeFactory().constructParametricType(Set.class, elementClass);
Set<T> t = Sets.newHashSet();
try {
t = mapper.readValue(content, javaType);
} catch (Exception e) {
log.error("deserialize set with java type object error: {}", content, e);
}
return t;
}
public static String timeStampSerialize(Object data) {
try {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.INDENT_OUTPUT);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
objectMapper.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
return objectMapper.writeValueAsString(data);
} catch (IOException e) {
log.error("serialize data error", e);
return null;
}
}
@Nullable
public static JsonNode readTree(String content) {
JsonNode ret = null;
try {
ret = mapper.readTree(content);
} catch (IOException e) {
log.error("readTree io exception: ", e);
}
return ret;
}
}
package com.quantgroup.asset.distribution.util;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/**
* @author shihuajun
* @date 2021/9/3 11:00
* @ describing
*/
public class PhoneNumberGeo {
private static final String[] PHONE_NUMBER_TYPE = {null, "移动", "联通", "电信", "电信虚拟运营商", "联通虚拟运营商", "移动虚拟运营商"};
private static final int INDEX_SEGMENT_LENGTH = 9;
private static final int DATA_FILE_LENGTH_HINT = 3747505;
private static final String PHONE_DAT_FILE_PATH = "phone/phone.dat";
private static byte[] dataByteArray;
private static int indexAreaOffset;
private static int phoneRecordCount;
private ByteBuffer byteBuffer;
private static synchronized void initData() {
if (dataByteArray == null) {
ByteArrayOutputStream byteData = new ByteArrayOutputStream(DATA_FILE_LENGTH_HINT);
byte[] buffer = new byte[1024];
int readBytesLength;
try (InputStream inputStream = PhoneNumberGeo.class.getClassLoader().getResourceAsStream(PHONE_DAT_FILE_PATH)) {
while ((readBytesLength = inputStream.read(buffer)) != -1) {
byteData.write(buffer, 0, readBytesLength);
}
} catch (Exception e) {
System.err.println("Can't find phone.dat in classpath: " + PHONE_DAT_FILE_PATH);
e.printStackTrace();
throw new RuntimeException(e);
}
dataByteArray = byteData.toByteArray();
ByteBuffer byteBuffer = ByteBuffer.wrap(dataByteArray);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
int dataVersion = byteBuffer.getInt();
indexAreaOffset = byteBuffer.getInt();
phoneRecordCount = (dataByteArray.length - indexAreaOffset) / INDEX_SEGMENT_LENGTH;
// print data version
// System.out.println(dataVersion);
// print record count
// System.out.println(phoneRecordCount);
}
}
public PhoneNumberGeo() {
initData();
byteBuffer = ByteBuffer.wrap(dataByteArray);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
public PhoneNumberInfo lookup(String phoneNumber) {
if (phoneNumber == null || phoneNumber.length() > 11 || phoneNumber.length() < 7) {
return null;
}
int phoneNumberPrefix;
try {
phoneNumberPrefix = Integer.parseInt(phoneNumber.substring(0, 7));
} catch (Exception e) {
return null;
}
int left = 0;
int right = phoneRecordCount;
while (left <= right) {
int middle = (left + right) >> 1;
int currentOffset = indexAreaOffset + middle * INDEX_SEGMENT_LENGTH;
if (currentOffset >= dataByteArray.length) {
return null;
}
byteBuffer.position(currentOffset);
int currentPrefix = byteBuffer.getInt();
if (currentPrefix > phoneNumberPrefix) {
right = middle - 1;
} else if (currentPrefix < phoneNumberPrefix) {
left = middle + 1;
} else {
int infoBeginOffset = byteBuffer.getInt();
int phoneType = byteBuffer.get();
int infoLength = -1;
for (int i = infoBeginOffset; i < indexAreaOffset; ++i) {
if (dataByteArray[i] == 0) {
infoLength = i - infoBeginOffset;
break;
}
}
String infoString = new String(dataByteArray, infoBeginOffset, infoLength, StandardCharsets.UTF_8);
String[] infoSegments = infoString.split("\\|");
PhoneNumberInfo phoneNumberInfo = new PhoneNumberInfo();
phoneNumberInfo.setPhoneNumber(phoneNumber);
phoneNumberInfo.setProvince(infoSegments[0]);
phoneNumberInfo.setCity(infoSegments[1]);
phoneNumberInfo.setZipCode(infoSegments[2]);
phoneNumberInfo.setAreaCode(infoSegments[3]);
phoneNumberInfo.setPhoneType(PHONE_NUMBER_TYPE[phoneType]);
return phoneNumberInfo;
}
}
return null;
}
public static void main(String[] args) {
PhoneNumberGeo phoneNumberGeo = new PhoneNumberGeo();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
System.out.println(phoneNumberGeo.lookup(scanner.next()));
}
}
}
package com.quantgroup.asset.distribution.util;
import lombok.Data;
/**
* @author shihuajun
* @date 2021/9/3 11:01
* @ describing
*/
@Data
public class PhoneNumberInfo {
private String phoneNumber;
private String province;
private String city;
private String zipCode;
private String areaCode;
private String phoneType;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment