package com.tourguide.common.huifu.biz; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.huifu.bspay.sdk.opps.core.net.BasePayRequest; import com.tourguide.common.huifu.properties.HuiFuProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; /** * 斗拱进件业务。 * * 备注:该类只负责把本项目导游开户资料提交给斗拱;导游账号、银行卡和审核状态应由上层业务服务落库。 */ @Component public class DouGongBasicDataBiz { private static final Logger log = LoggerFactory.getLogger(DouGongBasicDataBiz.class); @Autowired private HuiFuProperties huiFuProperties; /** * 个人用户基本信息开户 * * 备注:先创建斗拱个人基础资料,成功后才能继续调用业务入驻和结算卡配置。 * * @return * @throws Exception */ public Map userBasicDataIndv(DouGongUserWithdrawalProfile userWithdrawal) throws Exception { // 1. 数据初始化,填入对应的商户配置 DouGongRequestSupport.initBasePay(huiFuProperties); // 2.组装请求参数 Map paramsInfo = new HashMap<>(); // 请求流水号(动态生成,确保唯一性) paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); // 个人证件类型 paramsInfo.put("cert_type", "00"); String[] certificateExpireDateArr = userWithdrawal.getCertificateExpireTime().split(","); String startDateStr = certificateExpireDateArr[0]; // 个人证件有效期开始日期2023-08-02,2043-08-02 paramsInfo.put("cert_begin_date", startDateStr.replace("-", "")); // 个人证件有效期截止日期 String endDateStr = certificateExpireDateArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = endDateStr.replace("-", ""); paramsInfo.put("cert_end_date", formatEndDate); // 个人证件有效期类型 paramsInfo.put("cert_validity_type", "0"); }else { // 个人证件有效期类型 paramsInfo.put("cert_validity_type", "1"); } // 手机号 paramsInfo.put("mobile_no", userWithdrawal.getPhone()); // 个人姓名 paramsInfo.put("name", userWithdrawal.getOpenAccountName()); // 个人证件号码 paramsInfo.put("cert_no", userWithdrawal.getCertificateCode()); // 管理员账号 // paramsInfo.put("login_name", userWithdrawal.getPhone()); // 是否发送短信标识 paramsInfo.put("sms_send_flag", "Y"); // 3. 发起API调用 log.info("个人用户基本信息开户请求参数:{}", paramsInfo); Map response = BasePayRequest.requestBasePay("v2/user/basicdata/indv", paramsInfo, null, false); log.info("个人用户基本信息开户返回参数:{}", response); return response; } /** 企业用户基础资料进件。 */ public Map userBasicDataEnt(DouGongUserWithdrawalProfile userWithdrawal) throws Exception { DouGongRequestSupport.initBasePay(huiFuProperties); Map paramsInfo = enterpriseParams(userWithdrawal); paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); log.info("企业用户基本信息开户请求参数:{}", paramsInfo); Map response = BasePayRequest.requestBasePay( "v2/user/basicdata/ent", paramsInfo, null, false); log.info("企业用户基本信息开户返回参数:{}", response); return response; } /** * 个人用户基本信息修改 * @return * @throws Exception */ public Map userBasicDataIndvModify(DouGongUserWithdrawalProfile userWithdrawal) throws Exception { // 1. 数据初始化,填入对应的商户配置 DouGongRequestSupport.initBasePay(huiFuProperties); // 2.组装请求参数 Map paramsInfo = new HashMap<>(); // 请求流水号 paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); // 汇付客户Id paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); String[] certificateExpireDateArr = userWithdrawal.getCertificateExpireTime().split(","); String startDateStr = certificateExpireDateArr[0]; // 个人证件有效期开始日期 paramsInfo.put("cert_begin_date", startDateStr.replace("-", "")); // 个人证件有效期截止日期 String endDateStr = certificateExpireDateArr[1]; if (!"长期".equals(endDateStr)) { String formatEndDate = endDateStr.replace("-", ""); paramsInfo.put("cert_end_date", formatEndDate); // 个人证件有效期类型 paramsInfo.put("cert_validity_type", "0"); }else { // 个人证件有效期类型 paramsInfo.put("cert_validity_type", "1"); } // 手机号 paramsInfo.put("mobile_no", userWithdrawal.getPhone()); log.info("个人用户基本信息修改返回参数:{}", paramsInfo); // 3. 发起API调用 Map response = BasePayRequest.requestBasePay("v2/user/basicdata/indv/modify", paramsInfo, null, false); log.info("个人用户基本信息修改返回参数:{}", response); return response; } /** 企业用户基础资料修改,用于审核驳回后的重新提交。 */ public Map userBasicDataEntModify(DouGongUserWithdrawalProfile userWithdrawal) throws Exception { DouGongRequestSupport.initBasePay(huiFuProperties); Map paramsInfo = enterpriseParams(userWithdrawal); paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); log.info("企业用户基本信息修改请求参数:{}", paramsInfo); Map response = BasePayRequest.requestBasePay( "v2/user/basicdata/ent/modify", paramsInfo, null, false); log.info("企业用户基本信息修改返回参数:{}", response); return response; } /** 查询个人或企业用户的进件申请状态。 */ public Map userApplyQuery(DouGongUserWithdrawalProfile userWithdrawal, String applyNo) throws Exception { if (applyNo == null || applyNo.trim().isEmpty() || applyNo.trim().length() > 18) { throw new IllegalArgumentException("斗拱进件状态查询申请单号不能为空且长度不能超过18个字符"); } DouGongRequestSupport.initBasePay(huiFuProperties); Map paramsInfo = new HashMap<>(); paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); paramsInfo.put("apply_no", applyNo.trim()); log.info("用户进件申请状态查询请求参数:{}", paramsInfo); Map response = BasePayRequest.requestBasePay( "v2/user/apply/query", paramsInfo, null, false); log.info("用户进件申请状态查询返回参数:{}", response); return response; } /** * 用户业务入驻 * * 备注:业务入驻会绑定结算卡和提现规则,后续提现依赖这里返回的取现卡序列号。 * * @return * @throws Exception */ public Map userBusinessOpen(DouGongUserWithdrawalProfile userWithdrawal) throws Exception { // 1. 数据初始化,填入对应的商户配置 DouGongRequestSupport.initBasePay(huiFuProperties); // 2.组装请求参数 Map paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); // 渠道商/商户汇付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.getOpenAccountName()); 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"); } paramsInfo.put("card_info", cardInfo.toJSONString()); // 结算卡信息 JSONArray cashConfigArr = new JSONArray(); JSONObject cashConfig = new JSONObject(); /** * T1:下一工作日到银行账户; * D1:下一自然日到银行账户; * D0:当日到银行账户;默认D0; * DM:当日到账;到账资金不包括当天的交易资金; * 示例值:T1 */ cashConfig.put("cash_type", "D1"); cashConfig.put("fix_amt", "0.00"); cashConfig.put("weekday_fix_amt", "0.00"); cashConfig.put("weekday_fee_rate", "0.00"); cashConfigArr.add(cashConfig); paramsInfo.put("cash_config", cashConfigArr.toJSONString()); log.info("用户业务入驻返回参数:{}", paramsInfo); // 3. 发起API调用 Map response = BasePayRequest.requestBasePay("v2/user/busi/open", paramsInfo, null, false);; log.info("用户业务入驻返回参数:{}", response); return response; } /** * 用户业务入驻 * @return * @throws Exception */ public Map userBusinessOpenModify(DouGongUserWithdrawalProfile userWithdrawal) throws Exception { // 1. 数据初始化,填入对应的商户配置 DouGongRequestSupport.initBasePay(huiFuProperties); // 2.组装请求参数 Map paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", userWithdrawal.getHuifuId()); // 请求流水号 paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); // 结算卡信息 JSONObject cardInfo = new JSONObject(); cardInfo.put("card_type", "1"); cardInfo.put("card_name", userWithdrawal.getOpenAccountName()); 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"); } paramsInfo.put("card_info", cardInfo.toJSONString()); // 结算卡信息 JSONArray cashConfigArr = new JSONArray(); JSONObject cashConfig = new JSONObject(); /** * T1:下一工作日到银行账户; * D1:下一自然日到银行账户; * D0:当日到银行账户;默认D0; * DM:当日到账;到账资金不包括当天的交易资金; * 示例值:T1 */ cashConfig.put("switch_state", "1"); cashConfig.put("cash_type", "D1"); cashConfig.put("fix_amt", "0.00"); cashConfig.put("weekday_fix_amt", "0.00"); cashConfig.put("weekday_fee_rate", "0.00"); cashConfigArr.add(cashConfig); paramsInfo.put("cash_config", cashConfigArr.toJSONString()); log.info("用户业务入驻修改返回参数:{}", paramsInfo); // 3. 发起API调用 Map response = BasePayRequest.requestBasePay("v2/user/busi/modify", paramsInfo, null, false);; log.info("用户业务入驻修改返回参数:{}", response); return response; } public BigDecimal balanceQuery(String huifuId) throws Exception { // 1. 数据初始化,填入对应的商户配置 DouGongRequestSupport.initBasePay(huiFuProperties); // 2.组装请求参数 Map paramsInfo = new HashMap<>(); // 汇付ID paramsInfo.put("huifu_id", huifuId); // 请求流水号 paramsInfo.put("req_seq_id", DouGongRequestSupport.generateForHuiFu()); // 请求日期 paramsInfo.put("req_date", DouGongRequestSupport.todayForHuiFu()); log.info("账户余额信息查询返回参数:{}", paramsInfo); // 3. 发起API调用 Map response = BasePayRequest.requestBasePay("v2/trade/acctpayment/balance/query", paramsInfo, null, false); log.info("账户余额信息查询返回参数:{}", response); return availableBalance(response); } static BigDecimal availableBalance(Map response) { if (response == null) return BigDecimal.ZERO; Object accountData = response.get("acctInfo_list"); if (accountData == null) accountData = response.get("acct_info_list"); if (accountData == null) return BigDecimal.ZERO; JSONArray accountList = accountData instanceof JSONArray ? (JSONArray) accountData : JSONArray.parseArray(accountData instanceof String ? (String) accountData : JSONObject.toJSONString(accountData)); if (accountList == null || accountList.isEmpty()) return BigDecimal.ZERO; JSONObject acctInfo = accountList.getJSONObject(0); if (acctInfo == null || acctInfo.get("avail_bal") == null) return BigDecimal.ZERO; BigDecimal balance = acctInfo.getBigDecimal("avail_bal"); return balance == null ? BigDecimal.ZERO : balance; } private Map enterpriseParams(DouGongUserWithdrawalProfile profile) { Map params = new HashMap<>(); params.put("reg_name", profile.getEnterpriseName()); params.put("license_code", profile.getCreditCode()); params.put("license_validity_type", validityType(profile.getLicenseValidityType())); params.put("license_begin_date", compactDate(profile.getLicenseBeginDate())); putFixedEndDate(params, "license_end_date", profile.getLicenseValidityType(), profile.getLicenseEndDate()); params.put("reg_prov_id", profile.getRegisteredProvinceCode()); params.put("reg_area_id", profile.getRegisteredCityCode()); params.put("reg_district_id", profile.getRegisteredDistrictCode()); params.put("reg_detail", profile.getRegisteredAddress()); params.put("legal_name", profile.getCertificateName()); params.put("legal_cert_type", "00"); params.put("legal_cert_no", profile.getCertificateCode()); String[] certificateDates = certificateDates(profile.getCertificateExpireTime()); params.put("legal_cert_validity_type", "长期".equals(certificateDates[1]) ? "1" : "0"); params.put("legal_cert_begin_date", compactDate(certificateDates[0])); if (!"长期".equals(certificateDates[1])) { params.put("legal_cert_end_date", compactDate(certificateDates[1])); } params.put("legal_cert_nationality", "CHN"); params.put("contact_name", profile.getContactName()); params.put("contact_mobile", profile.getPhone()); return params; } private String validityType(String value) { return "long_term".equals(value) ? "1" : "0"; } private void putFixedEndDate(Map params, String key, String validityType, String value) { if (!"long_term".equals(validityType) && value != null && !value.trim().isEmpty()) { params.put(key, compactDate(value)); } } private String compactDate(String value) { return value == null ? null : value.replace("-", ""); } private String[] certificateDates(String value) { String normalized = value == null ? "" : value.replace(",", ","); String[] values = normalized.split(",", -1); return values.length >= 2 ? values : new String[]{normalized, "长期"}; } }