DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/account/controller/UserWithdrawalController.java
@@ -115,7 +115,7 @@ userWithdrawal.setOutRequestNo(ToolUtil.getRandomString(32)); try { // 司机进件 Map<String, Object> resultMap = douGongBasicDataBiz.userBasicDataIndv(userWithdrawalReq); Map<String, Object> resultMap = douGongBasicDataBiz.userBasicDataIndv(userWithdrawal); String respCode = (String) resultMap.get("resp_code"); if(!"00000000".equals(respCode)) { return ResultUtil.error((String) resultMap.get("resp_desc")); @@ -131,7 +131,7 @@ userWithdrawal.setImgUrlOne(userWithdrawalReq.getIdCardReversePicture()); userWithdrawal.setIdCardFrontPicture(userWithdrawalReq.getCopy1()); userWithdrawal.setIdCardReversePicture(userWithdrawalReq.getCopy2()); userWithdrawal.setHuiFuId((String) resultMap.get("huifu_id")); userWithdrawal.setHuifuId((String) resultMap.get("huifu_id")); //调用汇付业务入驻接口 Map<String, Object> map = douGongBasicDataBiz.userBusinessOpen(userWithdrawal); if (!"00000000".equals(map.get("resp_code"))){ DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongBasicDataBiz.java
@@ -70,8 +70,10 @@ paramsInfo.put("name", userWithdrawal.getOpenAccountName()); // 个人证件号码 paramsInfo.put("cert_no", userWithdrawal.getCertificateCode()); // 管理员账号 paramsInfo.put("login_name", userWithdrawal.getPhone()); // 是否发送短信标识 paramsInfo.put("sms_send_flag", "1"); paramsInfo.put("sms_send_flag", "Y"); // 3. 发起API调用 log.info("个人用户基本信息开户请求参数:{}", paramsInfo); Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/basicdata/indv", paramsInfo, null, false); @@ -98,7 +100,7 @@ // 请求日期 paramsInfo.put("req_date", DateUtil.format(new Date(),"yyyyMMdd")); // 汇付客户Id paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); String[] certificateExpireDateArr = userWithdrawal.getCertificateExpireTime().split(","); String startDateStr = certificateExpireDateArr[0]; // 个人证件有效期开始日期 @@ -138,7 +140,7 @@ // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 @@ -150,7 +152,7 @@ // 结算卡信息 JSONObject cardInfo = new JSONObject(); cardInfo.put("card_type", "1"); cardInfo.put("card_name", userWithdrawal.getBindAcctName()); cardInfo.put("card_name", userWithdrawal.getOpenAccountName()); cardInfo.put("card_no", userWithdrawal.getBankCardCode()); cardInfo.put("prov_id", userWithdrawal.getBankCardProvinceCode()); cardInfo.put("area_id", userWithdrawal.getBankCardCityCode()); @@ -194,7 +196,7 @@ // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 @@ -228,7 +230,7 @@ paramsInfo.put("card_info", cardInfo.toJSONString()); log.info("用户业务入驻修改返回参数:{}", paramsInfo); // 3. 发起API调用 Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/open", paramsInfo, null, false);; Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/modify", paramsInfo, null, false);; log.info("用户业务入驻修改返回参数:{}", response); return response; } DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/UserWithdrawal.java
@@ -168,7 +168,7 @@ private Integer type; @ApiModelProperty(value = "汇付ID") private String huiFuId; private String huifuId; @ApiModelProperty(value = "取现卡序列号") private String tokenNo; DriverJYXTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RequestSeqUtil.java
New file @@ -0,0 +1,217 @@ package com.stylefeng.guns.core.util; import java.security.SecureRandom; import java.util.concurrent.atomic.AtomicLong; /** * 请求流水号生成工具类 * * <p>用于生成32位唯一请求流水号,格式:[前缀2位][日期8位][时间6位][毫秒3位][序列号13位]</p> * <p>示例:rQ202511141540078404299875651</p> * * <p>特性:</p> * <ul> * <li>线程安全:使用AtomicLong保证高并发环境下的唯一性</li> * <li>高性能:避免重复创建对象,优化内存使用</li> * <li>可配置:支持自定义前缀适应不同业务场景</li> * <li>高可靠:时间戳+随机数+序列号三重保障唯一性</li> * </ul> * * @author harley * @since 2025-11-14 */ public class RequestSeqUtil { /** * 默认前缀 */ private static final String DEFAULT_PREFIX = "RQ"; /** * 序列号生成器,保证线程安全 */ private static final AtomicLong SEQUENCE_GENERATOR = new AtomicLong(0); /** * 安全随机数生成器 */ private static final SecureRandom SECURE_RANDOM = new SecureRandom(); /** * 流水号总长度 */ private static final int TOTAL_LENGTH = 32; /** * 前缀长度 */ private static final int PREFIX_LENGTH = 2; /** * 日期长度 (yyyyMMdd) */ private static final int DATE_LENGTH = 8; /** * 时间长度 (HHmmss) */ private static final int TIME_LENGTH = 6; /** * 毫秒长度 */ private static final int MILLIS_LENGTH = 3; /** * 序列号长度 */ private static final int SEQUENCE_LENGTH = 13; /** * 私有构造函数,防止实例化 */ private RequestSeqUtil() { throw new UnsupportedOperationException("工具类不允许实例化"); } /** * 生成默认前缀的32位请求流水号 * * @return 32位请求流水号,格式:RQ + 时间信息 + 序列号 */ public static String generate() { return generate(DEFAULT_PREFIX); } /** * 生成指定前缀的32位请求流水号 * * <p>流水号格式:[前缀2位][日期8位][时间6位][毫秒3位][序列号13位]</p> * <p>示例:rQ202511141540078404299875651</p> * * @param prefix 自定义前缀,建议2位字符 * @return 32位请求流水号 * @throws IllegalArgumentException 当前缀为空或长度不符合要求时抛出 */ public static String generate(String prefix) { // 参数校验 if (prefix == null || prefix.isEmpty()) { throw new IllegalArgumentException("前缀不能为空"); } if (prefix.length() != PREFIX_LENGTH) { throw new IllegalArgumentException("前缀长度必须为" + PREFIX_LENGTH + "位"); } long currentTime = System.currentTimeMillis(); // 构建流水号各个部分 String datePart = DateUtil.format(new java.util.Date(currentTime), "yyyyMMdd"); String timePart = DateUtil.format(new java.util.Date(currentTime), "HHmmss"); String millisPart = String.format("%03d", currentTime % 1000); // 生成序列号(时间戳后7位 + 随机数6位) long sequence = SEQUENCE_GENERATOR.incrementAndGet(); String sequencePart = String.format("%013d", Math.abs(sequence % 1000000000000L)); // 组装完整的流水号 StringBuilder seqBuilder = new StringBuilder(TOTAL_LENGTH); seqBuilder.append(prefix) .append(datePart) .append(timePart) .append(millisPart) .append(sequencePart); return seqBuilder.toString(); } /** * 生成带业务标识的流水号 * * <p>常用的业务前缀:</p> * <ul> * <li>rQ - 汇付请求</li> * <li>OR - 订单业务</li> * <li>PY - 支付业务</li> * <li>RF - 退款业务</li> * </ul> * * @param businessCode 业务代码前缀 * @return 32位业务流水号 */ public static String generateForBusiness(String businessCode) { return generate(businessCode); } /** * 生成汇付相关的请求流水号 * * @return 以"rQ"为前缀的32位流水号 */ public static String generateForHuiFu() { return generate("rQ"); } /** * 验证流水号格式是否正确 * * @param sequence 要验证的流水号 * @return 验证结果 */ public static boolean isValid(String sequence) { if (sequence == null || sequence.length() != TOTAL_LENGTH) { return false; } // 验证时间部分格式(第3-16位应该是数字) String timePart = sequence.substring(2, 16); if (!timePart.matches("\\d+")) { return false; } // 验证最后13位序列号是否为数字 String sequencePart = sequence.substring(19); if (!sequencePart.matches("\\d+")) { return false; } return true; } /** * 从流水号中提取前缀 * * @param sequence 流水号 * @return 流水号前缀 */ public static String extractPrefix(String sequence) { if (sequence == null || sequence.length() < PREFIX_LENGTH) { return null; } return sequence.substring(0, PREFIX_LENGTH); } /** * 从流水号中提取时间信息 * * @param sequence 流水号 * @return 格式化的时间字符串,格式:yyyy-MM-dd HH:mm:ss.SSS */ public static String extractDateTime(String sequence) { if (!isValid(sequence)) { return null; } String dateStr = sequence.substring(2, 10); // yyyyMMdd String timeStr = sequence.substring(10, 16); // HHmmss String millisStr = sequence.substring(16, 19); // 毫秒 return dateStr.substring(0, 4) + "-" + dateStr.substring(4, 6) + "-" + dateStr.substring(6, 8) + " " + timeStr.substring(0, 2) + ":" + timeStr.substring(2, 4) + ":" + timeStr.substring(4, 6) + "." + millisStr; } } ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongBasicDataBiz.java
@@ -148,52 +148,66 @@ // 请求日期 paramsInfo.put("req_date", DateUtil.format(new Date(), "yyyyMMdd")); // 企业用户名称 paramsInfo.put("reg_name", "企业商户名称8225"); paramsInfo.put("reg_name", tEnterpriseWithdrawal.getBusinessLicenseCompanyName()); // 营业执照编号 paramsInfo.put("license_code", "20220222013747149"); // 证照有效期类型 paramsInfo.put("license_validity_type", "1"); paramsInfo.put("license_code", tEnterpriseWithdrawal.getBusinessLicenseCode()); String[] businessExpireTimeArr = tEnterpriseWithdrawal.getBusinessExpireTime().split(","); String startDateStr = businessExpireTimeArr[0]; // 证照有效期起始日期 paramsInfo.put("license_begin_date", "20200117"); // 证照有效期结束日期日期格式:yyyyMMdd; 非长期有效时必填;<font color="green">示例值:20320905</font> paramsInfo.put("license_end_date", "20400117"); paramsInfo.put("license_begin_date", startDateStr.replace("-", "")); // 照有效期结束日期日期格式:yyyyMMdd; 非长期有效时必填;<font color="green">示例值:20320905</font> String endDateStr = businessExpireTimeArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = endDateStr.replace("-", ""); paramsInfo.put("license_end_date", formatEndDate); // 证照有效期类型 paramsInfo.put("license_validity_type", "0"); } else { // 证照有效期类型 paramsInfo.put("license_validity_type", "1"); } // 注册地址(省) paramsInfo.put("reg_prov_id", "310000"); paramsInfo.put("reg_prov_id", tEnterpriseWithdrawal.getBusinessLicenseProvinceCode()); // 注册地址(市) paramsInfo.put("reg_area_id", "310100"); paramsInfo.put("reg_area_id", tEnterpriseWithdrawal.getBusinessLicenseCityCode()); // 注册地址(区) paramsInfo.put("reg_district_id", "310104"); paramsInfo.put("reg_district_id", tEnterpriseWithdrawal.getBusinessLicenseDistrictCode()); // 注册地址(详细信息) paramsInfo.put("reg_detail", "上海市宜山路"); paramsInfo.put("reg_detail", tEnterpriseWithdrawal.getBusinessLicenseAddress()); // 法人姓名 paramsInfo.put("legal_name", "陈立五"); paramsInfo.put("legal_name", tEnterpriseWithdrawal.getCorporateIdCardReversePicture()); // 法人证件类型 paramsInfo.put("legal_cert_type", "00"); paramsInfo.put("legal_cert_type", tEnterpriseWithdrawal.getCorporateCertificateType().equals(1) ? "00" : "11"); // 法人证件号码 paramsInfo.put("legal_cert_no", "321084198912066582"); // 法人证件有效期类型 paramsInfo.put("legal_cert_validity_type", "1"); paramsInfo.put("legal_cert_no", tEnterpriseWithdrawal.getCertificateCode()); String[] certificateExpireTimeArr = tEnterpriseWithdrawal.getCertificateExpireTime().split(","); String expireStartDateStr = certificateExpireTimeArr[0]; // 法人证件有效期开始日期 paramsInfo.put("legal_cert_begin_date", "20120801"); paramsInfo.put("legal_cert_begin_date", expireStartDateStr.replace("-", "")); // 法人证件有效期截止日期日期格式:yyyyMMdd; 非长期有效时必填,长期有效为空;<font color="green">示例值:20320905</font> paramsInfo.put("legal_cert_end_date", "20300801"); // 法人国籍法人的证件类型为外国人居留证时,必填,参见《[国籍编码](https://cloudpnrcdn.oss-cn-shanghai.aliyuncs.com/opps/api/prod/download_file/area/%E5%9B%BD%E7%B1%8D.xlsx)》<font color="green">示例值:CHN</font> paramsInfo.put("legal_cert_nationality", "test"); String expireEndDateStr = certificateExpireTimeArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = expireEndDateStr.replace("-", ""); paramsInfo.put("legal_cert_end_date", formatEndDate); // 法人证件有效期类型 paramsInfo.put("legal_cert_validity_type", "0"); } else { // 法人证件有效期类型 paramsInfo.put("legal_cert_validity_type", "1"); } // 联系人姓名 paramsInfo.put("contact_name", "小的"); paramsInfo.put("contact_name", tEnterpriseWithdrawal.getCorporateName()); // 联系人手机号 paramsInfo.put("contact_mobile", "13764462211"); paramsInfo.put("contact_mobile", tEnterpriseWithdrawal.getCorporatePhone()); // 管理员账号如需短信通知则必填;<font color="green">示例值:Lg20220222013747</font> paramsInfo.put("login_name", "Lg2022022201374721361"); paramsInfo.put("login_name", tEnterpriseWithdrawal.getCorporatePhone()); // 经营简称 paramsInfo.put("short_name", "企业商户"); // 联系人电子邮箱 paramsInfo.put("contact_email", "jeff.peng@huifu.com"); paramsInfo.put("short_name", tEnterpriseWithdrawal.getMerchantAbbreviation()); // 是否发送短信标识 paramsInfo.put("sms_send_flag", "1"); paramsInfo.put("sms_send_flag", "Y"); // 3. 发起API调用 Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/basicdata/ent", paramsInfo, null, false); ; log.info("企业用户基本信息开户返回参数:{}", JSONObject.toJSONString(response)); return response; } @@ -211,11 +225,74 @@ merConfig.setRsaPrivateKey(huiFuProperties.getRsaPrivateKey()); merConfig.setRsaPublicKey(huiFuProperties.getRsaPublicKey()); BasePay.initWithMerConfig(merConfig); // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); log.info("个人用户基本信息修改返回参数:{}", paramsInfo); // 请求流水号(动态生成,确保唯一性) paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DateUtil.format(new Date(), "yyyyMMdd")); paramsInfo.put("huifu_id", tEnterpriseWithdrawal.getHuifuId()); // 企业用户名称 paramsInfo.put("reg_name", tEnterpriseWithdrawal.getBusinessLicenseCompanyName()); // 经营简称 paramsInfo.put("short_name", tEnterpriseWithdrawal.getMerchantAbbreviation()); // 营业执照编号 paramsInfo.put("license_code", tEnterpriseWithdrawal.getBusinessLicenseCode()); String[] businessExpireTimeArr = tEnterpriseWithdrawal.getBusinessExpireTime().split(","); String startDateStr = businessExpireTimeArr[0]; // 证照有效期起始日期 paramsInfo.put("license_begin_date", startDateStr.replace("-", "")); // 照有效期结束日期日期格式:yyyyMMdd; 非长期有效时必填;<font color="green">示例值:20320905</font> String endDateStr = businessExpireTimeArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = endDateStr.replace("-", ""); paramsInfo.put("license_end_date", formatEndDate); // 证照有效期类型 paramsInfo.put("license_validity_type", "0"); } else { // 证照有效期类型 paramsInfo.put("license_validity_type", "1"); } // 注册地址(省) paramsInfo.put("reg_prov_id", tEnterpriseWithdrawal.getBusinessLicenseProvinceCode()); // 注册地址(市) paramsInfo.put("reg_area_id", tEnterpriseWithdrawal.getBusinessLicenseCityCode()); // 注册地址(区) paramsInfo.put("reg_district_id", tEnterpriseWithdrawal.getBusinessLicenseDistrictCode()); // 注册地址(详细信息) paramsInfo.put("reg_detail", tEnterpriseWithdrawal.getBusinessLicenseAddress()); // 法人姓名 paramsInfo.put("legal_name", tEnterpriseWithdrawal.getCorporateIdCardReversePicture()); // 法人证件类型 paramsInfo.put("legal_cert_type", tEnterpriseWithdrawal.getCorporateCertificateType().equals(1) ? "00" : "11"); // 法人证件号码 paramsInfo.put("legal_cert_no", tEnterpriseWithdrawal.getCertificateCode()); String[] certificateExpireTimeArr = tEnterpriseWithdrawal.getCertificateExpireTime().split(","); String expireStartDateStr = certificateExpireTimeArr[0]; // 法人证件有效期开始日期 paramsInfo.put("legal_cert_begin_date", expireStartDateStr.replace("-", "")); // 法人证件有效期截止日期日期格式:yyyyMMdd; 非长期有效时必填,长期有效为空;<font color="green">示例值:20320905</font> String expireEndDateStr = certificateExpireTimeArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = expireEndDateStr.replace("-", ""); paramsInfo.put("legal_cert_end_date", formatEndDate); // 法人证件有效期类型 paramsInfo.put("legal_cert_validity_type", "0"); } else { // 法人证件有效期类型 paramsInfo.put("legal_cert_validity_type", "1"); } // 联系人姓名 paramsInfo.put("contact_name", tEnterpriseWithdrawal.getCorporateName()); // 联系人手机号 paramsInfo.put("contact_mobile", tEnterpriseWithdrawal.getCorporatePhone()); // 管理员账号如需短信通知则必填;<font color="green">示例值:Lg20220222013747</font> paramsInfo.put("login_name", tEnterpriseWithdrawal.getCorporatePhone()); // 是否发送短信标识 paramsInfo.put("sms_send_flag", "Y"); // 3. 发起API调用 Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/basicdata/indv/modify", paramsInfo, null, false); log.info("个人用户基本信息修改返回参数:{}", response); Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/basicdata/ent", paramsInfo, null, false); log.info("企业用户基本信息修改返回参数:{}", JSONObject.toJSONString(response)); return response; } @@ -225,7 +302,7 @@ * @return * @throws Exception */ public Map<String, Object> userBusinessOpen(UserWithdrawal userWithdrawal) throws Exception { public Map<String, Object> entBusinessOpen(TEnterpriseWithdrawal enterpriseWithdrawal) throws Exception { // 1. 数据初始化,填入对应的商户配置 MerConfig merConfig = new MerConfig(); merConfig.setProcutId(huiFuProperties.getProductId()); @@ -236,45 +313,28 @@ // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", enterpriseWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DateUtil.format(new Date(), "yyyyMMdd")); // 渠道商/商户汇付Id paramsInfo.put("upper_huifu_id", huiFuProperties.getUpperHuifuId()); //// 结算信息配置 // 结算信息配置 //paramsInfo.put("settle_config", "{\"settle_cycle\":\"D1\",\"min_amt\":\"0.01\",\"remained_amt\":\"10.00\",\"settle_abstract\":\"结算摘要\",\"out_settle_flag\":\"2\",\"settle_batch_no\":\"300\",\"fixed_ratio\":\"2\"}"); // 结算卡信息 JSONObject cardInfo = new JSONObject(); cardInfo.put("card_type", "1"); cardInfo.put("card_name", userWithdrawal.getBindAcctName()); cardInfo.put("card_no", userWithdrawal.getBankCardCode()); cardInfo.put("prov_id", userWithdrawal.getBankCardProvinceCode()); cardInfo.put("area_id", userWithdrawal.getBankCardCityCode()); cardInfo.put("cert_type", "00"); cardInfo.put("cert_no", userWithdrawal.getCertificateCode()); String[] certificateExpireDateArr = userWithdrawal.getCertificateExpireTime().split(","); String startDateStr = certificateExpireDateArr[0]; // 个人证件有效期开始日期 cardInfo.put("cert_begin_date", startDateStr.replace("-", "")); // 个人证件有效期截止日期 String endDateStr = certificateExpireDateArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = endDateStr.replace("-", ""); cardInfo.put("cert_end_date", formatEndDate); // 个人证件有效期类型 cardInfo.put("cert_validity_type", "0"); } else { // 个人证件有效期类型 cardInfo.put("cert_validity_type", "1"); } cardInfo.put("card_type", "0"); cardInfo.put("card_name", enterpriseWithdrawal.getDepositName()); cardInfo.put("card_no", enterpriseWithdrawal.getBankAccount()); cardInfo.put("prov_id", enterpriseWithdrawal.getBankCardProvinceCode()); cardInfo.put("area_id", enterpriseWithdrawal.getBankCardCityCode()); cardInfo.put("branch_code", enterpriseWithdrawal.getBankBranchCode()); paramsInfo.put("card_info", cardInfo.toJSONString()); log.info("用户业务入驻返回参数:{}", paramsInfo); log.info("企业业务入驻返回参数:{}", paramsInfo); // 3. 发起API调用 Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/open", paramsInfo, null, false); ; log.info("用户业务入驻返回参数:{}", response); log.info("企业业务入驻返回参数:{}", response); return response; } @@ -284,7 +344,7 @@ * @return * @throws Exception */ public Map<String, Object> userBusinessOpenModify(UserWithdrawal userWithdrawal) throws Exception { public Map<String, Object> entBusinessOpenModify(TEnterpriseWithdrawal enterpriseWithdrawal) throws Exception { // 1. 数据初始化,填入对应的商户配置 MerConfig merConfig = new MerConfig(); merConfig.setProcutId(huiFuProperties.getProductId()); @@ -295,43 +355,28 @@ // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", enterpriseWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DateUtil.format(new Date(), "yyyyMMdd")); // 渠道商/商户汇付Id paramsInfo.put("upper_huifu_id", huiFuProperties.getUpperHuifuId()); // 结算信息配置 //paramsInfo.put("settle_config", "{\"settle_cycle\":\"D1\",\"min_amt\":\"0.01\",\"remained_amt\":\"10.00\",\"settle_abstract\":\"结算摘要\",\"out_settle_flag\":\"2\",\"settle_batch_no\":\"300\",\"fixed_ratio\":\"2\"}"); // 结算卡信息 JSONObject cardInfo = new JSONObject(); cardInfo.put("card_type", "1"); cardInfo.put("card_name", userWithdrawal.getBindAcctName()); cardInfo.put("card_no", userWithdrawal.getBankCardCode()); cardInfo.put("prov_id", userWithdrawal.getBankCardProvinceCode()); cardInfo.put("area_id", userWithdrawal.getBankCardCityCode()); cardInfo.put("cert_type", "00"); cardInfo.put("cert_no", userWithdrawal.getCertificateCode()); String[] certificateExpireDateArr = userWithdrawal.getCertificateExpireTime().split(","); String startDateStr = certificateExpireDateArr[0]; // 个人证件有效期开始日期 cardInfo.put("cert_begin_date", startDateStr.replace("-", "")); // 个人证件有效期截止日期 String endDateStr = certificateExpireDateArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = endDateStr.replace("-", ""); cardInfo.put("cert_end_date", formatEndDate); // 个人证件有效期类型 cardInfo.put("cert_validity_type", "0"); } else { // 个人证件有效期类型 cardInfo.put("cert_validity_type", "1"); } cardInfo.put("card_type", "0"); cardInfo.put("card_name", enterpriseWithdrawal.getDepositName()); cardInfo.put("card_no", enterpriseWithdrawal.getBankAccount()); cardInfo.put("prov_id", enterpriseWithdrawal.getBankCardProvinceCode()); cardInfo.put("area_id", enterpriseWithdrawal.getBankCardCityCode()); cardInfo.put("branch_code", enterpriseWithdrawal.getBankBranchCode()); paramsInfo.put("card_info", cardInfo.toJSONString()); log.info("用户业务入驻修改返回参数:{}", paramsInfo); log.info("企业业务入驻修改返回参数:{}", paramsInfo); // 3. 发起API调用 Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/open", paramsInfo, null, false); ; log.info("用户业务入驻修改返回参数:{}", response); Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/modify", paramsInfo, null, false); log.info("企业业务入驻修改返回参数:{}", response); return response; } } ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TEnterpriseWithdrawalController.java
@@ -2,19 +2,23 @@ import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.stylefeng.guns.core.base.controller.BaseController; import com.stylefeng.guns.core.base.tips.ErrorTip; import com.stylefeng.guns.core.shiro.ShiroKit; import com.stylefeng.guns.core.util.SinataUtil; import com.stylefeng.guns.core.util.ToolUtil; import com.stylefeng.guns.modular.cloudPayment.example.MchApplicationExample; import com.stylefeng.guns.modular.huifu.biz.DouGongBasicDataBiz; import com.stylefeng.guns.modular.system.controller.util.Base64Util; import com.stylefeng.guns.modular.system.model.TBank; import com.stylefeng.guns.modular.system.model.TBankNext; import com.stylefeng.guns.modular.system.model.TImgMid; import com.stylefeng.guns.modular.system.model.TRegion; import com.stylefeng.guns.modular.system.service.ITBankNextService; import com.stylefeng.guns.modular.system.service.ITBankService; import com.stylefeng.guns.modular.system.service.ITImgMidService; import com.stylefeng.guns.modular.system.service.ITRegionService; import com.unionpay.upyzt.exception.UpyztException; import com.unionpay.upyzt.resp.MchApplicationResp; import com.unionpay.upyzt.resp.MchApplicationStoreResp; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -30,8 +34,10 @@ import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; /** * 控制器 @@ -54,12 +60,19 @@ @Autowired private ITBankNextService bankNextService; @Autowired private ITRegionService tRegionService; @Autowired private DouGongBasicDataBiz douGongBasicDataBiz; /** * 跳转到首页 */ @RequestMapping("") public String index(Model model) throws UpyztException { TEnterpriseWithdrawal companyId = tEnterpriseWithdrawalService.selectOne(new EntityWrapper<TEnterpriseWithdrawal>().eq("companyId", ShiroKit.getUser().getObjectId())); List<TRegion> provinceList = tRegionService.selectList(new EntityWrapper<TRegion>().eq("parent_id", 0)); model.addAttribute("provinceList",provinceList); if(companyId!=null){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); model.addAttribute("item",companyId); @@ -76,6 +89,18 @@ model.addAttribute("bankNext",tBankNext.getBankName()); model.addAttribute("bankCode",bankCode.getBankCode()); model.addAttribute("bankNextCode",tBankNext.getId()); String businessLicenseProvinceCode = companyId.getBusinessLicenseProvinceCode(); TRegion province = tRegionService.selectOne(new EntityWrapper<TRegion>().eq("code", businessLicenseProvinceCode)); if (Objects.nonNull(province)) { List<TRegion> cityList = tRegionService.selectList(new EntityWrapper<TRegion>().eq("parent_id", province.getId())); model.addAttribute("cityList", cityList); String businessLicenseCityCode = companyId.getBusinessLicenseCityCode(); TRegion city = tRegionService.selectOne(new EntityWrapper<TRegion>().eq("code", businessLicenseCityCode)); if (Objects.nonNull(city)) { List<TRegion> districtList = tRegionService.selectList(new EntityWrapper<TRegion>().eq("parent_id", city.getId())); model.addAttribute("districtList", districtList); } } if("auditing".equals(companyId.getApplicationStatus()) || "".equals(companyId.getApplicationStatus())){ return PREFIX + "tEnterpriseWithdrawal_detail.html"; }else if("account_need_verify".equals(companyId.getApplicationStatus())){ @@ -189,13 +214,18 @@ tEnterpriseWithdrawal.setCopy2(itImgMidService.selectOne(new EntityWrapper<TImgMid>().eq("url",tEnterpriseWithdrawal.getCorporateIdCardFrontPicture())).getMid()); tEnterpriseWithdrawal.setCopy3(itImgMidService.selectOne(new EntityWrapper<TImgMid>().eq("url",tEnterpriseWithdrawal.getCorporateIdCardReversePicture())).getMid()); System.out.println("----------"+"进件gogogo"+"----------"); MchApplicationStoreResp mchApplicationStoreResp = MchApplicationExample.create(tEnterpriseWithdrawal); System.out.println("----------"+mchApplicationStoreResp+"----------"); tEnterpriseWithdrawal.setOutRequestNo(mchApplicationStoreResp.getOutRequestNo()); tEnterpriseWithdrawal.setMchApplicationId(mchApplicationStoreResp.getMchApplicationId()); //MchApplicationStoreResp mchApplicationStoreResp = MchApplicationExample.create(tEnterpriseWithdrawal); Map<String, Object> resultMap = douGongBasicDataBiz.userBasicDataEnt(tEnterpriseWithdrawal); String respCode = (String) resultMap.get("resp_code"); if(!"00000000".equals(respCode)) { return new ErrorTip(500, (String) resultMap.get("resp_desc")); } Map<String, Object> map = douGongBasicDataBiz.entBusinessOpen(tEnterpriseWithdrawal); if(!"00000000".equals(map.get("resp_code"))) { return new ErrorTip(500, (String) resultMap.get("resp_desc")); } tEnterpriseWithdrawal.setHuifuId((String) resultMap.get("huifu_id")); tEnterpriseWithdrawal.setTokenNo((String) map.get("token_no")); tEnterpriseWithdrawal.setTransactionAuthorizationCode(Base64Util.encode(tEnterpriseWithdrawal.getTransactionAuthorizationCode())); tEnterpriseWithdrawal.setBusinessLicense(tEnterpriseWithdrawal.getBusinessLicense()); tEnterpriseWithdrawal.setCorporateIdCardFrontPicture(tEnterpriseWithdrawal.getCorporateIdCardFrontPicture()); @@ -252,21 +282,25 @@ } try { TEnterpriseWithdrawal enterpriseWithdrawal = tEnterpriseWithdrawalService.selectById(tEnterpriseWithdrawal.getId()); MchApplicationResp mchApplicationResp = MchApplicationExample.retrieveById(enterpriseWithdrawal.getMchApplicationId()); System.err.println(mchApplicationResp); if(enterpriseWithdrawal.getMchId()!=null){ tEnterpriseWithdrawal.setMchId(enterpriseWithdrawal.getMchId()); }else { tEnterpriseWithdrawal.setMchId(mchApplicationResp.getMchId()); Map<String, Object> map = douGongBasicDataBiz.userBasicDataEntModify(tEnterpriseWithdrawal); if(!"00000000".equals(map.get("resp_code"))) { return new ErrorTip(500, (String) map.get("resp_desc")); } TEnterpriseWithdrawal enterpriseWithdrawal = tEnterpriseWithdrawalService.selectById(tEnterpriseWithdrawal.getId()); //MchApplicationResp mchApplicationResp = MchApplicationExample.retrieveById(enterpriseWithdrawal.getMchApplicationId()); //System.err.println(mchApplicationResp); //if(enterpriseWithdrawal.getMchId()!=null){ // tEnterpriseWithdrawal.setMchId(enterpriseWithdrawal.getMchId()); //}else { // tEnterpriseWithdrawal.setMchId(mchApplicationResp.getMchId()); //} tEnterpriseWithdrawal.setOutRequestNo(ToolUtil.getRandomString(32)); String copy1 = tEnterpriseWithdrawalService.getmid(tEnterpriseWithdrawal.getCorporateIdCardFrontPicture()); String copy2 = tEnterpriseWithdrawalService.getmid(tEnterpriseWithdrawal.getCorporateIdCardReversePicture()); String copy3 = tEnterpriseWithdrawalService.getmid(tEnterpriseWithdrawal.getBusinessLicense()); tEnterpriseWithdrawal.setCopy1(copy3); tEnterpriseWithdrawal.setCopy2(copy1); tEnterpriseWithdrawal.setCopy3(copy2); //String copy1 = tEnterpriseWithdrawalService.getmid(tEnterpriseWithdrawal.getCorporateIdCardFrontPicture()); //String copy2 = tEnterpriseWithdrawalService.getmid(tEnterpriseWithdrawal.getCorporateIdCardReversePicture()); //String copy3 = tEnterpriseWithdrawalService.getmid(tEnterpriseWithdrawal.getBusinessLicense()); //tEnterpriseWithdrawal.setCopy1(copy3); //tEnterpriseWithdrawal.setCopy2(copy1); //tEnterpriseWithdrawal.setCopy3(copy2); tEnterpriseWithdrawal.setBankBranchCode(tEnterpriseWithdrawal.getBankBranchCode()); String depositBank = tEnterpriseWithdrawal.getDepositBank(); TBankNext tBankNext = bankNextService.selectById(depositBank); @@ -274,9 +308,13 @@ tEnterpriseWithdrawal.setBankBranchCode(tBankNext.getBankCode()); MchApplicationResp renew = MchApplicationExample.renew(tEnterpriseWithdrawal); tEnterpriseWithdrawal.setOutRequestNo(renew.getOutRequestNo()); tEnterpriseWithdrawal.setMchApplicationId(renew.getMchApplicationId()); //MchApplicationResp renew = MchApplicationExample.renew(tEnterpriseWithdrawal); //tEnterpriseWithdrawal.setOutRequestNo(renew.getOutRequestNo()); //tEnterpriseWithdrawal.setMchApplicationId(renew.getMchApplicationId()); Map<String, Object> resultMap = douGongBasicDataBiz.entBusinessOpenModify(tEnterpriseWithdrawal); if(!"00000000".equals(resultMap.get("resp_code"))) { return new ErrorTip(500, (String) map.get("resp_desc")); } tEnterpriseWithdrawalService.updateById(tEnterpriseWithdrawal); return SUCCESS_TIP; }catch (Exception e){ @@ -293,4 +331,16 @@ public Object detail(@PathVariable("tEnterpriseWithdrawalId") Integer tEnterpriseWithdrawalId) { return tEnterpriseWithdrawalService.selectById(tEnterpriseWithdrawalId); } @RequestMapping(value = "/change") @ResponseBody public Object change(@RequestParam Integer code) { List<TRegion> list = new ArrayList<>(); if (SinataUtil.isNotEmpty(code)){ TRegion region = tRegionService.selectOne(new EntityWrapper<TRegion>().eq("code", code)); if (Objects.nonNull(region)) { list = tRegionService.selectList(new EntityWrapper<TRegion>().eq("parent_id", region.getId())); } } return list; } } ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TEnterpriseWithdrawal.java
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.activerecord.Model; import com.baomidou.mybatisplus.annotations.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; @@ -62,6 +63,19 @@ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private String businessExpireTime; /** * 营业执照注册地址省编码 */ private String businessLicenseProvinceCode; /** * 营业执照注册地址市编码 */ private String businessLicenseCityCode; /** * 营业执照注册地址区编码 */ private String businessLicenseDistrictCode; /** * 统一社会信用代码 */ private String unifiedSocialCreditCode; @@ -97,6 +111,15 @@ * 银行账号 */ private String bankAccount; /** * 开户行所在省编码 */ private String bankCardProvinceCode; /** * 开户行所在市编码 */ private String bankCardCityCode; /** * 法人姓名 */ @@ -162,6 +185,20 @@ private String failureMsgsReason; //varchar 64 0 -1 0 0 0 电子账簿账簿号 utf8mb4 utf8mb4_bin 0 0 0 0 0 0 0 private String relAcctNo ; /** * 汇付ID */ private String huifuId; /** * 取现卡序列号 */ private String tokenNo; /** * 进件类型 0:江苏银行;1:汇付 */ private String type; @TableField(exist = false) private String copy1; @@ -182,6 +219,70 @@ @TableField(exist = false) private String bankBranchCode; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getHuifuId() { return huifuId; } public void setHuifuId(String huifuId) { this.huifuId = huifuId; } public String getBankCardProvinceCode() { return bankCardProvinceCode; } public void setBankCardProvinceCode(String bankCardProvinceCode) { this.bankCardProvinceCode = bankCardProvinceCode; } public String getBankCardCityCode() { return bankCardCityCode; } public void setBankCardCityCode(String bankCardCityCode) { this.bankCardCityCode = bankCardCityCode; } public String getTokenNo() { return tokenNo; } public void setTokenNo(String tokenNo) { this.tokenNo = tokenNo; } public String getBusinessLicenseProvinceCode() { return businessLicenseProvinceCode; } public void setBusinessLicenseProvinceCode(String businessLicenseProvinceCode) { this.businessLicenseProvinceCode = businessLicenseProvinceCode; } public String getBusinessLicenseCityCode() { return businessLicenseCityCode; } public void setBusinessLicenseCityCode(String businessLicenseCityCode) { this.businessLicenseCityCode = businessLicenseCityCode; } public String getBusinessLicenseDistrictCode() { return businessLicenseDistrictCode; } public void setBusinessLicenseDistrictCode(String businessLicenseDistinctCode) { this.businessLicenseDistrictCode = businessLicenseDistinctCode; } public static long getSerialVersionUID() { return serialVersionUID; } ManagementJYXTravel/guns-admin/src/main/resources/application.yml
@@ -37,7 +37,7 @@ db-column-underline: false configuration: configuration.map-underscore-to-camel-case: true #是否开启自动驼峰命名规则(camel case)映射 log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl #输出Sql,如需打印Sql注释该配置 # log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl #输出Sql,如需打印Sql注释该配置 #eureka: ManagementJYXTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tEnterpriseWithdrawal/tEnterpriseWithdrawal_add.html
@@ -16,11 +16,23 @@ </select> </div> </div> <#input id="merchantAbbreviation" name="商户简称" /> <#avatar id="businessLicense" name="营业执照" /> <#input id="businessLicenseCode" name="营业执照注册号"/> <#input id="businessLicenseCompanyName" name="营业执照公司名称"/> <#input id="businessLicenseAddress" name="营业执照注册地址"/> <#input id="merchantAbbreviation" name="商户简称" /> <#avatar id="businessLicense" name="营业执照" /> <#input id="businessLicenseCode" name="营业执照注册号"/> <#input id="businessLicenseCompanyName" name="营业执照公司名称"/> <#input id="businessLicenseAddress" name="营业执照注册地址"/> <#select id="businessLicenseProvinceCode" name="营业执照注册省:" onchange="TEnterpriseWithdrawalInfoDlg.provinceChange(1)"> <option value="">选择省</option> @for(province in provinceList){ <option value="${province.code}">${province.name}</option> @} </#select> <#select id="businessLicenseCityCode" name="营业执照注册市:" onchange="TEnterpriseWithdrawalInfoDlg.cityChange()"> <option value="">选择市</option> </#select> <#select id="businessLicenseDistrictCode" name="营业执照注册区:"> <option value="">选择区</option> </#select> <div class="form-group"> <label class="col-sm-3 control-label">营业期限:</label> <div class="col-sm-3" > @@ -51,7 +63,6 @@ </div> </div> <#input id="contactsEmail" name="邮箱地址"/> </div> <div class="col-sm-6" > @@ -82,6 +93,15 @@ </select> </div> </div> <#select id="bankCardProvinceCode" name="银行所在省:" onchange="TEnterpriseWithdrawalInfoDlg.provinceChange(2)"> <option value="">选择省</option> @for(province in provinceList){ <option value="${province.code}">${province.name}</option> @} </#select> <#select id="bankCardCityCode" name="银行所在市:" onchange="TEnterpriseWithdrawalInfoDlg.cityChange()"> <option value="">选择市</option> </#select> <#input id="depositName" name="开户名称" /> <#input id="bankAccount" name="银行账号"/> <#input id="corporateName" name="法人姓名"/> @@ -113,20 +133,20 @@ </div> </div> <#input id="corporatePhone" name="法人手机号" /> <div class="form-group"> <label class="col-sm-3 control-label">验证码:</label> <div class="col-sm-7"> <input class="form-control" id="code" name="code" type="text"> </div> <input type="button" id="sendCode" onclick="sendSMSCode(this)" style=" background-color: #0e9aef; border: 0; border-radius: 5px; width: 80px; height: 30px;color: white; " value="获取验证码"> </div> <!-- <div class="form-group">--> <!-- <label class="col-sm-3 control-label">验证码:</label>--> <!-- <div class="col-sm-7">--> <!-- <input class="form-control" id="code" name="code" type="text">--> <!-- </div>--> <!-- --> <!-- <input type="button" id="sendCode" onclick="sendSMSCode(this)" style="--> <!-- background-color: #0e9aef;--> <!-- border: 0;--> <!-- border-radius: 5px;--> <!-- width: 80px;--> <!-- height: 30px;color: white;--> <!-- " value="获取验证码">--> <!-- </div>--> <#avatar id="corporateIdCardFrontPicture" name="法人身份证照片正面" /> <#avatar id="corporateIdCardReversePicture" name="法人身份证照反面" /> </div> ManagementJYXTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tEnterpriseWithdrawal/tEnterpriseWithdrawal_edit.html
@@ -1,7 +1,7 @@ @layout("/common/_container.html"){ <div class="ibox float-e-margins"> <div class="ibox-content"> <div class="form-horizontal" > <div class="form-horizontal" id="enForm"> <input hidden id="id" value="${item.id}"> <input hidden id="enterpriseType_" value="${item.enterpriseType}"> <input hidden id="accountType_" value="${item.accountType}"> @@ -24,6 +24,32 @@ <#input id="businessLicenseCode" name="营业执照注册号" value="${item.businessLicenseCode}" /> <#input id="businessLicenseCompanyName" name="营业执照公司名称" value="${item.businessLicenseCompanyName}" /> <#input id="businessLicenseAddress" name="营业执照注册地址" value="${item.businessLicenseAddress}" /> <#select id="businessLicenseProvinceCode" name="营业执照注册省:" onchange="TEnterpriseWithdrawalInfoDlg.provinceChange(1)"> <option value="">选择省</option> @for(province in provinceList){ <option value="${province.code}" ${item.businessLicenseProvinceCode == province.code ? 'selected' : ''}>${province.name}</option> @} </#select> <#select id="businessLicenseCityCode" name="营业执照注册市:" onchange="TEnterpriseWithdrawalInfoDlg.cityChange()"> @if(isNotEmpty(cityList)){ <option value="">选择市</option> @for(city in cityList){ <option value="${city.code}" ${item.businessLicenseCityCode == city.code ? 'selected' : ''}>${city.name}</option> @} @}else{ <option value="">选择市</option> @} </#select> <#select id="businessLicenseDistrictCode" name="营业执照注册区:"> @if(isNotEmpty(districtList)){ <option value="">选择区</option> @for(district in districtList){ <option value="${district.code}" ${item.businessLicenseDistrictCode == district.code ? 'selected' : ''}>${district.name}</option> @} @}else{ <option value="">选择区</option> @} </#select> <div class="form-group"> <label class="col-sm-3 control-label">营业期限:</label> <div class="col-sm-3" > @@ -85,6 +111,22 @@ </select> </div> </div> <#select id="bankCardProvinceCode" name="营业执照注册省:" onchange="TEnterpriseWithdrawalInfoDlg.provinceChange(2)"> <option value="">选择省</option> @for(province in provinceList){ <option value="${province.code}" ${item.bankCardProvinceCode == province.code ? 'selected' : ''}>${province.name}</option> @} </#select> <#select id="bankCardCityCode" name="营业执照注册市:" onchange="TEnterpriseWithdrawalInfoDlg.cityChange()"> @if(isNotEmpty(cityList)){ <option value="">选择市</option> @for(city in cityList){ <option value="${city.code}" ${item.bankCardCityCode == city.code ? 'selected' : ''}>${city.name}</option> @} @}else{ <option value="">选择市</option> @} </#select> <#input id="depositName" name="开户名称" value="${item.depositName}" /> <#input id="bankAccount" name="银行账号" value="${item.bankAccount}"/> <#input id="corporateName" name="法人姓名" value="${item.corporateName}"/> ManagementJYXTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tEnterpriseWithdrawal/tEnterpriseWithdrawal_fail.html
@@ -24,6 +24,32 @@ <#input id="businessLicenseCode" name="营业执照注册号" value="${item.businessLicenseCode}" /> <#input id="businessLicenseCompanyName" name="营业执照公司名称" value="${item.businessLicenseCompanyName}" /> <#input id="businessLicenseAddress" name="营业执照注册地址" value="${item.businessLicenseAddress}" /> <#select id="businessLicenseProvinceCode" name="营业执照注册省:" onchange="TEnterpriseWithdrawalInfoDlg.provinceChange(1)"> <option value="">选择省</option> @for(province in provinceList){ <option value="${province.code}" ${item.businessLicenseProvinceCode == province.code ? 'selected' : ''}>${province.name}</option> @} </#select> <#select id="businessLicenseCityCode" name="营业执照注册市:" onchange="TEnterpriseWithdrawalInfoDlg.cityChange()"> @if(isNotEmpty(cityList)){ <option value="">选择市</option> @for(city in cityList){ <option value="${city.code}" ${item.businessLicenseCityCode == city.code ? 'selected' : ''}>${city.name}</option> @} @}else{ <option value="">选择市</option> @} </#select> <#select id="businessLicenseDistrictCode" name="营业执照注册区:"> @if(isNotEmpty(districtList)){ <option value="">选择区</option> @for(district in districtList){ <option value="${district.code}" ${item.businessLicenseDistrictCode == district.code ? 'selected' : ''}>${district.name}</option> @} @}else{ <option value="">选择区</option> @} </#select> <div class="form-group"> <label class="col-sm-3 control-label">营业期限:</label> <div class="col-sm-3" > @@ -88,6 +114,22 @@ </select> </div> </div> <#select id="bankCardProvinceCode" name="营业执照注册省:" onchange="TEnterpriseWithdrawalInfoDlg.provinceChange(2)"> <option value="">选择省</option> @for(province in provinceList){ <option value="${province.code}" ${item.bankCardProvinceCode == province.code ? 'selected' : ''}>${province.name}</option> @} </#select> <#select id="bankCardCityCode" name="营业执照注册市:" onchange="TEnterpriseWithdrawalInfoDlg.cityChange()"> @if(isNotEmpty(cityList)){ <option value="">选择市</option> @for(city in cityList){ <option value="${city.code}" ${item.bankCardCityCode == city.code ? 'selected' : ''}>${city.name}</option> @} @}else{ <option value="">选择市</option> @} </#select> <#input id="depositName" name="开户名称" value="${item.depositName}" /> <#input id="bankAccount" name="银行账号" value="${item.bankAccount}"/> <#input id="corporateName" name="法人姓名" value="${item.corporateName}"/> ManagementJYXTravel/guns-admin/src/main/webapp/static/modular/system/tEnterpriseWithdrawal/tEnterpriseWithdrawal_info.js
@@ -46,6 +46,27 @@ } } }, businessLicenseProvinceCode: { validators: { notEmpty: { message: '营业执照注册地址省不能为空' } } }, businessLicenseCityCode: { validators: { notEmpty: { message: '营业执照注册市不能为空' } } }, businessLicenseDistrictCode: { validators: { notEmpty: { message: '营业执照注册区不能为空' } } }, unifiedSocialCreditCode: { validators: { notEmpty: { @@ -85,6 +106,20 @@ validators: { notEmpty: { message: '开户名称不能为空' } } }, bankCardProvinceCode: { validators: { notEmpty: { message: '银行所在省不能为空' } } }, bankCardCityCode: { validators: { notEmpty: { message: '银行所在市不能为空' } } }, @@ -209,6 +244,11 @@ .set('businessLicenseCompanyName') .set('businessLicenseAddress') .set('businessExpireTime') .set('businessLicenseProvinceCode') .set('businessLicenseCityCode') .set('businessLicenseDistrictCode') .set('bankCardProvinceCode') .set('bankCardCityCode') .set('unifiedSocialCreditCode') .set('unifiedSocialCreditCodeExpireTime') .set('companyPhone') @@ -331,7 +371,45 @@ console.log(this.tEnterpriseWithdrawalInfoData) ajax.start(); } /** * 省改变时执行 */ TEnterpriseWithdrawalInfoDlg.provinceChange = function (type) { let code = type == 1 ? code = $("#businessLicenseProvinceCode").val() : $("#bankCardProvinceCode").val(); var ajax = new $ax(Feng.ctxPath + "/tEnterpriseWithdrawal/change", function(data){ if(data!=null){ var content='<option value="">选择市</option>'; $.each(data, function(k,v) { content += "<option value='"+v.code+"'>"+v.name+"</option>"; }); if (type == 1) { $("#businessLicenseCityCode").empty().append(content); $("#businessLicenseDistinctCode").empty().append('<option value="">选择区</option>'); }else if (type == 2) { $("#bankCardCityCode").empty().append(content); } } }); ajax.set("code", code); ajax.start(); } /** * 市改变时执行 */ TEnterpriseWithdrawalInfoDlg.cityChange = function () { var businessLicenseCityCode = $("#businessLicenseCityCode").val(); var ajax = new $ax(Feng.ctxPath + "/tEnterpriseWithdrawal/change", function(data){ if(data!=null){ var content='<option value="">选择区</option>'; $.each(data, function(k,v) { content += "<option value='"+v.code+"'>"+v.name+"</option>"; }); $("#businessLicenseDistinctCode").empty().append(content); } }); ajax.set("code",businessLicenseCityCode); ajax.start(); } $(function() { Feng.initValidator("enForm", TEnterpriseWithdrawalInfoDlg.validateFields); var businessLicense = new $WebUpload("businessLicense"); ManagementJYXTravel/guns-core/src/main/java/com/stylefeng/guns/core/util/RequestSeqUtil.java
New file @@ -0,0 +1,217 @@ package com.stylefeng.guns.core.util; import java.security.SecureRandom; import java.util.concurrent.atomic.AtomicLong; /** * 请求流水号生成工具类 * * <p>用于生成32位唯一请求流水号,格式:[前缀2位][日期8位][时间6位][毫秒3位][序列号13位]</p> * <p>示例:rQ202511141540078404299875651</p> * * <p>特性:</p> * <ul> * <li>线程安全:使用AtomicLong保证高并发环境下的唯一性</li> * <li>高性能:避免重复创建对象,优化内存使用</li> * <li>可配置:支持自定义前缀适应不同业务场景</li> * <li>高可靠:时间戳+随机数+序列号三重保障唯一性</li> * </ul> * * @author harley * @since 2025-11-14 */ public class RequestSeqUtil { /** * 默认前缀 */ private static final String DEFAULT_PREFIX = "RQ"; /** * 序列号生成器,保证线程安全 */ private static final AtomicLong SEQUENCE_GENERATOR = new AtomicLong(0); /** * 安全随机数生成器 */ private static final SecureRandom SECURE_RANDOM = new SecureRandom(); /** * 流水号总长度 */ private static final int TOTAL_LENGTH = 32; /** * 前缀长度 */ private static final int PREFIX_LENGTH = 2; /** * 日期长度 (yyyyMMdd) */ private static final int DATE_LENGTH = 8; /** * 时间长度 (HHmmss) */ private static final int TIME_LENGTH = 6; /** * 毫秒长度 */ private static final int MILLIS_LENGTH = 3; /** * 序列号长度 */ private static final int SEQUENCE_LENGTH = 13; /** * 私有构造函数,防止实例化 */ private RequestSeqUtil() { throw new UnsupportedOperationException("工具类不允许实例化"); } /** * 生成默认前缀的32位请求流水号 * * @return 32位请求流水号,格式:RQ + 时间信息 + 序列号 */ public static String generate() { return generate(DEFAULT_PREFIX); } /** * 生成指定前缀的32位请求流水号 * * <p>流水号格式:[前缀2位][日期8位][时间6位][毫秒3位][序列号13位]</p> * <p>示例:rQ202511141540078404299875651</p> * * @param prefix 自定义前缀,建议2位字符 * @return 32位请求流水号 * @throws IllegalArgumentException 当前缀为空或长度不符合要求时抛出 */ public static String generate(String prefix) { // 参数校验 if (prefix == null || prefix.isEmpty()) { throw new IllegalArgumentException("前缀不能为空"); } if (prefix.length() != PREFIX_LENGTH) { throw new IllegalArgumentException("前缀长度必须为" + PREFIX_LENGTH + "位"); } long currentTime = System.currentTimeMillis(); // 构建流水号各个部分 String datePart = DateUtil.format(new java.util.Date(currentTime), "yyyyMMdd"); String timePart = DateUtil.format(new java.util.Date(currentTime), "HHmmss"); String millisPart = String.format("%03d", currentTime % 1000); // 生成序列号(时间戳后7位 + 随机数6位) long sequence = SEQUENCE_GENERATOR.incrementAndGet(); String sequencePart = String.format("%013d", Math.abs(sequence % 1000000000000L)); // 组装完整的流水号 StringBuilder seqBuilder = new StringBuilder(TOTAL_LENGTH); seqBuilder.append(prefix) .append(datePart) .append(timePart) .append(millisPart) .append(sequencePart); return seqBuilder.toString(); } /** * 生成带业务标识的流水号 * * <p>常用的业务前缀:</p> * <ul> * <li>rQ - 汇付请求</li> * <li>OR - 订单业务</li> * <li>PY - 支付业务</li> * <li>RF - 退款业务</li> * </ul> * * @param businessCode 业务代码前缀 * @return 32位业务流水号 */ public static String generateForBusiness(String businessCode) { return generate(businessCode); } /** * 生成汇付相关的请求流水号 * * @return 以"rQ"为前缀的32位流水号 */ public static String generateForHuiFu() { return generate("rQ"); } /** * 验证流水号格式是否正确 * * @param sequence 要验证的流水号 * @return 验证结果 */ public static boolean isValid(String sequence) { if (sequence == null || sequence.length() != TOTAL_LENGTH) { return false; } // 验证时间部分格式(第3-16位应该是数字) String timePart = sequence.substring(2, 16); if (!timePart.matches("\\d+")) { return false; } // 验证最后13位序列号是否为数字 String sequencePart = sequence.substring(19); if (!sequencePart.matches("\\d+")) { return false; } return true; } /** * 从流水号中提取前缀 * * @param sequence 流水号 * @return 流水号前缀 */ public static String extractPrefix(String sequence) { if (sequence == null || sequence.length() < PREFIX_LENGTH) { return null; } return sequence.substring(0, PREFIX_LENGTH); } /** * 从流水号中提取时间信息 * * @param sequence 流水号 * @return 格式化的时间字符串,格式:yyyy-MM-dd HH:mm:ss.SSS */ public static String extractDateTime(String sequence) { if (!isValid(sequence)) { return null; } String dateStr = sequence.substring(2, 10); // yyyyMMdd String timeStr = sequence.substring(10, 16); // HHmmss String millisStr = sequence.substring(16, 19); // 毫秒 return dateStr.substring(0, 4) + "-" + dateStr.substring(4, 6) + "-" + dateStr.substring(6, 8) + " " + timeStr.substring(0, 2) + ":" + timeStr.substring(2, 4) + ":" + timeStr.substring(4, 6) + "." + millisStr; } } UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/account/controller/ElectronicLedgerController.java
@@ -125,7 +125,7 @@ userWithdrawal.setImgUrlOne(userWithdrawalReq.getIdCardReversePicture()); userWithdrawal.setIdCardFrontPicture(userWithdrawalReq.getCopy1()); userWithdrawal.setIdCardReversePicture(userWithdrawalReq.getCopy2()); userWithdrawal.setHuiFuId((String) resultMap.get("huifu_id")); userWithdrawal.setHuifuId((String) resultMap.get("huifu_id")); //调用汇付业务入驻接口 Map<String, Object> map = douGongBasicDataBiz.userBusinessOpen(userWithdrawal); if (!"00000000".equals(map.get("resp_code"))){ @@ -232,7 +232,7 @@ UserWithdrawal userWithdrawal1 = userWithdrawalService.selectOne(new EntityWrapper<UserWithdrawal>() .eq("phone", userInfo.getPhone()).eq("type", 1) .last("LIMIT 1")); if(userWithdrawal1==null|| userWithdrawal1.getHuiFuId()==null){ if(userWithdrawal1==null|| userWithdrawal1.getHuifuId()==null){ return ResultUtil.runErr(); } UserWithdrawal userWithdrawal = new UserWithdrawal(); @@ -272,7 +272,7 @@ userWithdrawal1.setBankName(bankName); userWithdrawal1.setImgUrl(idCardFrontPicture); userWithdrawal1.setImgUrlOne(idCardReversePicture); userWithdrawal1.setHuiFuId((String) resultMap.get("huifu_id")); userWithdrawal1.setHuifuId((String) resultMap.get("huifu_id")); userWithdrawal1.setTokenNo((String) map.get("token_no")); userWithdrawalService.updateById(userWithdrawal1); UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongBasicDataBiz.java
@@ -73,8 +73,10 @@ paramsInfo.put("name", userWithdrawal.getOpenAccountName()); // 个人证件号码 paramsInfo.put("cert_no", userWithdrawal.getCertificateCode()); // 管理员账号 paramsInfo.put("login_name", userWithdrawal.getPhone()); // 是否发送短信标识 paramsInfo.put("sms_send_flag", "1"); paramsInfo.put("sms_send_flag", "Y"); // 3. 发起API调用 log.info("个人用户基本信息开户请求参数:{}", paramsInfo); Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/basicdata/indv", paramsInfo, null, false); @@ -101,7 +103,7 @@ // 请求日期 paramsInfo.put("req_date", DateUtil.format(new Date(),"yyyyMMdd")); // 汇付客户Id paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); String[] certificateExpireDateArr = userWithdrawal.getCertificateExpireTime().split(","); String startDateStr = certificateExpireDateArr[0]; // 个人证件有效期开始日期 @@ -141,7 +143,7 @@ // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 @@ -197,7 +199,7 @@ // 2.组装请求参数 Map<String, Object> paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuiFuId()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu()); // 请求日期 @@ -231,7 +233,7 @@ paramsInfo.put("card_info", cardInfo.toJSONString()); log.info("用户业务入驻修改返回参数:{}", paramsInfo); // 3. 发起API调用 Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/open", paramsInfo, null, false);; Map<String, Object> response = BasePayRequest.requestBasePay("v2/user/busi/modify", paramsInfo, null, false);; log.info("用户业务入驻修改返回参数:{}", response); return response; } UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/UserWithdrawal.java
@@ -161,7 +161,7 @@ private Integer type; @ApiModelProperty(value = "汇付ID") private String huiFuId; private String huifuId; @ApiModelProperty(value = "取现卡序列号") private String tokenNo;