package com.nova.sankuai.domain.api.zhongan;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.nova.sankuai.domain.entity.City;
|
import com.nova.sankuai.domain.entity.Customer;
|
import com.nova.sankuai.domain.enums.SourceTypeEnum;
|
import com.nova.sankuai.domain.enums.customerinfo.EnterpriseInfoEnum;
|
import com.nova.sankuai.domain.enums.customerinfo.MaritalStatusEnum;
|
import com.nova.sankuai.infra.config.CommonException;
|
import com.nova.sankuai.service.ICityService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.time.DateFormatUtils;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.Assert;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.text.ParseException;
|
import java.text.SimpleDateFormat;
|
import java.util.*;
|
|
/**
|
* <p>
|
* description
|
* </p>
|
*
|
* @author denglb 2021/11/16
|
*/
|
@Component
|
@Slf4j
|
public class ZhongAnUtil {
|
|
@Value("${rsa.local.privateKey}")
|
private String localPrivateKey;
|
@Value("${rsa.local.publicKey}")
|
private String localPublicKey;
|
@Value("${rsa.zhongan.publicKey}")
|
private String zhonganPublicKey;
|
@Value("${rsa.zhongan.appKey}")
|
private String zhonganAppKey;
|
@Value("${rsa.zhongan.creditApplyService}")
|
private String creditApplyService;
|
@Value("${rsa.zhongan.url}")
|
private String zhonganUrl;
|
@Value("${rsa.zhongan.callbackService}")
|
private String callbackService;
|
|
@Resource
|
private ICityService cityService;
|
|
private static final String API_NAME = "apiName";
|
private static final String CHANNEL_NO = "channelNo";
|
private static final String SUPPLIER_NO = "supplierNo";
|
private static final String REQ_DATE = "reqDate";
|
private static final String REQ_NO = "reqNo";
|
private static final String RESP_CODE = "respCode";
|
private static final String RESP_MSG = "respMsg";
|
private static final String RESP_NO = "respNo";
|
private static final String RESULT = "result";
|
private static final String THIRD_USER_NO = "thirdUserNo";
|
private static final String APPKEY = "appKey";
|
private static final String SERVICE_NAME = "serviceName";
|
private static final String BIZ_CONTENT = "bizContent";
|
private static final String TIMESTAMP = "timestamp";
|
private static final String FORMAT = "format";
|
private static final String SIGN_TYPE = "signType";
|
private static final String CHARSET = "charset";
|
private static final String VERSION = "version";
|
private static final String SIGN = "sign";
|
private static final String CERTI_NO = "certiNo";
|
private static final String PHONE = "phone";
|
private static final String IS_ALLOW_CREDIT = "isAllowCredit";
|
private static final String ERROR_CODE = "errorCode";
|
private static final String ERROR_MSG = "errorMsg";
|
private static final String VAL_CHANNEL_NO = "DL-ZAXD001";
|
private static final String VAL_CHARSET_DEFAULT = "UTF-8";
|
private static final String VAL_FORMAT_DEFAULT = "json";
|
private static final String VAL_SIGN_TYPE_DEFAULT = "RSA";
|
private static final String VAL_SUCCESS_CODE = "0000";
|
private static final String VAL_SUCCESS_MSG = "";
|
private static final String VAL_VERSION = "1.0.0";
|
|
public String buildAvailAmountResult(Customer customer, DuolaiRequest request) {
|
if (customer == null) {
|
throw new CommonException("未查询到相关信息");
|
}
|
AvailAmountQuery query = queryZhonganCustomerCardNo(request);
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
|
AvailAmountResult result = new AvailAmountResult();
|
result.setCreditAmount(BigDecimal.valueOf(customer.getLoanAmount()));
|
result.setUsedAmount(BigDecimal.valueOf(0));
|
result.setFrozenAmount(BigDecimal.valueOf(0));
|
result.setAvailableAmount(BigDecimal.valueOf(customer.getLoanAmount()));
|
result.setStartLoanAmount(BigDecimal.valueOf(customer.getLoanAmount()));
|
String applyDate = sdf.format(customer.getApplyDate());
|
result.setEffectiveDate(applyDate);
|
Calendar cal = Calendar.getInstance();
|
cal.setTime(customer.getApplyDate());
|
cal.add(Calendar.YEAR, 1);
|
result.setExpireDate(sdf.format(cal.getTime()));
|
result.setStatus(1);
|
result.setMaxLoanPeriods(12);
|
result.setSupportPeriods(Collections.singletonList(12));
|
Map<String, Object> respInner = new HashMap<>();
|
respInner.put(RESULT, result);
|
respInner.put(RESP_CODE, "0000");
|
respInner.put(RESP_MSG, "成功");
|
respInner.put(RESP_NO, UUID.randomUUID().toString());
|
respInner.put(REQ_NO, query.getReqNo());
|
//使用众安的公钥加密
|
String bizContent = SignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(respInner),
|
zhonganPublicKey);
|
return bizContent;
|
}
|
|
public Map<String, Object> buildAvailAmountResp(String bizContent, String resultCode, String resultMsg) {
|
Map<String, Object> resp = new HashMap<>();
|
resp.put(BIZ_CONTENT, bizContent);// 业务数据
|
resp.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
|
resp.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
|
resp.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
|
resp.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
|
resp.put(ERROR_CODE, resultCode == null ? "" : resultCode);// 错误码
|
resp.put(ERROR_MSG, resultMsg == null ? "" : resultMsg);// 错误信息
|
// 供应商的私钥加签
|
String sign = SignUtil.doSign(resp, localPrivateKey);
|
// sign签名当成请求入参
|
resp.put(SIGN, sign);
|
return resp;
|
}
|
|
public AvailAmountQuery queryZhonganCustomerCardNo(DuolaiRequest request) {
|
Map<String, Object> req = buildZhonganReq(request, creditApplyService);
|
String getSign = String.valueOf(req.get(SIGN));
|
// 使用众安的公钥验签
|
boolean verify = SignUtil.rsa256CheckContent(req, getSign, zhonganPublicKey);
|
Assert.isTrue(verify, "验签失败");
|
// 使用供应商的私钥解密
|
String decryptBizContent = SignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(req.get(BIZ_CONTENT)),
|
localPrivateKey);
|
log.info("众安参数:" + decryptBizContent);
|
AvailAmountQuery query = JSONObject.parseObject(decryptBizContent, AvailAmountQuery.class);
|
if (query == null || StringUtils.isBlank(query.getCertiNo())) {
|
log.error("接收参数异常:{}", query);
|
throw new CommonException("接收参数异常");
|
}
|
return query;
|
}
|
|
private DuolaiDto queryDuolaiDto(DuolaiRequest request) {
|
if (request == null) {
|
throw new CommonException("未接受到参数");
|
}
|
Map<String, Object> req = buildZhonganReq(request, creditApplyService);
|
String getSign = String.valueOf(req.get(SIGN));
|
// 使用众安的公钥验签
|
// boolean verify = SignUtil.rsa256CheckContent(req, getSign, zhonganPublicKey);
|
// Assert.isTrue(verify, "验签失败");
|
// 使用供应商的私钥解密
|
String decryptBizContent = SignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(req.get(BIZ_CONTENT)),
|
localPrivateKey);
|
log.info("众安参数:" + decryptBizContent);
|
DuolaiDto dto = JSONObject.parseObject(decryptBizContent, DuolaiDto.class);
|
return dto;
|
}
|
|
public Customer buildZhongAnCustomer(DuolaiRequest request) {
|
DuolaiDto dto = queryDuolaiDto(request);
|
Customer customer = new Customer();
|
OcrInfoDto infoDto = dto.getOcrInfoDto();
|
customer.setName(infoDto.getName());
|
customer.setPhone(dto.getMobile());
|
customer.setIdCard(infoDto.getCertiNo());
|
OtherCreditInfo otherCreditInfo = dto.getOtherCreditInfo();
|
City one = cityService.getOne(new LambdaQueryWrapper<City>().like(City::getName, otherCreditInfo.getContactCity()));
|
if (one != null) {
|
customer.setCity(one.getCityId());
|
customer.setCityName(one.getName());
|
}
|
customer.setSourceChannel(SourceTypeEnum.ZhongAn.getCode());
|
customer.setApplyDate(dto.getCreditApplyTime());
|
customer.setIdCardFrontPath(dto.getCertFrontImageId());
|
customer.setIdCardBackPath(dto.getCertBackImageId());
|
if (otherCreditInfo.getContact1Relation().equals(RelationshipEnum.PARENT.getCode())) {
|
customer.setRelationship("0");
|
customer.setRelationshipName(otherCreditInfo.getContact1Name());
|
customer.setRelationshipPhone(otherCreditInfo.getContact1Mobile());
|
} else if (otherCreditInfo.getContact1Relation().equals(RelationshipEnum.CHILD.getCode())) {
|
customer.setRelationship("1");
|
customer.setRelationshipName(otherCreditInfo.getContact1Name());
|
customer.setRelationshipPhone(otherCreditInfo.getContact1Mobile());
|
} else {
|
customer.setContact1Name(otherCreditInfo.getContact1Name());
|
customer.setContact1Phone(otherCreditInfo.getContact1Mobile());
|
}
|
if (otherCreditInfo.getContact2Relation().equals(RelationshipEnum.PARENT.getCode())) {
|
customer.setRelationship1("0");
|
customer.setRelationship1Name(otherCreditInfo.getContact2Name());
|
customer.setRelationship1Phone(otherCreditInfo.getContact2Mobile());
|
} else if (otherCreditInfo.getContact2Relation().equals(RelationshipEnum.CHILD.getCode())) {
|
customer.setRelationship1("1");
|
customer.setRelationship1Name(otherCreditInfo.getContact2Name());
|
customer.setRelationship1Phone(otherCreditInfo.getContact2Mobile());
|
} else {
|
customer.setContactName(otherCreditInfo.getContact2Name());
|
customer.setContactPhone(otherCreditInfo.getContact2Mobile());
|
}
|
customer.setEducation(queryEducation(otherCreditInfo.getFilledDegree()));
|
customer.setMaritalStatus(queryMarital(otherCreditInfo.getMarriage()));
|
customer.setMonthlyIncome(queryInCome(otherCreditInfo.getMonthlyPay()));
|
customer.setAddress(otherCreditInfo.getDetailedAddress());
|
customer.setAge(getAge(dto.getOcrInfoDto().getBirthday()));
|
if (StringUtils.isBlank(otherCreditInfo.getCompanyName())) {
|
customer.setEnterpriseInfo(EnterpriseInfoEnum.Enterprise_1.getCode());
|
} else {
|
customer.setEnterpriseInfo(EnterpriseInfoEnum.Enterprise_2.getCode());
|
}
|
customer.setLoanAmount(buildLoanAmount());
|
return customer;
|
}
|
|
private Double buildLoanAmount() {
|
Random random = new Random();
|
int i = random.nextInt(5) + 1;
|
return i * 10000.00;
|
}
|
|
private Integer getAge(String strDate) {
|
if (StringUtils.isBlank(strDate)) {
|
return null;
|
}
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
Date birthDay = null;
|
try {
|
birthDay = sdf.parse(strDate);
|
} catch (ParseException e) {
|
e.printStackTrace();
|
}
|
Calendar cal = Calendar.getInstance();
|
if (cal.before(birthDay)) { //出生日期晚于当前时间,无法计算
|
throw new IllegalArgumentException(
|
"The birthDay is before Now.It's unbelievable!");
|
}
|
int yearNow = cal.get(Calendar.YEAR); //当前年份
|
int monthNow = cal.get(Calendar.MONTH); //当前月份
|
int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
|
cal.setTime(birthDay);
|
int yearBirth = cal.get(Calendar.YEAR);
|
int monthBirth = cal.get(Calendar.MONTH);
|
int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
|
int age = yearNow - yearBirth; //计算整岁数
|
if (monthNow <= monthBirth) {
|
if (monthNow == monthBirth) {
|
if (dayOfMonthNow < dayOfMonthBirth) {
|
age--;
|
}//当前日期在生日之前,年龄减一
|
} else {
|
age--;//当前月份在生日之前,年龄减一1
|
}
|
}
|
return age;
|
}
|
|
private Integer queryInCome(Integer monthlyPay) {
|
for (MonthPayEnum m : MonthPayEnum.values()) {
|
if (m.getCode().equals(monthlyPay)) {
|
return m.getSys();
|
}
|
}
|
return null;
|
}
|
|
private String queryMarital(Integer marriage) {
|
for (MaritalStatusEnum maritalStatusEnum : MaritalStatusEnum.values()) {
|
return maritalStatusEnum.getSys();
|
}
|
return null;
|
}
|
|
private String queryEducation(Integer zhonganEducation) {
|
for (ZhonganEducationEnum educationEnum : ZhonganEducationEnum.values()) {
|
if (educationEnum.getCode().equals(zhonganEducation)) {
|
return educationEnum.getSys();
|
}
|
}
|
return null;
|
}
|
|
private Map<String, Object> buildZhonganReq(DuolaiRequest request, String serviceName) {
|
Map<String, Object> req = new HashMap<>();
|
req.put(APPKEY, zhonganAppKey);// appKey
|
req.put(SERVICE_NAME, serviceName);// serviceName
|
req.put(BIZ_CONTENT, request.getBizContent());// 业务数据
|
req.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
|
req.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
|
req.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
|
req.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
|
req.put(VERSION, VAL_VERSION);// API版本号
|
req.put(SIGN, request.getSign());
|
return req;
|
}
|
|
public Map<String, Object> buildZhonganResp(DuolaiRequest request, String status, String resultCode, String resultMsg) {
|
DuolaiDto dto = queryDuolaiDto(request);
|
CreditApplyResult result = new CreditApplyResult();
|
result.setOuterCreditApplyNo(result.getOuterCreditApplyNo());
|
result.setStatus(status);
|
result.setResultCode(resultCode);
|
result.setResultMsg(resultMsg);
|
|
Map<String, Object> respInner = new HashMap<>();
|
respInner.put(RESULT, result);
|
respInner.put(RESP_CODE, resultCode == null ? "0000" : resultCode);
|
respInner.put(RESP_MSG, resultMsg);
|
respInner.put(RESP_NO, UUID.randomUUID().toString());
|
respInner.put(REQ_NO, dto.getReqNo());
|
//使用众安的公钥加密
|
String bizContent = SignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(respInner),
|
zhonganPublicKey);
|
Map<String, Object> resp = new HashMap<>();
|
resp.put(BIZ_CONTENT, bizContent);// 业务数据
|
resp.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
|
resp.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
|
resp.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
|
resp.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
|
resp.put(ERROR_CODE, resultCode == null ? "" : resultCode);// 错误码
|
resp.put(ERROR_MSG, resultMsg == null ? "" : resultMsg);// 错误信息
|
// 供应商的私钥加签
|
String sign = SignUtil.doSign(resp, localPrivateKey);
|
// sign签名当成请求入参
|
resp.put(SIGN, sign);
|
return resp;
|
}
|
|
public void callback(DuolaiRequest request, String status, Double money) {
|
DuolaiDto dto = queryDuolaiDto(request);
|
Map<String, Object> map = new HashMap<>();
|
map.put(CHANNEL_NO, dto.getChannelNo());
|
map.put(REQ_DATE, dto.getReqDate());
|
map.put(REQ_NO, dto.getReqNo());
|
map.put(THIRD_USER_NO, dto.getThirdUserNo());
|
map.put("productCode", dto.getProductCode());
|
map.put("creditApplyNo", dto.getOuterCreditApplyNo());
|
map.put("status", status);
|
map.put("creditApplyTime", DateFormatUtils.format(dto.getCreditApplyTime(), "yyyy-MM-dd HH:mm:ss"));
|
if (ZhongAnStatus.STATUS_3.getCode().equals(status)) {
|
map.put("creditAmount", BigDecimal.valueOf(money));
|
map.put("availableAmount", BigDecimal.valueOf(money));
|
Calendar cal = Calendar.getInstance();
|
cal.setTime(dto.getCreditApplyTime());
|
cal.add(Calendar.YEAR, 1);
|
map.put("quotaInvalidDate", DateFormatUtils.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss"));
|
} else {
|
map.put("resultMsg", "订单常见失败");
|
}
|
|
//使用众安的公钥加密
|
String bizContent = SignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(map),
|
zhonganPublicKey);
|
Map<String, Object> req = new HashMap<>();
|
req.put(APPKEY, zhonganAppKey);// appKey
|
req.put(SERVICE_NAME, callbackService);// serviceName
|
req.put(BIZ_CONTENT, bizContent);// 业务数据
|
req.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
|
req.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
|
req.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
|
req.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
|
req.put(VERSION, VAL_VERSION);// API版本号
|
req.put(SUPPLIER_NO, request.getSupplierNo());//TODO 供应商发起请求该值必填,值为众安侧分配的编码
|
// 供应商的私钥加签
|
String sign = SignUtil.doSign(req, localPrivateKey);
|
// sign签名当成请求入参
|
req.put(SIGN, sign);
|
// HttpUtil.post(zhonganUrl, req);
|
}
|
}
|