Commit 4fb9311c authored by liwenbin's avatar liwenbin

xincheng

parent 6c62f5c6
...@@ -23,15 +23,15 @@ import lombok.extern.slf4j.Slf4j; ...@@ -23,15 +23,15 @@ import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.JedisPoolConfig;
/** /**
* *
* @author liwenbin * @author liwenbin
* *
*/ */
@Configuration @Configuration
@Slf4j @Slf4j
public class RedisConfig { public class RedisConfig {
@Value("${asset.data.redis.defaultExpiration}") @Value("${asset.data.redis.defaultExpiration}")
private Long defaultExpiration; private Long defaultExpiration;
@Value("${asset.redis.master.host}") @Value("${asset.redis.master.host}")
private String masterHost; private String masterHost;
......
package com.quantgroup.asset.distribution.constant;
/**
* @author : Hyuk
* @description : CodeConstants
* @date : 2020/6/4 6:50 下午
*/
public class CodeConstants {
public static final String SUCCESS = "0";
}
package com.quantgroup.asset.distribution.constant.aid;
/**
* 1-通过,0-审核拒绝,2-审核中
* @author : Hyuk
* @description : AidAuditResultConstants
* @date : 2020/7/9 12:22 上午
*/
public class AidAuditResultConstants {
/**
* 通过
*/
public static final int PASS = 1;
/**
* 拒绝
*/
public static final int REJECT = 0;
/**
* 审核中
*/
public static final int AUDITING = 2;
}
package com.quantgroup.asset.distribution.constant.aid;
/**
* @author : Hyuk
* @description : PreAuditTypeConstants
* @date : 2020/6/4 6:55 下午
*/
public class PreAuditTypeConstants {
/**
* 手机号MD5
*/
public static final int PHONE_NO_MD5 = 1;
/**
* 身份证号MD5(X大写)
*/
public static final int ID_CARD_MD5 = 2;
/**
* 手机号+身份证号MD5(X大写)
*/
public static final int PHONE_NO_ID_CARD_MD5 = 3;
/**
* 手机号或者身份证号MD5
*/
public static final int PHONE_NO_OR_ID_CARD_NO_MD5 = 4;
}
package com.quantgroup.asset.distribution.controller;
import com.alibaba.fastjson.JSON;
import com.quantgroup.asset.distribution.constant.AidFundConstants;
import com.quantgroup.asset.distribution.constant.AidFundStatus;
import com.quantgroup.asset.distribution.constant.StatusConstants;
import com.quantgroup.asset.distribution.constant.aid.AidAuditResultConstants;
import com.quantgroup.asset.distribution.enums.response.MiddleOfficeCommonResponseEnum;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.entity.aid.AidAuditResultEntity;
import com.quantgroup.asset.distribution.model.entity.aid.AidRsaParams;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.model.response.MiddleOfficeResponse;
import com.quantgroup.asset.distribution.service.aid.IAidFundInfoConfigService;
import com.quantgroup.asset.distribution.service.alarm.IAlarmService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRecordService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService;
import com.quantgroup.asset.distribution.service.funding.IAidAssetCommonService;
import com.quantgroup.asset.distribution.service.funding.IAidFundAuditOrderService;
import com.quantgroup.asset.distribution.service.jpa.entity.AidFundInfoConfig;
import com.quantgroup.asset.distribution.service.jpa.entity.AidLoanFundAuditOrder;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.niwodai.vo.NiwodaiIncomingResultResponseVO;
import com.quantgroup.asset.distribution.service.notify.INotifyService;
import com.quantgroup.asset.distribution.service.product.IFinanceProductService;
import com.quantgroup.asset.distribution.util.RsaUtils;
import com.quantgroup.asset.distribution.util.aid.AidAuditResultCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Map;
import java.util.Optional;
/**
* @author : Hyuk
* @description : AidCommonCallbackController
* @date : 2020/7/5 11:14 下午
*/
@RestController
@Slf4j
@RequestMapping("/distribution/aid/common/asset")
public class AidCommonCallbackController {
@Autowired
private IAlarmService alarmService;
@Autowired
private IAidFundInfoConfigService aidFundInfoConfigService;
@Autowired
private IAidFundAuditOrderService aidFundAuditOrderService;
@Autowired
private IAssetDistributeRecordService assetDistributeRecordService;
@Autowired
private IAssetDistributeService assetDistributeService;
@Autowired
private IFinanceProductService financeProductService;
@Autowired
private INotifyService notifyService;
// private IAidAssetCommonService
@RequestMapping("/{fund_id}/{fund_product_id}/audit_result_callback")
public MiddleOfficeResponse auditResultCallback(@PathVariable("fund_id") String fundId,
@PathVariable("fund_product_id") String fundProId,
@RequestBody AidRsaParams aidRsaParams) {
try {
QGPreconditions.checkArgument(StringUtils.isNoneEmpty(fundId, fundProId, aidRsaParams.getContent()),
QGExceptionType.AID_COMMON_AUDIT_RESULT_ORDER_ERROR, fundId, fundProId, aidRsaParams.getContent());
AidFundInfoConfig aidFundInfoConfig = aidFundInfoConfigService.findAidFundInfo(fundId, fundProId);
QGPreconditions.checkArgument(aidFundInfoConfig != null, QGExceptionType.UNKNOW_AID_FUND_ID, fundId);
String content = RsaUtils.decryptByPublicKey(aidRsaParams.getContent(), aidFundInfoConfig.getPublicKey());
log.info("通用助贷资方接收审核结果, fundId : {}, fundProductId : {}, content : {}", fundId, fundProId, content);
AidAuditResultEntity aidAuditResultEntity = JSON.parseObject(content, AidAuditResultEntity.class);
QGPreconditions.checkArgument(AidAuditResultCheckUtils.check(aidAuditResultEntity),
QGExceptionType.AID_COMMON_AUDIT_RESULT_ORDER_ERROR, fundId, fundProId, JSON.toJSONString(aidAuditResultEntity));
// 定位订单
AidLoanFundAuditOrder aidLoanFundAuditOrder = aidFundAuditOrderService.findByBizNoAndFundId(
aidAuditResultEntity.getOrderNo(), fundId);
QGPreconditions.checkArgument(aidLoanFundAuditOrder != null &&
(aidLoanFundAuditOrder.getAuditResult().equals(AidFundStatus.Incoming.WAIT) ||
aidLoanFundAuditOrder.getAuditResult().equals(AidFundStatus.Incoming.PRE)),
QGExceptionType.AID_COMMON_AUDIT_RESULT_ORDER_ERROR,
aidAuditResultEntity.getOrderNo(), fundId, aidLoanFundAuditOrder.getAuditResult());
// 开始处理审核结果
String orderNo = aidAuditResultEntity.getOrderNo();
if (aidAuditResultEntity.getAuditResult().equals(AidAuditResultConstants.AUDITING)) {
return MiddleOfficeResponse.created(MiddleOfficeCommonResponseEnum.SUCCESS);
}
AssetForm assetForm = JSON.parseObject(aidLoanFundAuditOrder.getAssetFormText(), AssetForm.class);
Asset asset = JSON.parseObject(aidLoanFundAuditOrder.getAssetText(), Asset.class);
Map<String, Object> dataMap = JSON.parseObject(aidLoanFundAuditOrder.getDataText(), Map.class);
// 审核拒绝
if (aidAuditResultEntity.getAuditResult().equals(AidAuditResultConstants.REJECT)) {
// 将助贷审核订单状态改为拒绝
aidFundAuditOrderService.updateOrderStatus(aidLoanFundAuditOrder, AidFundStatus.Incoming.REJECT);
// 将分发记录改为失败
assetDistributeRecordService.updateAssetDistributeStatus(orderNo, StatusConstants.FAIL);
// 重新进行分发
assetDistributeService.distribute(assetForm, asset, dataMap);
return MiddleOfficeResponse.created(MiddleOfficeCommonResponseEnum.SUCCESS);
}
// 审核通过
if (aidAuditResultEntity.getAuditResult().equals(AidAuditResultConstants.PASS)) {
aidLoanFundAuditOrder.setAuditContext(JSON.toJSONString(aidAuditResultEntity));
// 通过了直接通知资金系统
String finance = financeProductService.createSingletonFinanceProduct(aidAuditResultEntity.getAmount().toString(),
String.valueOf(aidAuditResultEntity.getTerm()), aidLoanFundAuditOrder.getFundId(), aidLoanFundAuditOrder.getFundProductId());
assetForm = financeProductService.checkFundResult(assetForm, finance, aidAuditResultEntity.getDeadLine());
assetForm.setAmount(aidAuditResultEntity.getAmount().toString());
assetForm.setTerm(String.valueOf(aidAuditResultEntity.getTerm()));
// 将助贷审核订单状态改为成功
aidFundAuditOrderService.updateOrderStatus(aidLoanFundAuditOrder, AidFundStatus.Incoming.PASS);
notifyService.notifyFundServer(assetForm, dataMap);
}
return MiddleOfficeResponse.created(MiddleOfficeCommonResponseEnum.SUCCESS);
} catch (QGException qx) {
log.error("助贷资方通用审核结果回调接口出现错误 : {}, fundId : {}, fundProductId : {}, aidRsaParams : {}", fundId,
fundProId, aidRsaParams);
alarmService.dingtalkAlarm("Warn", "助贷资方通用审核结果回调接口出现错误", "fundId : " +
fundId + " , fundProductId : " + fundProId + " , 错误信息 : " + qx.qgExceptionType.code + "->" + qx.detail);
} catch (Exception e) {
log.error("助贷资方通用审核结果回调接口出现未知异常, fundId : {}, fundProductId : {}, aidRsaParams : {}", fundId,
fundProId, aidRsaParams, e);
alarmService.dingtalkAlarm("Warn", "助贷资方通用审核结果回调接口出现未知错误", "fundId : " +
fundId + " , fundProductId : " + fundProId + " , 错误信息 : 未知错误");
}
return MiddleOfficeResponse.created(MiddleOfficeCommonResponseEnum.SUCCESS);
}
}
package com.quantgroup.asset.distribution.enums.response;
import lombok.Getter;
/**
* @author : Hyuk
* @description : MiddleOfficeCommonResponseEnum
* @date : 2020/6/4 6:29 下午
*/
public enum MiddleOfficeCommonResponseEnum {
// 0-success
SUCCESS("0", "success"),
// 4**客户端错误
// 401-权限错误
AUTH_ERROR("401", "权限校验失败"),
// 402-流量限制, 请求频繁
REQUEST_LIMIT("402", "请求次数过多"),
// 403-参数错误
REQUEST_PARAMS_ERROR("403", "参数有误"),
// 404-请求地址错误
REQUEST_URL_ERROR("404", "请求地址错误"),
// 405-并发错误, 客户端在一定维度单线程调用
CONCURRENT_REQUEST("405", "存在未结束的请求, 不允许再次调用"),
// 406-行为错误,客户端应该更换后续行为。此路不通,应该更换其他执行路径
REQUEST_PATH_ERROR("406", "行为错误,当前不能调用此接口"),
// 5**服务端错误
// 501-中间件错误
MIDDLEWARE_ERROR("407", "中间件服务出现异常"),
// 502-第三方服务不可用
THIRD_SERVER_ERROR("502", "第三方服务出现异常"),
// 600-未知错误
UN_KNOW_ERROR("600", "未知错误");
@Getter
private String code;
@Getter
private String msg;
MiddleOfficeCommonResponseEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
package com.quantgroup.asset.distribution.enums.user;
/**
* @author : Hyuk
* @description : EducationEnum
* @date : 2020/6/27 4:03 上午
*/
public enum EducationEnum {
MASTER("硕士及以上"),
UNDER_GRADUATE("本科"),
JUNIOR_COLLEGE("大专"),
TECHNICAL_SECONDARY_SCHOOL("中专"),
TECHNICAL_SCHOOL("技校"),
HIGH_SCHOOL("高中"),
MIDDLE_SCHOOL("初中"),
PRIMARY_SCHOOL("小学"),
OTHER("其他"),
UNKNOWN("暂无");
private String name;
EducationEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
package com.quantgroup.asset.distribution.enums.user;
/**
* @author : Hyuk
* @description : IncomeRangeEnum
* @date : 2020/6/27 4:10 上午
*/
public enum IncomeRangeEnum {
BELOW_1000("小于1000元"),
BELOW_3000("1000至3000元"),
BELOW_5000("3000至5000元"),
BELOW_8000("5000至8000元"),
BELOW_10000("8000至10000元"),
BELOW_15000("10000至15000元"),
BELOW_20000("15000至20000元"),
ABOVE_20000("大于20000元"),
UNKNOWN("暂无");
private String desc;
public String getDesc() {
return desc;
}
IncomeRangeEnum(String desc) {
this.desc = desc;
}
}
package com.quantgroup.asset.distribution.enums.user;
/**
* @author : Hyuk
* @description : MaritalStatusEnum
* @date : 2020/6/27 4:12 上午
*/
public enum MaritalStatusEnum {
SINGLE("未婚"),
MARRIED("已婚"),
DIVORCED("离异"),
WINDOWED("丧偶"),
OTHER("其他"),
UNKNOWN("未知");
private String desc;
MaritalStatusEnum(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
package com.quantgroup.asset.distribution.enums.user;
/**
* @author : Hyuk
* @description : OccupationEnum
* @date : 2020/6/27 4:09 上午
*/
public enum OccupationEnum {
WORKER("工人"),
TEACHER("教师"),
WHITE_COLLAR("白领"),
STUDENT("学生"),
CAREER_BUILDER("创业者"),
SELF_EMPLOYER("个体户"),
EMPLOYEE("公司职员"),
BISUNESS_ENTITY("企业法人"),
ONLINE_STORE_OWNER("网店店主"),
UNEMPLOYED("暂无职业"),
OTHER("其他"),
UNKNOWN("暂未填写");
private String name;
OccupationEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
...@@ -68,9 +68,13 @@ public enum QGExceptionType { ...@@ -68,9 +68,13 @@ public enum QGExceptionType {
UNKNOW_AID_FUND_ID(3016, "未知的助贷资方, fundId : %s"), UNKNOW_AID_FUND_ID(3016, "未知的助贷资方, fundId : %s"),
UNKNOW_PRE_AUDIT_TYPE(3017, "助贷资方未知的撞库方式, fundId : %s, preAuditType : %s"), UNKNOW_PRE_AUDIT_TYPE(3017, "助贷资方未知的撞库方式, fundId : %s, preAuditType : %s"),
USER_CONTACT_INFO_EMPTY(3018, "用户联系人方式为空, uuid : %s"), USER_CONTACT_INFO_EMPTY(3018, "用户联系人方式为空, uuid : %s"),
AID_COMMON_PRE_AUDIT_ERROR(3022, "助贷通用预审出现错误, uuid : %s, bizNo : %s, fundId : %s"),
AID_COMMON_AUDIT_ERROR(3023, "助贷通用进件接口出现错误, uuid : %s, bizNo : %s, fundId : %s"),
AID_COMMON_AUDIT_RESULT_ERROR(3024, "助贷回调URL或content内容错误, fundId : %s, fundProductId : %s, content : %s"),
AID_COMMON_AUDIT_RESULT_ORDER_ERROR(3026, "通用助贷结果接收订单状态异常, orderNo : %s, fundId : %s, orderStatus : %s"),
USER_OCR_INFO_IS_EMPTY(3018, "用户OCR信息为空, uuid : %s"), USER_OCR_INFO_IS_EMPTY(3019, "用户OCR信息为空, uuid : %s"),
LIVE_DATA_ERROR(3019, "活体数据获取失败, uuid : %s"), LIVE_DATA_ERROR(3020, "活体数据获取失败, uuid : %s"),
USER_LOAN_TYPE_IS_EMPTY(3021, "用户类型为空, uuid : %s"); USER_LOAN_TYPE_IS_EMPTY(3021, "用户类型为空, uuid : %s");
......
package com.quantgroup.asset.distribution.factory;
/**
* @author : Hyuk
* @description : Operation
* @date : 2020/7/9 12:40 上午
*/
public interface Operation<T> {
boolean check(T t);
}
package com.quantgroup.asset.distribution.model.entity;
import com.quantgroup.asset.distribution.service.niwodai.vo.IdCardA;
import com.quantgroup.asset.distribution.service.niwodai.vo.IdCardB;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : OcrIdCardEntity
* @date : 2020/6/5 6:34 下午
*/
@Data
public class OcrIdCardEntity implements Serializable {
private static final long serialVersionUID = 1L;
private IdCardA idCardA;
private IdCardB idCardB;
private String idCardBaseContentA;
private String idCardBaseContentB;
private String livePhotoContent;
}
package com.quantgroup.asset.distribution.model.entity.aid;
import com.quantgroup.asset.distribution.constant.aid.AidAuditResultConstants;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author : Hyuk
* @description : AidAuditResultEntity
* @date : 2020/7/6 12:47 上午
*/
@Data
public class AidAuditResultEntity implements Serializable {
private static final long serialVersionUID = 1L;
private String orderNo;
/**
* 1-通过,0-审核拒绝,2-审核中
*/
private Integer auditResult;
/**
* 审批金额
*/
private BigDecimal amount;
/**
* 审批期限
*/
private Integer term;
/**
* 月利率
*/
private String monthRate;
/**
* 日利率
*/
private String dayRate;
/**
* 额度有效期截止时间
*/
private Long deadLine;
}
package com.quantgroup.asset.distribution.model.entity.aid;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : AidContactsInfo
* @date : 2020/6/5 3:41 下午
*/
@Data
public class AidContactsInfo implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName;
private String firstRelation;
private String firstMobile;
private String secondName;
private String secondRelation;
private String secondMobile;
private String thirdName;
private String thirdRelation;
private String thirdMobile;
}
package com.quantgroup.asset.distribution.model.entity.aid;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : AidIncomingEntity
* @date : 2020/6/5 3:39 下午
*/
@Data
public class AidIncomingEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 订单号
*/
private String orderNo;
/**
* 基础信息箱
*/
private AidUserInfo userInfo;
/**
* 联系人信息
*/
private AidContactsInfo contactsInfo;
/**
* 借款申请信息
*/
private AidLoanInfo loanInfo;
/**
* 风控信息
*/
private AidRiskInfo riskInfo;
public AidIncomingEntity(String orderNo) {
this.orderNo = orderNo;
}
}
package com.quantgroup.asset.distribution.model.entity.aid;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : AidLoanInfo
* @date : 2020/6/5 3:50 下午
*/
@Data
public class AidLoanInfo implements Serializable {
private static final long serialVersionUID = 1L;
private String amount;
private int term;
private int purpose;
}
package com.quantgroup.asset.distribution.model.entity.aid;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author : Hyuk
* @description : AidRiskInfo
* @date : 2020/6/5 3:51 下午
*/
@Builder
@Data
public class AidRiskInfo implements Serializable {
private static final long serialVersionUID = 1L;
private int label;
/**
* 量子分3
*/
private BigDecimal qgScore3;
/**
* 量子分5
*/
private BigDecimal qgScore5;
/**
* 偿债能力评分
*/
private BigDecimal qgDebtPayingScore;
/**
* 量子风险等级手机号命中
*/
private String qgRiskLevelPhone;
/**
* 量子风险等级身份证号命中
*/
private String qgRiskLevelIdNo;
public AidRiskInfo() {}
public AidRiskInfo(int label, BigDecimal qgScore3, BigDecimal qgScore5, BigDecimal qgDebtPayingScore, String qgRiskLevelPhone, String qgRiskLevelIdNo) {
super();
this.label = label;
this.qgScore3 = qgScore3;
this.qgScore5 = qgScore5;
this.qgDebtPayingScore = qgDebtPayingScore;
this.qgRiskLevelPhone = qgRiskLevelPhone;
this.qgRiskLevelIdNo = qgRiskLevelIdNo;
}
}
package com.quantgroup.asset.distribution.model.entity.aid;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : AidRsaParams
* @date : 2020/7/6 4:35 下午
*/
@Builder
@Data
public class AidRsaParams implements Serializable {
private static final long serialVersionUID = 1L;
private String appId;
private String content;
public AidRsaParams(String appId, String content) {
super();
this.appId = appId;
this.content = content;
}
public AidRsaParams() {}
}
package com.quantgroup.asset.distribution.model.entity.aid;
import com.quantgroup.asset.distribution.model.entity.live.TencentLiveEntity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author : Hyuk
* @description : AidUserInfo
* @date : 2020/6/5 3:40 下午
*/
@Data
public class AidUserInfo implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String idCardNo;
private String phoneNo;
/**
* 教育程度
*/
private String education;
/**
* 职业
*/
private String occupation;
/**
* 月收入
*/
private String income;
/**
* 婚姻状况
*/
private String maritalStatus;
/**
* 详细居住地址
*/
private String address;
/**
* 负债情况
*/
private int debt;
/**
* 身份证有效期起始时间
*/
private String validDateBegin;
/**
* 身份证有效期截止时间
*/
private String validDateEnd;
/**
* 身份证户籍地址
*/
private String idCardAddress;
/**
* 性别
*/
private String gender;
/**
* 民族
*/
private String nation;
/**
* 发行机构
*/
private String agency;
/**
* 身份证正面找屁啊你
*/
private String idCardBaseContentA;
/**
* 身份证反面照片
*/
private String idCardBaseContentB;
/**
* 活体照片
*/
private String livePhotoContent;
/**
* 活体类型,0-腾讯
*/
private Integer liveType;
/**
* 活体分值
*/
private TencentLiveEntity liveResult;
private String companyName;
private String companyAddress;
private String email;
}
package com.quantgroup.asset.distribution.model.entity.live;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author : Hyuk
* @description : TencentLiveEntity
* @date : 2020/6/27 4:36 上午
*/
@Data
public class TencentLiveEntity implements Serializable {
private static final long serialVersionUID = 1L;
private BigDecimal similarity;
@JSONField(deserialize = false, serialize = false)
private BigDecimal liveRate;
}
package com.quantgroup.asset.distribution.model.entity.user;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author : Hyuk
* @description : SDKUserInfo
* @date : 2020/6/9 9:32 下午
*/
@Data
public class SDKUserInfo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String phoneNo;
private Long registerFrom;
private String uuid;
private String idNo;
private String gender;
private String qq;
private String email;
private String marryStatus;
private String educationEnum;
private String occupationEnum;
private String incomeRangeEnum;
private String incomeEnum;
private Boolean hasCar;
private Boolean hasSocialSecurity;
private Boolean hasHouse;
private Boolean hasCreditCard;
private List<UserAddressInfo> addressList;
private List<UserContactInfo> contactList;
}
package com.quantgroup.asset.distribution.model.entity.user;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : UserAddressInfo
* @date : 2020/6/27 3:55 上午
*/
@Data
public class UserAddressInfo implements Serializable {
private static final long serialVersionUID = 1L;
private Integer provinceCode;
private String province;
private Integer cityCode;
private String city;
private Integer districtCode;
private String district;
private String address;
public String getAddressDetail() {
StringBuilder address = new StringBuilder();
if (this.province != null) {
address.append(this.province);
}
if (this.city != null) {
address.append(this.city);
}
if (this.district != null) {
address.append(this.district);
}
if (this.address != null) {
address.append(this.address);
}
return address.toString();
}
}
package com.quantgroup.asset.distribution.model.entity.user;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : UserContactInfo
* @date : 2020/6/27 3:56 上午
*/
@Data
public class UserContactInfo implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String phoneNo;
private String relationName;
private String relation;
}
package com.quantgroup.asset.distribution.model.response;
import com.quantgroup.asset.distribution.enums.response.MiddleOfficeCommonResponseEnum;
import lombok.Data;
/**
* @author : Hyuk
* @description : MiddleOfficeResponse
* @date : 2020/6/4 6:28 下午
*/
@Data
public class MiddleOfficeResponse {
private String code;
private String msg;
private Object data;
public MiddleOfficeResponse() {}
public MiddleOfficeResponse(String code, String msg) {
this.code = code;
this.msg = msg;
}
public MiddleOfficeResponse(String code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static MiddleOfficeResponse created(MiddleOfficeCommonResponseEnum middleOfficeCommonResponseEnum) {
return new MiddleOfficeResponse(middleOfficeCommonResponseEnum.getCode(), middleOfficeCommonResponseEnum.getMsg());
}
public static MiddleOfficeResponse created(MiddleOfficeCommonResponseEnum middleOfficeCommonResponseEnum, Object data) {
return new MiddleOfficeResponse(middleOfficeCommonResponseEnum.getCode(), middleOfficeCommonResponseEnum.getMsg(), data);
}
}
package com.quantgroup.asset.distribution.service.aid;
import com.quantgroup.asset.distribution.service.jpa.entity.AidFundInfoConfig;
/**
* @author : Hyuk
* @description : IAidFundInfoService
* @date : 2020/6/9 8:19 下午
*/
public interface IAidFundInfoConfigService {
AidFundInfoConfig findAidFundInfo(String fundId, String fundProductId);
void clearAidFundInfoCache(String fundId, String fundProductId);;
}
package com.quantgroup.asset.distribution.service.aid.impl;
import com.quantgroup.asset.distribution.service.aid.IAidFundInfoConfigService;
import com.quantgroup.asset.distribution.service.jpa.entity.AidFundInfoConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAidFundInfoConfigRepository;
import com.quantgroup.asset.distribution.service.redis.IRedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author : Hyuk
* @description : AidFundInfoConfigServiceImpl
* @date : 2020/6/9 8:21 下午
*/
@Slf4j
@Service
public class AidFundInfoConfigServiceImpl implements IAidFundInfoConfigService {
@Autowired
private IAidFundInfoConfigRepository aidFundInfoConfigRepository;
@Autowired
private IRedisService<AidFundInfoConfig> redisService;
private static final String AID_FUND_INFO_CONFIG_KEY_PREFIX = "ASSET_DISTRIBUTION:AID_FUND_INFO_CONFIG:AMV8N:";
@Override
public AidFundInfoConfig findAidFundInfo(String fundId, String fundProductId) {
String redisKey = getAidFundInfoConfigKey(fundId, fundProductId);
// AidFundInfoConfig aidFundInfoConfig = redisService.getEntity(redisKey);
AidFundInfoConfig aidFundInfoConfig = null;
if (aidFundInfoConfig == null) {
List<AidFundInfoConfig> aidFundInfoConfigs = aidFundInfoConfigRepository.findByFundIdAndFundProductIdAndEnableIsTrue(fundId, fundProductId);
if (CollectionUtils.isNotEmpty(aidFundInfoConfigs)) {
aidFundInfoConfig = aidFundInfoConfigs.get(0);
redisService.setEntityEx(redisKey, aidFundInfoConfig, 5, TimeUnit.MINUTES);
}
}
return aidFundInfoConfig;
}
@Override
public void clearAidFundInfoCache(String fundId, String fundProductId) {
redisService.del(getAidFundInfoConfigKey(fundId, fundProductId));
}
/**
* 获取AidFundInfoConfig缓存key
* @param fundId
* @param fundProductId
* @return
*/
private String getAidFundInfoConfigKey(String fundId, String fundProductId) {
StringBuilder sb = new StringBuilder(AID_FUND_INFO_CONFIG_KEY_PREFIX);
sb.append(fundId).append(":").append(fundProductId);
return sb.toString();
}
}
package com.quantgroup.asset.distribution.service.funding;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import java.util.Map;
/**
* @author : Hyuk
* @description : IAidAssetCommonService
* @date : 2020/6/4 6:28 下午
*/
public interface IAidAssetCommonService {
/**
* 助贷资方通用预审接口
* @param assetForm
* @param fundId
* @param fundProductId
* @param data
* @return
*/
boolean preAudit(AssetForm assetForm, String fundId, String fundProductId, Map<String, Object> data);
/**
* 助贷资方通用审核接口
* @param assetForm
* @param asset
* @param data
* @param fundId
* @param fundProductId
* @return
*/
boolean audit(AssetForm assetForm, Asset asset, Map<String, Object> data, String fundId, String fundProductId);
/**
* 审核结果查询
* @param assetForm
* @param asset
* @param fundId
* @param fundProductId
*/
void auditResult(AssetForm assetForm, Asset asset, String fundId, String fundProductId);
}
...@@ -23,7 +23,8 @@ public interface IAidFundAssetService { ...@@ -23,7 +23,8 @@ public interface IAidFundAssetService {
* 进件审核 * 进件审核
* @param assetForm * @param assetForm
* @param data * @param data
* @param userLoanType * @param asset
* @param fundId
* @return true:进件成功 false:进件失败 * @return true:进件成功 false:进件失败
*/ */
public boolean audit(AssetForm assetForm, Map<String, Object> data, Asset asset, String fundId); public boolean audit(AssetForm assetForm, Map<String, Object> data, Asset asset, String fundId);
......
package com.quantgroup.asset.distribution.service.funding.impl;
import cn.quantgroup.motan.bean.UserInfo;
import cn.quantgroup.motan.vo.UserSysResult;
import cn.quantgroup.user.IUserSdkService;
import cn.quantgroup.user.UserSdkServiceFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lkb.data.hbase.dataservice.verify.OCRIdCardDataService;
import com.lkb.data.hbase.row.verify.OCRIdCardRow;
import com.quantgroup.asset.distribution.constant.CodeConstants;
import com.quantgroup.asset.distribution.constant.aid.PreAuditTypeConstants;
import com.quantgroup.asset.distribution.enums.user.EducationEnum;
import com.quantgroup.asset.distribution.enums.user.IncomeRangeEnum;
import com.quantgroup.asset.distribution.enums.user.MaritalStatusEnum;
import com.quantgroup.asset.distribution.enums.user.OccupationEnum;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.entity.OcrIdCardEntity;
import com.quantgroup.asset.distribution.model.entity.aid.*;
import com.quantgroup.asset.distribution.model.entity.live.TencentLiveEntity;
import com.quantgroup.asset.distribution.model.entity.user.SDKUserInfo;
import com.quantgroup.asset.distribution.model.entity.user.UserAddressInfo;
import com.quantgroup.asset.distribution.model.entity.user.UserContactInfo;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.MiddleOfficeResponse;
import com.quantgroup.asset.distribution.service.aid.IAidFundInfoConfigService;
import com.quantgroup.asset.distribution.service.funding.IAidAssetCommonService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
import com.quantgroup.asset.distribution.service.jpa.entity.AidFundInfoConfig;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.niwodai.vo.IdCardA;
import com.quantgroup.asset.distribution.service.niwodai.vo.IdCardB;
import com.quantgroup.asset.distribution.service.user.IUserCenterService;
import com.quantgroup.asset.distribution.util.MD5Util;
import com.quantgroup.asset.distribution.util.OcrUtils;
import com.quantgroup.asset.distribution.util.RsaUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author : Hyuk
* @description : AidAssetCommonServiceImpl
* @date : 2020/6/4 6:32 下午
*/
@Slf4j
@Service
public class AidAssetCommonServiceImpl implements IAidAssetCommonService {
//TODO
@Value("${opearotr.server.domain}")
private String operatorDomain;
@Autowired
private IAidFundInfoConfigService aidFundInfoConfigService;
@Autowired
private IHttpService httpService;
@Autowired
private IUserCenterService userCenterService;
@Override
public boolean preAudit(AssetForm assetForm, String fundId, String fundProductId, Map<String, Object> data) {
try {
AidFundInfoConfig aidFundInfoConfig = aidFundInfoConfigService.findAidFundInfo(fundId, fundProductId);
String preAuditUrl = aidFundInfoConfig.getPreAuditUrl();
int preAuditType = PreAuditTypeConstants.PHONE_NO_OR_ID_CARD_NO_MD5;
Map<String, String> requestParams = getPreAuditParams(assetForm.getUuid(), fundId, fundProductId, preAuditType);
MiddleOfficeResponse response = request(preAuditUrl, JSON.toJSONString(requestParams), aidFundInfoConfig.getPrivateKey(), aidFundInfoConfig.getPublicKey());
if (CodeConstants.SUCCESS.equals(response.getCode())) {
return true;
}
return false;
} catch (Exception e) {
log.error("助贷资方通用预审接口出现错误, uuid : {}, bizNo : {}, fundId : {}", assetForm.getUuid(), assetForm.getBizNo(), fundId, e);
throw new QGException(QGExceptionType.AID_COMMON_PRE_AUDIT_ERROR, assetForm.getUuid(), assetForm.getBizNo(), fundId);
}
}
@Override
public boolean audit(AssetForm assetForm, Asset asset, Map<String, Object> data, String fundId, String fundProductId) {
try {
AidFundInfoConfig aidFundInfoConfig = aidFundInfoConfigService.findAidFundInfo(fundId, fundProductId);
String requestURL = aidFundInfoConfig.getAuditUrl();
// 用户中心相关信息, 这里不可能为空,不然预审就拦截住了
UserInfo userInfo = userCenterService.getUserInfoByUuid(assetForm.getUuid());
SDKUserInfo sdkUserInfo = userCenterService.getSDKUserExtInfo(userInfo.getPhoneNo(), assetForm.getUuid());
QGPreconditions.checkArgument(sdkUserInfo != null, QGExceptionType.GET_USER_INFO_ERROR, assetForm.getUuid());
AidIncomingEntity aidIncomingEntity = new AidIncomingEntity(assetForm.getBizNo());
aidIncomingEntity.setUserInfo(createdAidUserInfo(userInfo, sdkUserInfo, assetForm.getUuid()));
aidIncomingEntity.setContactsInfo(createdAidContactsInfo(sdkUserInfo.getContactList(), assetForm.getUuid()));
aidIncomingEntity.setLoanInfo(createdAidLoanInfo(assetForm.getUuid()));
aidIncomingEntity.setRiskInfo(createdAidRiskInfo(assetForm.getUuid(), data));
MiddleOfficeResponse response = request(requestURL, JSON.toJSONString(aidIncomingEntity), aidFundInfoConfig.getPrivateKey(), aidFundInfoConfig.getPublicKey());
if (CodeConstants.SUCCESS.equals(response.getCode())) {
return true;
}
return false;
} catch (Exception e) {
log.error("助贷资方通用进件接口出现错误, uuid : {}, bizNo : {}, fundId : {}", assetForm.getUuid(), assetForm.getBizNo(), fundId, e);
throw new QGException(QGExceptionType.AID_COMMON_AUDIT_ERROR, assetForm.getUuid(), assetForm.getBizNo(), fundId);
}
}
@Override
public void auditResult(AssetForm assetForm, Asset asset, String fundId, String fundProductId) {
try {
String url = "https://sit02-third.n-orange.com/webservice/api/lhp/v1/credit/applyResult";
AidFundInfoConfig aidFundInfoConfig = aidFundInfoConfigService.findAidFundInfo(fundId, fundProductId);
Map<String, String> params = new HashMap<>();
params.put("orderNo", assetForm.getBizNo());
MiddleOfficeResponse response = request(url, JSON.toJSONString(params), aidFundInfoConfig.getPrivateKey(), aidFundInfoConfig.getPublicKey());
} catch (Exception e) {
log.error("111", e);
}
}
/**
* 获取撞库接口Map
* @param uuid
* @param fundId
* @param fundProductId
* @param preAuditType
* @return
*/
public Map<String, String> getPreAuditParams(String uuid, String fundId, String fundProductId, int preAuditType) {
UserInfo userInfo = userCenterService.getUserInfoByUuid(uuid);
if (userInfo == null){
log.error("通用助贷资方推送获取用户中心信息失败 uuid : {}",uuid, fundId, fundProductId, preAuditType);
throw new QGException(QGExceptionType.GET_USER_INFO_ERROR, uuid);
}
String name = userInfo.getName();
String idNo = userInfo.getIdNo();
String phoneNo = userInfo.getPhoneNo();
if (StringUtils.isAnyEmpty(name, idNo, phoneNo)) {
log.info("通用助贷资方推送,用户三要素部分缺失, fundId : {}, fundProductId : {}, uuid : {}");
throw new QGException(QGExceptionType.GET_USER_INFO_ERROR, uuid);
}
Map<String, String> requestParams = new HashMap<>();
requestParams.put("type", String.valueOf(preAuditType));
switch (preAuditType) {
case PreAuditTypeConstants.PHONE_NO_MD5 : {
requestParams.put("phoneNo", MD5Util.md5(phoneNo));
break;
}
case PreAuditTypeConstants.ID_CARD_MD5 : {
requestParams.put("idCardNo", MD5Util.md5(idNo.replaceAll("x", "X")));
break;
}
case PreAuditTypeConstants.PHONE_NO_ID_CARD_MD5 : {
String param = phoneNo + idNo.replaceAll("x", "X");
requestParams.put("exData", MD5Util.md5(param));
break;
}
case PreAuditTypeConstants.PHONE_NO_OR_ID_CARD_NO_MD5 : {
requestParams.put("phoneNo", MD5Util.md5(phoneNo));
requestParams.put("idCardNo", MD5Util.md5(idNo.replaceAll("x", "X")));
requestParams.put("name", name);
break;
}
default:
throw new QGException(QGExceptionType.UNKNOW_PRE_AUDIT_TYPE, fundId, preAuditType);
}
return requestParams;
}
/**
* 创建助贷通用UserInfo
* @param userInfo
* @param sdkUserInfo
* @param uuid
* @return
*/
private AidUserInfo createdAidUserInfo(UserInfo userInfo, SDKUserInfo sdkUserInfo, String uuid) {
AidUserInfo aidUserInfo = new AidUserInfo();
List<OCRIdCardRow> rows = OCRIdCardDataService.get(uuid);
QGPreconditions.checkArgument(!CollectionUtils.isEmpty(rows), QGExceptionType.FUND_PRIORITY_IS_ERROR, uuid);
OcrIdCardEntity ocrIdCardEntity = OcrUtils.transForm(rows.get(0));
aidUserInfo.setName(ocrIdCardEntity.getIdCardA().getName());
aidUserInfo.setIdCardNo(ocrIdCardEntity.getIdCardA().getCitizen_id().replaceAll("x", "X"));
aidUserInfo.setPhoneNo(userInfo.getPhoneNo());
aidUserInfo.setEducation(sdkUserInfo.getEducationEnum());
aidUserInfo.setOccupation(sdkUserInfo.getOccupationEnum());
aidUserInfo.setIncome(sdkUserInfo.getIncomeRangeEnum());
aidUserInfo.setMaritalStatus(sdkUserInfo.getMarryStatus());
UserAddressInfo addressInfo = sdkUserInfo.getAddressList().get(0);
aidUserInfo.setAddress(addressInfo.getAddressDetail());
aidUserInfo.setValidDateBegin(ocrIdCardEntity.getIdCardB().getValid_date_begin());
aidUserInfo.setValidDateEnd(ocrIdCardEntity.getIdCardB().getValid_date_end());
aidUserInfo.setIdCardAddress(ocrIdCardEntity.getIdCardA().getAddress());
aidUserInfo.setGender("男".equals(ocrIdCardEntity.getIdCardA().getGender()) ? "1" : "2");
aidUserInfo.setNation(ocrIdCardEntity.getIdCardA().getNation());
aidUserInfo.setAgency(ocrIdCardEntity.getIdCardB().getAgency());
aidUserInfo.setIdCardBaseContentA(ocrIdCardEntity.getIdCardBaseContentA());
aidUserInfo.setIdCardBaseContentB(ocrIdCardEntity.getIdCardBaseContentB());
aidUserInfo.setLivePhotoContent(ocrIdCardEntity.getLivePhotoContent());
// 0-腾讯, 增加了就去写个枚举
aidUserInfo.setLiveType(0);
TencentLiveEntity tencentLiveEntity = getTencentLiveEntity(uuid);
aidUserInfo.setLiveResult(tencentLiveEntity);
aidUserInfo.setEmail(sdkUserInfo.getEmail());
return aidUserInfo;
}
/**
* 创建助贷通用联系人信息
* @param uuid
* @return
*/
private AidContactsInfo createdAidContactsInfo(List<UserContactInfo> contactInfoList, String uuid) {
QGPreconditions.checkArgument(!CollectionUtils.isEmpty(contactInfoList), QGExceptionType.USER_CONTACT_INFO_EMPTY, uuid);
AidContactsInfo aidContactsInfo = new AidContactsInfo();
aidContactsInfo.setFirstName(contactInfoList.get(0).getName());
aidContactsInfo.setFirstMobile(contactInfoList.get(0).getPhoneNo());
aidContactsInfo.setFirstRelation(contactInfoList.get(0).getRelationName());
if (contactInfoList.size() > 1) {
aidContactsInfo.setSecondName(contactInfoList.get(1).getName());
aidContactsInfo.setSecondMobile(contactInfoList.get(1).getPhoneNo());
aidContactsInfo.setSecondRelation(contactInfoList.get(1).getRelationName());
}
return aidContactsInfo;
}
/**
* 创建助贷通用借款申请相关信息
* @param uuid
* @return
*/
private AidLoanInfo createdAidLoanInfo(String uuid) {
return null;
}
/**
* 创建助贷通用风控信息
* @param uuid
* @param data
* @return
*/
private AidRiskInfo createdAidRiskInfo(String uuid, Map<String, Object> data) {
// TODO
return AidRiskInfo.builder()
.label(1)
.qgScore3(new BigDecimal("0.3484291211465728"))
.qgScore5(new BigDecimal("0.4391283915198491"))
.qgDebtPayingScore(new BigDecimal("42"))
.qgRiskLevelPhone("B1")
.qgRiskLevelIdNo("B1")
.build();
}
/**
* 获取腾讯活体结果
* @param uuid
* @return
*/
private TencentLiveEntity getTencentLiveEntity(String uuid) {
String url = operatorDomain + "/auth-center/ex/face/getOcrData.json";
Map<String, String> params = new HashMap<>();
params.put("uuid", uuid);
// 以后增加活体类型记得增加枚举
params.put("liveType", "teng_xun");
String result = httpService.post(url, params);
JSONObject data = JSON.parseObject(result);
QGPreconditions.checkArgument(data != null , QGExceptionType.LIVE_DATA_ERROR, uuid);
if ("0".equals(data.getString("code")) && "0".equals(data.getString("business_code"))) {
return JSON.parseObject(data.getString("data"), TencentLiveEntity.class);
}
return null;
}
/**
* 创建包装助贷资方对象
* @param data
* @param privateKey
* @return
*/
private String createRequestParams(String data, String privateKey) throws Exception {
AidRsaParams aidRsaParams = AidRsaParams.builder()
.appId("1050")
.content(RsaUtils.encryptByPrivateKey(data, privateKey))
.build();
return JSON.toJSONString(aidRsaParams);
}
/**
* 通用请求,包装加密和解密
* @param url
* @param data
* @return
*/
private MiddleOfficeResponse request(String url, String data, String privateKey, String publicKey) throws Exception {
String text = httpService.postJson(url, createRequestParams(data, privateKey));
AidRsaParams aidRsaParams = JSON.parseObject(text, AidRsaParams.class);
String result = RsaUtils.decryptByPublicKey(aidRsaParams.getContent(), publicKey);
log.info("通用助贷资方请求结束, url : {}, data : {}, result : {}", url, data, result);
MiddleOfficeResponse response = JSON.parseObject(result, MiddleOfficeResponse.class);
return response;
}
public static void main(String[] args) {
String text = "{\"content\":\"cCdElnqK1w3GRfuz9seRmo7fY3iJQNFoDRvpBdg8maIhJ/IzOBQQdeqxhxT14cJ1oT/4pHazsTNK\\r\\ngmGARtFR1SPi9kSa7/MdVTibOp1p+rzbe1tVHSL/GFuQPgglgQakZ1EnoiLj5jTwRBA29n4EgN4+\\r\\nalq95YC1Y+Rq1k4RyrU=\\r\\n\"}";
AidRsaParams aidRsaParams = JSON.parseObject(text, AidRsaParams.class);
System.out.println(aidRsaParams);
}
}
...@@ -64,7 +64,11 @@ public interface IHttpService { ...@@ -64,7 +64,11 @@ public interface IHttpService {
public String post(String uri, Map<String, String> headers,Map<String, String> parameters, boolean isLog); public String post(String uri, Map<String, String> headers,Map<String, String> parameters, boolean isLog);
public String postJson(String uri, Map<String, String> headers, String jsonParams) ; public String postJson(String uri, Map<String, String> headers, String jsonParams) ;
String postJson(String uri, String jsonParams);
String postJson(String uri, Map<String, String> params);
public String postObj(String uri, Map<String, Object> parameters); public String postObj(String uri, Map<String, Object> parameters);
public String postObj(String uri, Map<String, String> headers, Map<String, Object> parameters) ; public String postObj(String uri, Map<String, String> headers, Map<String, Object> parameters) ;
/** /**
......
package com.quantgroup.asset.distribution.service.httpclient.impl; package com.quantgroup.asset.distribution.service.httpclient.impl;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gson.Gson; import com.google.gson.Gson;
...@@ -44,6 +45,8 @@ public class HttpServiceImpl implements IHttpService { ...@@ -44,6 +45,8 @@ public class HttpServiceImpl implements IHttpService {
private static final int TIME_OUT_60 = 60 * 1000; private static final int TIME_OUT_60 = 60 * 1000;
private static final int TIME_OUT_20 = 30 * 1000; private static final int TIME_OUT_20 = 30 * 1000;
private static Map<String, String> defaultJsonHeaders;
@Autowired @Autowired
@Qualifier("httpClient") @Qualifier("httpClient")
private CloseableHttpClient httpClient; private CloseableHttpClient httpClient;
...@@ -51,6 +54,11 @@ public class HttpServiceImpl implements IHttpService { ...@@ -51,6 +54,11 @@ public class HttpServiceImpl implements IHttpService {
@Qualifier("niwodaiHttpsClient") @Qualifier("niwodaiHttpsClient")
private CloseableHttpClient niwodaiHttpsClient; private CloseableHttpClient niwodaiHttpsClient;
static {
defaultJsonHeaders = new HashMap<>();
defaultJsonHeaders.put("Content-Type", "application/json");
}
@Override @Override
public String get(String uri) { public String get(String uri) {
return get(uri, null, null); return get(uri, null, null);
...@@ -104,6 +112,17 @@ public class HttpServiceImpl implements IHttpService { ...@@ -104,6 +112,17 @@ public class HttpServiceImpl implements IHttpService {
public String postJson(String uri, Map<String, String> headers, String jsonParams) { public String postJson(String uri, Map<String, String> headers, String jsonParams) {
return doJsonHttp(RequestBuilder.post(),uri,headers,jsonParams); return doJsonHttp(RequestBuilder.post(),uri,headers,jsonParams);
} }
@Override
public String postJson(String uri, String jsonParams) {
return postJson(uri, defaultJsonHeaders, jsonParams);
}
@Override
public String postJson(String uri, Map<String, String> params) {
return postJson(uri, defaultJsonHeaders, JSON.toJSONString(params));
}
@Override @Override
public String postObj(String uri, Map<String, Object> parameters) { public String postObj(String uri, Map<String, Object> parameters) {
return postObj(uri, null, parameters); return postObj(uri, null, parameters);
......
package com.quantgroup.asset.distribution.service.jpa.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author : Hyuk
* @description : AidFundInfoConfig
* @date : 2020/6/9 8:13 下午
*/
@Entity
@Table(name="aid_fund_info_config")
@Data
public class AidFundInfoConfig implements Serializable {
private static final long serialVersionUID = -1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "fund_id")
private String fundId;
@Column(name = "fund_product_id")
private String fundProductId;
@Column(name = "pre_audit_type")
private Integer preAuditType;
@Column(name = "private_key")
private String privateKey;
@Column(name = "public_key")
private String publicKey;
@Column(name = "pre_audit_url")
private String preAuditUrl;
@Column(name = "audit_url")
private String auditUrl;
@Column(name = "enable")
private Boolean enable;
@Column(name = "created_at")
private Timestamp createdAt;
@Column(name = "updated_at")
private Timestamp updatedAt;
@PrePersist
public void prePersist() {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
createdAt = timestamp;
updatedAt = timestamp;
}
@PreUpdate
public void preUpdate() {
updatedAt = new Timestamp(System.currentTimeMillis());
}
}
package com.quantgroup.asset.distribution.service.jpa.repository;
import com.quantgroup.asset.distribution.service.jpa.entity.AidFundInfoConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
* @author : Hyuk
* @description : IAidFundInfoConfigRepository
* @date : 2020/6/9 8:15 下午
*/
public interface IAidFundInfoConfigRepository extends JpaRepository<AidFundInfoConfig, Long> {
List<AidFundInfoConfig> findByFundIdAndFundProductIdAndEnableIsTrue(String fundId, String fundProductId);
}
package com.quantgroup.asset.distribution.service.user;
import cn.quantgroup.motan.bean.UserInfo;
import cn.quantgroup.motan.retbean.XUserExtInfo;
import com.quantgroup.asset.distribution.model.entity.user.SDKUserInfo;
/**
* @author : Hyuk
* @description : IUserCenterService
* @date : 2020/6/9 8:50 下午
*/
public interface IUserCenterService {
/**
* 根据uuid获取UserInfo
* @param uuid
* @return
*/
UserInfo getUserInfoByUuid(String uuid);
/**
* 根据手机号查询用户全量信息
* @param phoneNo
* @param uuid 打印日志用,方便后续根据日志定位问题
* @return
*/
SDKUserInfo getSDKUserExtInfo(String phoneNo, String uuid);
}
package com.quantgroup.asset.distribution.service.user.impl;
import cn.quantgroup.motan.bean.UserInfo;
import cn.quantgroup.motan.retbean.XUserExtInfo;
import cn.quantgroup.motan.vo.UserSysResult;
import cn.quantgroup.user.IUserSdkService;
import cn.quantgroup.user.UserSdkServiceFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.model.entity.user.SDKUserInfo;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
import com.quantgroup.asset.distribution.service.redis.IRedisService;
import com.quantgroup.asset.distribution.service.user.IUserCenterService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author : Hyuk
* @description : UserCenterServiceImpl
* @date : 2020/6/27 2:05 上午
*/
@Slf4j
@Service
public class UserCenterServiceImpl implements IUserCenterService {
@Value("${user.sdk.url}")
private String userSysUrl;
private IUserSdkService userSdkService;
@Autowired
@Qualifier("httpClient")
private CloseableHttpClient httpClient;
@Autowired
private IRedisService<UserInfo> redisService;
@Autowired
private IHttpService httpService;
/**
* UserInfo redisKey前缀
*/
private static final String USER_INFO_PRE_FIX = "ASSET_DISTRIBUTION:GET_USER_INFO_BY_UUID:MMNACH99:";
@PostConstruct
private void init() {
userSdkService = UserSdkServiceFactory.generateSDKService(userSysUrl, httpClient);
}
@Override
public UserInfo getUserInfoByUuid(String uuid) {
final String cacheKey = getUserInfoCacheKey(uuid);
UserInfo userInfo = redisService.getEntity(cacheKey);
if (userInfo == null) {
UserSysResult<UserInfo> result = userSdkService.findUserInfoByUuid(uuid);
if (result.isSuccess() && result.getData() != null) {
userInfo = result.getData();
redisService.setEntityEx(cacheKey, userInfo, 5, TimeUnit.MINUTES);
} else {
log.info("用户中心根据uuid查询userInfo失败, uuid : {}, result : {}", uuid, result);
}
}
return userInfo;
}
@Override
public SDKUserInfo getSDKUserExtInfo(String phoneNo, String uuid) {
// 这个暂时就先不做缓存了,如果后续有需求用到,再加上缓存,目前是一次性使用
String url = userSysUrl + "/innerapi/user-association/search/userId";
Map<String, String> params = new HashMap<>();
params.put("phoneNo", phoneNo);
String result = httpService.post(url, params);
JSONObject data = JSON.parseObject(result);
Boolean success = data.getBoolean("success");
if (!(success != null && success.booleanValue() && "0000".equals(data.getString("code"))
&& "0000".equals(data.getString("businessCode")))) {
log.info("用户中心根据phoneNo查询用户全量信息失败, phone : {}, result : {}", phoneNo, result);
return null;
}
SDKUserInfo sdkUserInfo = JSON.parseObject(data.getString("data"), SDKUserInfo.class);
return sdkUserInfo;
}
/**
* 获取UserInfo缓存key前缀
* @param uuid
* @return
*/
private static final String getUserInfoCacheKey(String uuid) {
return USER_INFO_PRE_FIX + uuid;
}
}
/**
*
*/
package com.quantgroup.asset.distribution.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MD5Util
*/
public class MD5Util {
private static final Logger logger = LoggerFactory.getLogger(MD5Util.class);
public static void main(String[] args) {
long timeunit = System.currentTimeMillis();
String appkey = "qaaaaa";
md5("timeunit=" + timeunit + "appkey=" + appkey);
}
/**
* md5加密
* @param content
* @return
*/
public static String md5(String content){
StringBuffer md5StrBuff =null;
try {
MessageDigest md5 = MessageDigest.getInstance("md5");
md5.update(content.getBytes());
byte[] domain = md5.digest();
md5StrBuff = new StringBuffer();
for (int i = 0; i < domain.length; i++) {
if (Integer.toHexString(0xFF & domain[i]).length() == 1) {
md5StrBuff.append("0").append(Integer.toHexString(0xFF & domain[i]));
} else{
md5StrBuff.append(Integer.toHexString(0xFF & domain[i]));
}
}
} catch (NoSuchAlgorithmException e) {
logger.error("md5 encrypt exception",e);
}
return md5StrBuff.toString();
}
}
package com.quantgroup.asset.distribution.util;
import com.alibaba.fastjson.JSON;
import com.lkb.data.hbase.row.verify.OCRIdCardRow;
import com.quantgroup.asset.distribution.model.entity.OcrIdCardEntity;
import com.quantgroup.asset.distribution.service.niwodai.vo.IdCardA;
import com.quantgroup.asset.distribution.service.niwodai.vo.IdCardB;
/**
* @author : Hyuk
* @description : OcrUtils
* @date : 2020/6/5 6:40 下午
*/
public class OcrUtils {
/**
* OCRIdCardRow转化成OcrIdCardEntity
* @param ocrIdCardRow
* @return
*/
public static OcrIdCardEntity transForm(OCRIdCardRow ocrIdCardRow) {
if (ocrIdCardRow == null) { return null; }
OcrIdCardEntity ocrIdCardEntity = new OcrIdCardEntity();
ocrIdCardEntity.setIdCardA(JSON.parseObject(ocrIdCardRow.getIdCardContentA(), IdCardA.class));
ocrIdCardEntity.setIdCardB(JSON.parseObject(ocrIdCardRow.getIdCardContentB(), IdCardB.class));
ocrIdCardEntity.setIdCardBaseContentA(ocrIdCardRow.getIdCardBaseContentA());
ocrIdCardEntity.setIdCardBaseContentB(ocrIdCardRow.getIdCardBaseContentB());
ocrIdCardEntity.setLivePhotoContent(ocrIdCardRow.getLivePhotoContent());
return ocrIdCardEntity;
}
}
package com.quantgroup.asset.distribution.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* @author : Hyuk
* @description : RsaUtils
* @date : 2020/7/1 11:23 上午
*/
public class RsaUtils {
private static final String CHAR_ENCODING = "UTF-8";
private static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";
/**
* 指定key的大小
*/
private static int KEYSIZE = 1024;
/** */
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/** */
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 生成密钥对
*/
public static Map<String, String> generateKeyPair() throws Exception {
/** RSA算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom();
/** 为RSA算法创建一个KeyPairGenerator对象 */
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
kpg.initialize(KEYSIZE, sr);
/** 生成密匙对 */
KeyPair kp = kpg.generateKeyPair();
/** 得到公钥 */
Key publicKey = kp.getPublic();
byte[] publicKeyBytes = publicKey.getEncoded();
String pub = new String(Base64.encodeBase64(publicKeyBytes), CHAR_ENCODING);
/** 得到私钥 */
Key privateKey = kp.getPrivate();
byte[] privateKeyBytes = privateKey.getEncoded();
String pri = new String(Base64.encodeBase64(privateKeyBytes), CHAR_ENCODING);
Map<String, String> map = new HashMap<String, String>();
map.put("publicKey", pub);
map.put("privateKey", pri);
RSAPublicKey rsp = (RSAPublicKey)kp.getPublic();
BigInteger bint = rsp.getModulus();
byte[] b = bint.toByteArray();
byte[] deBase64Value = Base64.encodeBase64(b);
String retValue = new String(deBase64Value);
map.put("modulus", retValue);
return map;
}
/**
* 加密方法 source: 源数据
*/
public static String encrypt(String source, String publicKey) throws Exception {
Key key = getPublicKey(publicKey);
/** 得到Cipher对象来实现对源数据的RSA加密 */
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] b = source.getBytes();
/** 执行加密操作 */
byte[] b1 = cipher.doFinal(b);
return new String(Base64.encodeBase64(b1), CHAR_ENCODING);
}
/**
* 解密算法 cryptograph:密文
*/
public static String decrypt(String cryptograph, String privateKey) throws Exception {
Key key = getPrivateKey(privateKey);
/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] b1 = Base64.decodeBase64(cryptograph.getBytes());
/** 执行解密操作 */
byte[] b = cipher.doFinal(b1);
return new String(b);
}
/**
* 得到公钥
*
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(key.getBytes()));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 得到私钥
*
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(key.getBytes()));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/** */
/**
* <P>
* 私钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** */
/**
* <p>
* 公钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {
byte[] keyBytes = java.util.Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* 公钥解密
* @param encryptedData Base64转换过的密文
* @param publicKey
* @return
* @throws Exception
*/
public static String decryptByPublicKey(String encryptedData, String publicKey) throws Exception {
byte[] base64 = org.apache.commons.net.util.Base64.decodeBase64(encryptedData);
return new String(RsaUtils.decryptByPublicKey(base64, publicKey), "utf-8");
}
/** */
/**
* <p>
* 公钥加密
* </p>
*
* @param data 源数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = java.util.Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** */
/**
* <p>
* 私钥加密
* </p>
*
* @param data 源数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/**
* 私钥加密, 加密返回Base64转换过的密文
* @param data
* @param privateKey
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String data, String privateKey) throws Exception {
return org.apache.commons.net.util.Base64.encodeBase64String(encryptByPrivateKey(data.getBytes(), privateKey));
}
}
package com.quantgroup.asset.distribution.util.aid;
import com.quantgroup.asset.distribution.constant.aid.AidAuditResultConstants;
import com.quantgroup.asset.distribution.factory.Operation;
import com.quantgroup.asset.distribution.model.entity.aid.AidAuditResultEntity;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* @author : Hyuk
* @description : AidAuditResultCheckUtils
* @date : 2020/7/9 12:41 上午
*/
public class AidAuditResultCheckUtils {
private static final Map<Integer, Operation<AidAuditResultEntity>> map = new HashMap<>();
static {
map.put(AidAuditResultConstants.AUDITING, (aidAuditResultEntity) -> checkOrderNo(aidAuditResultEntity));
map.put(AidAuditResultConstants.REJECT, (aidAuditResultEntity) -> checkOrderNo(aidAuditResultEntity));
map.put(AidAuditResultConstants.PASS, (aidAuditResultEntity) -> {
if (checkOrderNo(aidAuditResultEntity) && aidAuditResultEntity.getAmount() != null &&
aidAuditResultEntity.getTerm() != null && aidAuditResultEntity.getDeadLine() != null) {
return true;
}
return false;
});
}
private static boolean checkOrderNo(AidAuditResultEntity aidAuditResultEntity) {
return StringUtils.isNotEmpty(aidAuditResultEntity.getOrderNo());
}
public static final boolean check(AidAuditResultEntity aidAuditResultEntity) {
return Optional.ofNullable(map.get(aidAuditResultEntity.getAuditResult())).orElse((aidAuditResultEntity1 -> false)).check(aidAuditResultEntity);
}
}
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