package com.jsowell.adapay.service; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONReader; import com.alibaba.fastjson2.TypeReference; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.huifu.adapay.core.exception.BaseAdaPayException; import com.huifu.adapay.model.*; import com.huifu.adapay.model.CorpMember; import com.huifu.adapay.model.SettleAccount; import com.jsowell.adapay.common.*; import com.jsowell.adapay.config.AbstractAdapayConfig; import com.jsowell.adapay.dto.*; import com.jsowell.adapay.factory.AdapayConfigFactory; import com.jsowell.adapay.operation.PaymentReverseOperation; import com.jsowell.adapay.response.*; import com.jsowell.adapay.vo.*; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.enums.DelFlagEnum; import com.jsowell.common.enums.adapay.AdapayPayChannelEnum; import com.jsowell.common.enums.adapay.AdapayStatusEnum; import com.jsowell.common.enums.adapay.MerchantDelayModeEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.AdapayUtil; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.ZipUtil; import com.jsowell.common.util.id.IdUtils; import com.jsowell.pile.domain.AdapayMemberAccount; import com.jsowell.pile.domain.ClearingBillInfo; import com.jsowell.pile.domain.ClearingWithdrawInfo; import com.jsowell.pile.domain.MemberBasicInfo; import com.jsowell.pile.dto.PayOrderDTO; import com.jsowell.pile.service.*; import com.jsowell.pile.vo.base.MerchantInfoVO; import com.jsowell.pile.vo.web.WithdrawInfoVO; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cglib.beans.BeanMap; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import java.io.File; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @Slf4j @Service public class AdapayService { @Autowired private RedisCache redisCache; @Value("${adapay.callback}") private String ADAPAY_CALLBACK_URL; String wechatAppId1 = "wxbb3e0d474569481d"; // 万车充 @Autowired private AdapayMemberAccountService adapayMemberAccountService; @Autowired private ClearingWithdrawInfoService clearingWithdrawInfoService; @Autowired private ClearingBillInfoService clearingBillInfoService; @Autowired private PileMerchantInfoService pileMerchantInfoService; @Autowired private MemberBasicInfoService memberBasicInfoService; /** * 获取支付参数-微信支付 */ public Map createPaymentForWechat(PayOrderDTO dto) { // log.info("===============使用汇付支付-获取支付参数"); // 相同参数重复请求,返回同一个支付对象 String redisKey = CacheConstants.ADAPAY_ORDER_PARAM + dto.getOrderCode(); Map resultMap = redisCache.getCacheObject(redisKey); if (resultMap != null) { // 表示已经获取到支付参数了,后续再有支付请求就拒绝 return resultMap; } // 获取支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 获取openId MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(dto.getMemberId()); if (memberBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_GET_OPEN_ID_BY_CODE_ERROR); } // 支付场景 String type = dto.getType(); // 封装对象 String amount = AdapayUtil.formatAmount(dto.getPayAmount()); // 用户支付金额 String delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId()); String payMode = MerchantDelayModeEnum.getAdapayPayMode(delayMode); CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam(); // 请求订单号, 防止请求订单号重复,结尾拼接时间 String orderNo = dto.getOrderCode() + "_" + DateUtils.dateTimeNow(); createAdaPaymentParam.setOrder_no(orderNo); createAdaPaymentParam.setPay_amt(amount); createAdaPaymentParam.setApp_id(config.getAdapayAppId()); // todo 如果以后有支付宝等别的渠道,这里需要做修改,判断是什么渠道的请求 // 2024年6月13日11点55分,需要兼容支付宝小程序,首先判断请求来源,如为空默认微信小程序 String payChannel = StringUtils.isNotBlank(dto.getRequestSource()) ? dto.getRequestSource() : AdapayPayChannelEnum.WX_LITE.getValue(); createAdaPaymentParam.setPay_channel(payChannel); createAdaPaymentParam.setGoods_title(dto.getGoodsTitle()); createAdaPaymentParam.setGoods_desc(dto.getGoodsDesc()); // 这个字段是微信支付凭证的商品名 Map map = Maps.newHashMap(); map.put("type", type); map.put("orderCode", dto.getOrderCode()); map.put("payMode", payMode); map.put("memberId", dto.getMemberId()); createAdaPaymentParam.setDescription(JSON.toJSONString(map)); // 异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数 createAdaPaymentParam.setNotify_url(ADAPAY_CALLBACK_URL); createAdaPaymentParam.setExpend(JSON.toJSONString(ImmutableMap.of("open_id", memberBasicInfo.getOpenId()))); // 延时分账 if (StringUtils.isNotBlank(payMode)) { createAdaPaymentParam.setPay_mode(payMode); } try { Map response = Payment.create(BeanMap.create(createAdaPaymentParam), config.getWechatAppId()); log.info("创建汇付支付参数:{}, response:{}", JSON.toJSONString(createAdaPaymentParam), JSON.toJSONString(response)); if (response != null && !response.isEmpty()) { String status = (String) response.get("status"); if (!StringUtils.equals(status, AdapayStatusEnum.SUCCEEDED.getValue())) { String error_msg = (String) response.get("error_msg"); throw new BusinessException(ReturnCodeEnum.CODE_GET_WECHAT_PAY_PARAMETER_ERROR.getValue(), error_msg); } JSONObject expend = JSONObject.parseObject(response.get("expend").toString()); JSONObject pay_info = expend.getJSONObject("pay_info"); resultMap = JSONObject.parseObject(pay_info.toJSONString(), new TypeReference>() {}); } } catch (BaseAdaPayException e) { log.error("汇付-获取支付对象发生异常, orderCode:{}", dto.getOrderCode(), e); } // 放缓存 if (resultMap != null) { // 请求参数放入缓存,15分钟以内返回同一个支付参数 redisCache.setCacheObject(redisKey, resultMap, 15, TimeUnit.MINUTES); // 请求订单号放redis redisCache.setCacheObject(CacheConstants.ORDER_WECHAT_PAY_PARAMETERS + dto.getOrderCode(), orderNo, CacheConstants.cache_expire_time_10d); } return resultMap; } /** * 获取支付参数-支付宝支付 */ public Map createPaymentForAlipay(PayOrderDTO dto) { // log.info("===============使用汇付支付-获取支付参数"); // 相同参数重复请求,返回同一个支付对象 String redisKey = CacheConstants.ADAPAY_ORDER_PARAM + dto.getOrderCode(); Map resultMap = redisCache.getCacheObject(redisKey); if (resultMap != null) { // 表示已经获取到支付参数了,后续再有支付请求就拒绝 return resultMap; } // 获取支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getAlipayAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 获取openId MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(dto.getMemberId()); if (memberBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_GET_OPEN_ID_BY_CODE_ERROR); } // 支付场景 String type = dto.getType(); // 封装对象 String amount = AdapayUtil.formatAmount(dto.getPayAmount()); // 用户支付金额 String delayMode = dto.getDelayMode(); if (StringUtils.isBlank(delayMode)) { delayMode = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAlipayAppId()); } String payMode = MerchantDelayModeEnum.getAdapayPayMode(delayMode); CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam(); // 请求订单号, 防止请求订单号重复,结尾拼接时间 String orderNo = dto.getOrderCode() + "_" + DateUtils.dateTimeNow(); createAdaPaymentParam.setOrder_no(orderNo); createAdaPaymentParam.setPay_amt(amount); createAdaPaymentParam.setApp_id(config.getAdapayAppId()); // 2024年6月13日11点55分,需要兼容支付宝小程序,首先判断请求来源,如为空默认微信小程序 String payChannel = StringUtils.isNotBlank(dto.getRequestSource()) ? dto.getRequestSource() : AdapayPayChannelEnum.WX_LITE.getValue(); createAdaPaymentParam.setPay_channel(payChannel); createAdaPaymentParam.setGoods_title(dto.getGoodsTitle()); createAdaPaymentParam.setGoods_desc(dto.getGoodsDesc()); // 这个字段是微信支付凭证的商品名 Map map = Maps.newHashMap(); map.put("type", type); map.put("orderCode", dto.getOrderCode()); map.put("payMode", payMode); map.put("memberId", dto.getMemberId()); createAdaPaymentParam.setDescription(JSON.toJSONString(map)); // 异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数 createAdaPaymentParam.setNotify_url(ADAPAY_CALLBACK_URL); // alipay_lite参数 buyer_id String(100) Y 买家的支付宝用户 id createAdaPaymentParam.setExpend(JSON.toJSONString(ImmutableMap.of("buyer_id", memberBasicInfo.getBuyerId()))); // 延时分账 if (StringUtils.isNotBlank(payMode)) { createAdaPaymentParam.setPay_mode(payMode); } try { Map response = Payment.create(BeanMap.create(createAdaPaymentParam), config.getWechatAppId()); log.info("创建汇付支付参数:{}, response:{}", JSON.toJSONString(createAdaPaymentParam), JSON.toJSONString(response)); if (response != null && !response.isEmpty()) { String status = (String) response.get("status"); if (!StringUtils.equals(status, AdapayStatusEnum.SUCCEEDED.getValue())) { String error_msg = (String) response.get("error_msg"); throw new BusinessException(ReturnCodeEnum.CODE_GET_WECHAT_PAY_PARAMETER_ERROR.getValue(), error_msg); } JSONObject expend = JSONObject.parseObject(response.get("expend").toString()); JSONObject pay_info = expend.getJSONObject("pay_info"); resultMap = JSONObject.parseObject(pay_info.toJSONString(), new TypeReference>() {}); } } catch (BaseAdaPayException e) { log.error("汇付-获取支付对象发生异常, orderCode:{}", dto.getOrderCode(), e); } // 放缓存 if (resultMap != null) { // 请求参数放入缓存,15分钟以内返回同一个支付参数 redisCache.setCacheObject(redisKey, resultMap, 15, TimeUnit.MINUTES); // 请求订单号放redis redisCache.setCacheObject(CacheConstants.ORDER_WECHAT_PAY_PARAMETERS + dto.getOrderCode(), orderNo, CacheConstants.cache_expire_time_10d); } return resultMap; } /** * 创建个人用户 */ public void createAdapayMember(CreatePersonalMemberDTO dto) throws BaseAdaPayException, BusinessException { SettleAccountDTO request = SettleAccountDTO.builder() .merchantId(dto.getMerchantId()) .location(dto.getLocation()) .email(dto.getEmail()) .gender(dto.getGender()) .nickname(dto.getNickname()) .wechatAppId(pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId())) .build(); createMember(request); } /** * 创建企业用户 */ public void createCorpMember(CreateCorpMemberDTO dto) throws BaseAdaPayException, BusinessException { SettleAccountDTO request = SettleAccountDTO.builder() .merchantId(dto.getMerchantId()) .wechatAppId(pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId())) .businessName(dto.getName()) .provCode(dto.getProvCode()) .areaCode(dto.getAreaCode()) .socialCreditCode(dto.getSocialCreditCode()) .socialCreditCodeExpires(dto.getSocialCreditCodeExpires()) .businessScope(dto.getBusinessScope()) .legalPerson(dto.getLegalPerson()) .legalCertId(dto.getLegalCertId()) .legalCertIdExpires(dto.getLegalCertIdExpires()) .legalMp(dto.getLegalMp()) .address(dto.getAddress()) .zipCode(dto.getZipCode()) .telphone(dto.getTelphone()) .email(dto.getEmail()) .imgList(dto.getImgList()) .build(); createCorpMember(request); } /** * 创建结算账户 */ public void createSettleAccount(CreateSettleAccountDTO dto) throws BaseAdaPayException, BusinessException { AdapayMemberAccount adapayMemberAccount = requireCurrentMemberAccount(dto.getMerchantId()); if (CollectionUtils.isNotEmpty(selectSettleAccount(dto.getMerchantId()))) { throw new BusinessException("", "当前商户已存在结算账户"); } String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); SettleAccountDTO request = buildSettleAccountDTO(dto); Map settleCount = createSettleAccountRequest(request, adapayMemberAccount.getAdapayMemberId(), wechatAppId); if (settleCount == null || StringUtils.equals((String) settleCount.get("status"), "failed")) { String errorMsg = settleCount == null ? "创建汇付结算账户失败" : (String) settleCount.get("error_msg"); throw new BusinessException("00500001", errorMsg); } AdapayMemberAccount updateRecord = new AdapayMemberAccount(); updateRecord.setAdapayMemberId(adapayMemberAccount.getAdapayMemberId()); updateRecord.setSettleAccountId((String) settleCount.get("id")); adapayMemberAccountService.updateAdapayMemberAccountByMemberId(updateRecord); } /** * 查询当前商户的结算账户 */ public List selectSettleAccount(String merchantId) throws BaseAdaPayException { AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId); if (adapayMemberAccount == null) { return Lists.newArrayList(); } String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(merchantId); String settleAccountId = adapayMemberAccount.getSettleAccountId(); if (StringUtils.isBlank(settleAccountId) && isCorpMember(adapayMemberAccount.getAdapayMemberId())) { AdapayCorpMemberVO corpMemberVO = queryCorpAdapayMemberInfo(adapayMemberAccount.getAdapayMemberId(), wechatAppId); if (corpMemberVO != null) { settleAccountId = corpMemberVO.getSettleAccountId(); } } AdapaySettleAccountVO adapaySettleAccountVO = queryAdapaySettleAccount(adapayMemberAccount.getAdapayMemberId(), settleAccountId, wechatAppId); if (adapaySettleAccountVO == null) { return Lists.newArrayList(); } adapaySettleAccountVO.setMerchantId(merchantId); return Lists.newArrayList(adapaySettleAccountVO); } /** * 创建汇付会员 * * @param dto * @throws Exception */ @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public void createMember(SettleAccountDTO dto) throws BaseAdaPayException, BusinessException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 逻辑删除原来审核不通过的记录 adapayMemberAccountService.deleteAuditFailed(dto.getMerchantId()); // 查询汇付会员关系 AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId()); if (adapayMemberAccount != null) { throw new BusinessException("", "当前商户已绑定汇付用户"); } log.info("=======execute CreateMember begin======="); Map memberParams = Maps.newHashMap(); String adapayMemberId = Constants.ADAPAY_MEMBER_PREFIX + IdUtils.getMemberId(); memberParams.put("member_id", adapayMemberId); memberParams.put("app_id", config.getAdapayAppId()); memberParams.put("location", dto.getLocation()); memberParams.put("email", dto.getEmail()); memberParams.put("gender", dto.getGender()); memberParams.put("nickname", dto.getNickname()); log.info("创建用户,请求参数:" + JSON.toJSONString(memberParams)); Map member = Member.create(memberParams, config.getWechatAppId()); log.info("创建用户,返回参数:" + JSON.toJSONString(member)); log.info("=======execute CreateMember end======="); if (member == null || StringUtils.equals((String) member.get("status"), "failed")) { String errorMsg = member == null ? "创建汇付用户失败" : (String) member.get("error_msg"); throw new BusinessException("00500001", errorMsg); } // 保存到数据库 adapayMemberAccount = new AdapayMemberAccount(); adapayMemberAccount.setMerchantId(dto.getMerchantId()); adapayMemberAccount.setAdapayMemberId(adapayMemberId); adapayMemberAccount.setStatus(Constants.ONE); adapayMemberAccountService.insertAdapayMemberAccount(adapayMemberAccount); } /** * 查询汇付会员信息 * * @param merchantId * @return */ public AdapayMemberAggregateVO selectAdapayMember(String merchantId) throws BaseAdaPayException { AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId); if (adapayMemberAccount == null) { log.error("通过merchantId:{}, 没有查询到结算账户配置", merchantId); return null; } AdapayMemberAggregateVO.AdapayMemberAggregateVOBuilder builder = AdapayMemberAggregateVO.builder() .adapayMemberId(adapayMemberAccount.getAdapayMemberId()); // 审核失败 if (Constants.TWO.equals(adapayMemberAccount.getStatus())) { AdapayCorpMemberVO adapayCorpMemberVO = new AdapayCorpMemberVO(); MerchantInfoVO merchantInfoVO = pileMerchantInfoService.getMerchantInfoVO(adapayMemberAccount.getMerchantId()); if (merchantInfoVO != null) { adapayCorpMemberVO.setName(merchantInfoVO.getMerchantName()); } adapayCorpMemberVO.setAuditState("B"); adapayCorpMemberVO.setAuditDesc(adapayMemberAccount.getRemark()); return builder .memberType("CORP") .bankAcctType(Constants.ONE) .adapayCorpMember(adapayCorpMemberVO) .settleAccountList(Lists.newArrayList()) .canDeleteUser(true) .build(); } // 通过merchantId获取appId String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(merchantId); String adapayMemberId = adapayMemberAccount.getAdapayMemberId(); List settleAccountList = selectSettleAccount(merchantId); boolean canDeleteUser = CollectionUtils.isEmpty(settleAccountList); builder .settleAccountList(settleAccountList) .canDeleteUser(canDeleteUser) .deleteBlockReason(canDeleteUser ? "" : "请先删除结算账户"); if (StringUtils.startsWith(adapayMemberId, Constants.ADAPAY_MEMBER_PREFIX)) { // 查询个人用户 AdapayMemberInfoVO adapayMemberInfoVO = queryAdapayMemberInfo(adapayMemberId, wechatAppId); return builder .memberType("PERSONAL") .bankAcctType(Constants.TWO) .adapayMember(adapayMemberInfoVO) .build(); } // 查询企业用户 AdapayCorpMemberVO adapayCorpMemberVO = queryCorpAdapayMemberInfo(adapayMemberId, wechatAppId); return builder .memberType("CORP") .bankAcctType(Constants.ONE) .adapayCorpMember(adapayCorpMemberVO) .build(); } /** * 查询汇付会员信息 */ public AdapayMemberInfoVO queryAdapayMemberInfo(String adapayMemberId, String wechatAppId) throws BaseAdaPayException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } if (StringUtils.isBlank(adapayMemberId)) { return null; } Map memberParams = Maps.newHashMap(); memberParams.put("member_id", adapayMemberId); memberParams.put("app_id", config.getAdapayAppId()); Map member = Member.query(memberParams, config.getWechatAppId()); log.info("==查询个人用户,请求参数:{},返回参数:{}", JSON.toJSONString(memberParams), JSON.toJSONString(member)); if (member == null || member.isEmpty() || !"succeeded".equals(member.get("status"))) { return null; } QueryMemberResponse queryMemberResponse = JSON.parseObject(JSON.toJSONString(member), QueryMemberResponse.class); AdapayMemberInfoVO resultVO = AdapayMemberInfoVO.builder() .memberId(adapayMemberId) .nickname(queryMemberResponse.getNickname()) .gender(queryMemberResponse.getGender()) .email(queryMemberResponse.getEmail()) .location(queryMemberResponse.getLocation()) .build(); return resultVO; } /** * 查询企业用户信息 */ public AdapayCorpMemberVO queryCorpAdapayMemberInfo(String adapayMemberId, String wechatAppId) throws BaseAdaPayException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map memberParams = Maps.newHashMap(); memberParams.put("member_id", adapayMemberId); memberParams.put("app_id", config.getAdapayAppId()); Map member = CorpMember.query(memberParams, config.getWechatAppId()); log.info("==查询企业用户信息 param:{}, result:{}", JSON.toJSONString(memberParams), JSON.toJSONString(member)); if (member == null || member.isEmpty() || !"succeeded".equals(member.get("status"))) { return null; } QueryCorpMemberResponse response = JSONObject.parseObject(JSON.toJSONString(member), QueryCorpMemberResponse.class); AdapayCorpMemberVO corpMemberVO = AdapayCorpMemberVO.builder() .memberId(adapayMemberId) .address(response.getAddress()) .name(response.getName()) .areaCode(response.getArea_code()) .provCode(response.getProv_code()) .auditDesc(response.getAudit_desc()) .auditState(response.getAudit_state()) .legalCertIdExpires(response.getLegal_cert_id_expires()) .businessScope(response.getBusiness_scope()) .legalMp(response.getLegal_mp()) .legalPerson(response.getLegal_person()) .legalCertId(response.getLegal_cert_id()) .telphone(response.getTelphone()) .zipCode(response.getZip_code()) .email(response.getEmail()) .socialCreditCode(response.getSocial_credit_code()) .socialCreditCodeExpires(response.getSocial_credit_code_expires()) .build(); if (StringUtils.isNotBlank(response.getSettle_accounts())) { JSONObject jsonObject = JSON.parseObject(response.getSettle_accounts()); JSONObject recipient = jsonObject.getJSONObject("recipient"); if (recipient != null) { corpMemberVO.setCardName(recipient.getString("cardName")); corpMemberVO.setCardNo(recipient.getString("cardNo")); } String settleAccountId = jsonObject.getString("id"); if (StringUtils.isNotEmpty(settleAccountId)) { corpMemberVO.setSettleAccountId(settleAccountId); AdapaySettleAccountVO adapaySettleAccountVO = queryAdapaySettleAccount(adapayMemberId, settleAccountId, config.getWechatAppId()); if (adapaySettleAccountVO != null) { corpMemberVO.setBankCode(adapaySettleAccountVO.getBankCode()); } } } return corpMemberVO; } /** * 创建结算账户请求 */ public Map createSettleAccountRequest(SettleAccountDTO dto, String adapayMemberId, String wechatAppId) throws BaseAdaPayException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 创建结算账户 Map accountInfo = Maps.newHashMap(); // 银行卡号 accountInfo.put("card_id", dto.getCardId()); accountInfo.put("card_no", dto.getCardNo()); // 银行卡对应的户名 accountInfo.put("card_name", dto.getCardName()); // 证件号,银行账户类型为对私时,必填 if (StringUtils.isNotBlank(dto.getCertId())) { accountInfo.put("cert_id", dto.getCertId()); } // 证件类型,仅支持:00-身份证,银行账户类型为对私时,必填 accountInfo.put("cert_type", "00"); // 手机号 accountInfo.put("tel_no", dto.getTelNo()); // 银行编码,详见附录 银行代码,银行账户类型对公时,必填 if (StringUtils.isNotBlank(dto.getBankCode())) { accountInfo.put("bank_code", dto.getBankCode()); } // 银行账户类型:1-对公;2-对私 accountInfo.put("bank_acct_type", dto.getBankAcctType()); // 银行账户开户银行所在省份编码 (省市编码),银行账户类型为对公时,必填 if (StringUtils.isNotBlank(dto.getProvCode())) { accountInfo.put("prov_code", dto.getProvCode()); } // 银行账户开户银行所在地区编码(省市编码),银行账户类型为对公时,必填 if (StringUtils.isNotBlank(dto.getAreaCode())) { accountInfo.put("area_code", dto.getAreaCode()); } Map settleCountParams = Maps.newHashMap(); settleCountParams.put("member_id", adapayMemberId); settleCountParams.put("app_id", config.getAdapayAppId()); // channel String Y 目前仅支持:bank_account(银行卡) settleCountParams.put("channel", "bank_account"); settleCountParams.put("account_info", accountInfo); Map settleCount = SettleAccount.create(settleCountParams, config.getWechatAppId()); log.info("创建汇付结算账户param:{}, result:{}", JSON.toJSONString(settleCountParams), JSON.toJSONString(settleCount)); return settleCount; } /** * 删除结算账户对象/创建删除结算账户请求 * 企业用户更新银行卡信息时调用,先删除后新建 */ public void createDeleteSettleAccountRequest(String adapayMemberId, String settleAccountId, String wechatAppId) throws BaseAdaPayException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map settleCountParams = Maps.newHashMap(); settleCountParams.put("settle_account_id", settleAccountId); settleCountParams.put("member_id", adapayMemberId); settleCountParams.put("app_id", config.getAdapayAppId()); Map settleCount = SettleAccount.delete(settleCountParams, wechatAppId); log.info("创建删除结算账户请求param:{}, result:{}", JSON.toJSONString(settleCountParams), JSON.toJSONString(settleCount)); } /** * 查询汇付结算账户信息 */ public AdapaySettleAccountVO queryAdapaySettleAccount(String adapayMemberId, String settleAccountId, String wechatAppId) throws BaseAdaPayException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } if (StringUtils.isBlank(adapayMemberId) || StringUtils.isBlank(settleAccountId)) { return null; } Map settleCountParams = Maps.newHashMap(); settleCountParams.put("settle_account_id", settleAccountId); settleCountParams.put("member_id", adapayMemberId); settleCountParams.put("app_id", config.getAdapayAppId()); Map settleAccount = SettleAccount.query(settleCountParams, config.getWechatAppId()); log.info("==查询汇付结算账户信息param:{}, result:{}", JSON.toJSONString(settleCountParams), JSON.toJSONString(settleAccount)); if (settleAccount == null || settleAccount.isEmpty() || !"succeeded".equals(settleAccount.get("status"))) { return null; } QueryMemberResponse.SettleAccount settleAccountInfo = JSON.parseObject(JSON.toJSONString(settleAccount), QueryMemberResponse.SettleAccount.class); QueryMemberResponse.AccountInfo accountInfo = settleAccountInfo.getAccount_info(); AdapaySettleAccountVO resultVO = AdapaySettleAccountVO.builder() .adapayMemberId(settleAccountInfo.getMember_id()) .settleAccountId(settleAccountInfo.getId()) .cardId(accountInfo.getCard_id()) .cardName(accountInfo.getCard_name()) .certId(accountInfo.getCert_id()) .certType(accountInfo.getCert_type()) .telNo(accountInfo.getTel_no()) .bankName(accountInfo.getBank_name()) .bankCode(accountInfo.getBank_code()) .bankAcctType(accountInfo.getBank_acct_type()) .provCode(accountInfo.getProv_code()) .areaCode(accountInfo.getArea_code()) .build(); return resultVO; } /** * 查询汇付会员账户余额 */ public AdapayAccountBalanceVO queryAdapayAccountBalance(String merchantId) throws BaseAdaPayException { String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(merchantId); // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } AdapayAccountBalanceVO vo = AdapayAccountBalanceVO.builder().build(); // 通过merchantId 查询出汇付会员id 和 结算账户id,用来查询余额 AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId); if (adapayMemberAccount == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_MEMBER_IS_NULL_ERROR); } String settle_account_id = adapayMemberAccount.getSettleAccountId(); String member_id = adapayMemberAccount.getAdapayMemberId(); Map queryParams = Maps.newHashMap(); queryParams.put("settle_account_id", settle_account_id); queryParams.put("member_id", member_id); queryParams.put("app_id", config.getAdapayAppId()); Map settleCount = SettleAccount.balance(queryParams, config.getWechatAppId()); if (settleCount == null || settleCount.isEmpty() || !"succeeded".equals(settleCount.get("status"))) { return vo; } vo.setFrzBalance(new BigDecimal((String) settleCount.get("frz_balance"))); vo.setAcctBalance(new BigDecimal((String) settleCount.get("acct_balance"))); vo.setAvlBalance(new BigDecimal((String) settleCount.get("avl_balance"))); vo.setLastAvlBalance(new BigDecimal((String) settleCount.get("last_avl_balance"))); vo.setAdapayMemberId(adapayMemberAccount.getAdapayMemberId()); vo.setSettleAccountId(adapayMemberAccount.getSettleAccountId()); // 昨日收入 BigDecimal yesterdayRevenue = BigDecimal.ZERO; ClearingBillInfo clearingBillInfo = clearingBillInfoService.selectByMerchantIdAndTradeDate(merchantId, DateUtils.getYesterdayStr()); if (clearingBillInfo != null) { yesterdayRevenue = clearingBillInfo.getActualClearingAmount(); } vo.setYesterdayRevenue(yesterdayRevenue); // 累计提现金额 // BigDecimal totalWithdraw = BigDecimal.ZERO; // List withdrawInfoVOS = clearingWithdrawInfoService.selectByMerchantId(merchantId); // if (CollectionUtils.isNotEmpty(withdrawInfoVOS)) { // totalWithdraw = withdrawInfoVOS.stream().map(WithdrawInfoVO::getCashAmt).reduce(BigDecimal.ZERO, BigDecimal::add); // } // BigDecimal totalWithdraw = clearingWithdrawInfoService.queryTotalWithdraw(merchantId); vo.setTotalWithdraw(clearingWithdrawInfoService.queryTotalWithdraw(merchantId)); // 在途金额 BigDecimal pendingAmount = BigDecimal.ZERO; BigDecimal todayWithdrawalAmount = BigDecimal.ZERO; List withdrawInfoVOS = clearingWithdrawInfoService.selectByMerchantId(merchantId); // log.info("==查询提现在途金额param:{}, result:{}", JSON.toJSONString(withdrawInfoVOS), JSON.toJSONString(pendingAmount)); if (CollectionUtils.isNotEmpty(withdrawInfoVOS)) { pendingAmount = withdrawInfoVOS.stream() .filter(item -> Constants.ZERO.equals(item.getStatusDesc())) .map(WithdrawInfoVO::getCashAmt) .reduce(BigDecimal.ZERO, BigDecimal::add); // 查询今天的提现金额 for (WithdrawInfoVO withdrawInfoVO : withdrawInfoVOS) { // 如果applicationTime在当天,则加到todayWithdrawalAmount中 if (DateUtils.isToday(withdrawInfoVO.getApplicationTime())) { todayWithdrawalAmount = todayWithdrawalAmount.add(withdrawInfoVO.getCashAmt()); } } } vo.setPendingAmount(pendingAmount); // BigDecimal todayWithdrawalAmount = clearingWithdrawInfoService.queryTodayWithdrawalAmount(merchantId); // 如果大于0,则重新更新LastAvlBalance if (todayWithdrawalAmount.compareTo(BigDecimal.ZERO) > 0) { vo.setLastAvlBalance(BigDecimal.ZERO.max(vo.getLastAvlBalance().subtract(todayWithdrawalAmount))); } return vo; } /** * 更新结算账户设置 * * @param dto * @throws BaseAdaPayException */ public void updateSettleAccountConfig(UpdateAccountConfigDTO dto) throws BaseAdaPayException { String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 通过merchantId 查询出汇付会员id 和 结算账户id,用来查询余额 AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId()); if (adapayMemberAccount == null) { log.error("通过merchantId:{}, 没有查询到结算账户配置", dto.getMerchantId()); return; } // 修改账户配置 Map params = Maps.newHashMap(); params.put("app_id", config.getAdapayAppId()); params.put("member_id", adapayMemberAccount.getAdapayMemberId()); params.put("settle_account_id", adapayMemberAccount.getSettleAccountId()); if (StringUtils.isNotBlank(dto.getMinAmt())) { params.put("min_amt", dto.getMinAmt()); } if (StringUtils.isNotBlank(dto.getRemainedAmt())) { params.put("remained_amt", dto.getRemainedAmt()); } if (StringUtils.isNotBlank(dto.getChannelRemark())) { params.put("channel_remark", dto.getChannelRemark()); } Map settleCount = SettleAccount.update(params); log.info("更新结算账户设置 param:{}, result:{}", JSON.toJSONString(params), JSON.toJSONString(settleCount)); } /** * 创建企业用户 */ public void createCorpMember(SettleAccountDTO dto) throws BaseAdaPayException, BusinessException { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 逻辑删除原来审核不通过的记录 adapayMemberAccountService.deleteAuditFailed(dto.getMerchantId()); AdapayMemberAccount currentAccount = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId()); if (currentAccount != null) { throw new BusinessException("", "当前商户已绑定汇付用户"); } // 创建企业用户参数 Map memberParams = Maps.newHashMap(); String adapayMemberId = Constants.ADAPAY_CORP_MEMBER_PREFIX + IdUtils.getMemberId(); // 先保存一条记录 AdapayMemberAccount adapayMemberAccount = new AdapayMemberAccount(); adapayMemberAccount.setMerchantId(dto.getMerchantId()); adapayMemberAccount.setAdapayMemberId(adapayMemberId); adapayMemberAccount.setStatus(Constants.ZERO); adapayMemberAccountService.insertAdapayMemberAccount(adapayMemberAccount); memberParams.put("member_id", adapayMemberId); memberParams.put("app_id", config.getAdapayAppId()); // memberParams.put("order_no", "jsdk_order" + System.currentTimeMillis()); memberParams.put("order_no", IdUtils.get16UUID("jsdk_order")); memberParams.put("social_credit_code_expires", dto.getSocialCreditCodeExpires()); memberParams.put("business_scope", dto.getBusinessScope()); memberParams.put("name", dto.getBusinessName()); memberParams.put("prov_code", dto.getProvCode()); memberParams.put("area_code", dto.getAreaCode()); memberParams.put("social_credit_code", dto.getSocialCreditCode()); memberParams.put("legal_person", dto.getLegalPerson()); memberParams.put("legal_cert_id", dto.getLegalCertId()); memberParams.put("legal_cert_id_expires", dto.getLegalCertIdExpires()); memberParams.put("legal_mp", dto.getLegalMp()); memberParams.put("address", dto.getAddress()); memberParams.put("zip_code", dto.getZipCode()); memberParams.put("telphone", dto.getTelphone()); memberParams.put("email", dto.getEmail()); memberParams.put("notify_url", ADAPAY_CALLBACK_URL); File file = ZipUtil.createZipFileFromImages(dto.getImgList()); Map member = CorpMember.create(memberParams, file, config.getWechatAppId()); log.info("创建企业账户param:{}, result:{}", JSON.toJSONString(memberParams), JSON.toJSONString(member)); if (StringUtils.equals((String) member.get("status"), "failed")) { String error_msg = (String) member.get("error_msg"); adapayMemberAccount.setStatus(Constants.TWO); // 创建失败,改状态 adapayMemberAccount.setRemark(error_msg); adapayMemberAccountService.updateAdapayMemberAccount(adapayMemberAccount); throw new BusinessException("", error_msg); } // 取消自动创建结算账户,手动创建结算账户 // Map settleCount = createSettleAccountRequest(dto, adapayMemberId, dto.getWechatAppId()); // // if (settleCount == null || StringUtils.equals((String) settleCount.get("status"), "failed")) { // String errorMsg = settleCount == null ? "创建汇付结算账户失败" : (String) settleCount.get("error_msg"); // throw new BusinessException("00500001", errorMsg); // } // String settleAccountId = (String) settleCount.get("id"); // // 更新数据库 // adapayMemberAccount.setSettleAccountId(settleAccountId); // adapayMemberAccountService.updateAdapayMemberAccount(adapayMemberAccount); } /** * 提现逻辑/创建取现对象 * * @param dto * @throws BaseAdaPayException */ public void drawCash(WithdrawDTO dto) throws BaseAdaPayException { String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 查询余额 AdapayAccountBalanceVO adapayAccountBalanceVO = queryAdapayAccountBalance(dto.getMerchantId()); if (adapayAccountBalanceVO == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_MEMBER_IS_NULL_ERROR); } // 提现金额为昨日金额 withdrawalAmount BigDecimal withdrawalAmount = adapayAccountBalanceVO.getLastAvlBalance(); // 提现手续费 每笔固定5元 2025年2月13日11点47分手续费改为参数传入 // BigDecimal feeAmt = new BigDecimal("5"); BigDecimal feeAmt = new BigDecimal(dto.getFeeAmt()); // 实际提现到账金额 BigDecimal cashAmt = withdrawalAmount.subtract(feeAmt); // 可提现金额减去手续费后需大于0 if (cashAmt.compareTo(BigDecimal.ZERO) <= 0) { throw new BusinessException(ReturnCodeEnum.CODE_INSUFFICIENT_BALANCE_ERROR); } // 发送提现申请 // Map settleCountParams = Maps.newHashMap(); String orderNo = "drawcash_" + dto.getMerchantId() + "_" + System.currentTimeMillis(); // settleCountParams.put("order_no", orderNo); // settleCountParams.put("cash_amt", AdapayUtil.formatAmount(cashAmt)); // settleCountParams.put("member_id", adapayAccountBalanceVO.getAdapayMemberId()); // settleCountParams.put("app_id", config.getAdapayAppId()); // settleCountParams.put("settle_account_id", adapayAccountBalanceVO.getSettleAccountId()); // settleCountParams.put("cash_type", "T1"); // settleCountParams.put("notify_url", ADAPAY_CALLBACK_URL); Map settleCount = createDrawcashRequest(orderNo, cashAmt, adapayAccountBalanceVO.getAdapayMemberId(), config.getAdapayAppId(), adapayAccountBalanceVO.getSettleAccountId(), config.getWechatAppId()); // log.info("申请取现接口,请求参数:{}, 返回参数:{}", JSON.toJSONString(settleCountParams), JSON.toJSONString(settleCount)); if (settleCount == null) { throw new BusinessException("", "申请取现接口发生异常"); } if (AdapayStatusEnum.FAILED.getValue().equals(settleCount.get("status"))) { throw new BusinessException((String) settleCount.get("error_code"), (String) settleCount.get("error_msg")); } String id = (String) settleCount.get("id"); // 发起支付手续费请求 inMemberId为0表示本商户 if (BigDecimal.ZERO.compareTo(feeAmt) > 0) { createBalancePaymentRequest(adapayAccountBalanceVO.getAdapayMemberId(), Constants.ZERO, feeAmt.toString(), "提现手续费", "提现单号:" + id, config.getWechatAppId()); } // 保存提现记录 ClearingWithdrawInfo record = new ClearingWithdrawInfo(); record.setMerchantId(dto.getMerchantId()); record.setWithdrawCode(id); record.setOrderNo(orderNo); record.setWithdrawStatus(Constants.ZERO); record.setWithdrawAmt(withdrawalAmount); // 申请提现金额 record.setFeeAmt(feeAmt); // 提现手续费 record.setCreditedAmt(cashAmt); // 到账金额 Date now = new Date(); record.setApplicationTime(now); record.setCreateTime(now); record.setDelFlag(DelFlagEnum.NORMAL.getValue()); clearingWithdrawInfoService.insertSelective(record); // 修改清分账单为提现中 List list = clearingBillInfoService.selectByMerchantId(dto.getMerchantId(), "2"); List clearingBillIds = list.stream().map(ClearingBillInfo::getId).collect(Collectors.toList()); String billStatus = "3"; clearingBillInfoService.updateStatus(clearingBillIds, billStatus, id); } /** * 创建提现请求 */ public Map createDrawcashRequest(String orderNo, BigDecimal cashAmt, String adapayMemberId, String adapayAppId, String settleAccountId, String wechatAppId) throws BaseAdaPayException { Map settleCountParams = Maps.newHashMap(); settleCountParams.put("order_no", orderNo); settleCountParams.put("cash_amt", AdapayUtil.formatAmount(cashAmt)); settleCountParams.put("member_id", adapayMemberId); settleCountParams.put("app_id", adapayAppId); settleCountParams.put("settle_account_id", settleAccountId); settleCountParams.put("cash_type", "T1"); settleCountParams.put("notify_url", ADAPAY_CALLBACK_URL); Map settleCount = Drawcash.create(settleCountParams, wechatAppId); log.info("申请取现接口,请求参数:{}, 返回参数:{}", JSON.toJSONString(settleCountParams), JSON.toJSONString(settleCount)); return settleCount; } /** * 查询取现对象 * * @param orderNo 请求订单号 */ public DrawCashDetailVO queryDrawCashDetail(String orderNo, String wechatAppId) throws BaseAdaPayException { Map queryCashParam = Maps.newHashMap(); queryCashParam.put("order_no", orderNo); Map response = Drawcash.query(queryCashParam, wechatAppId); log.info("查询取现对象param:{}, result:{}", JSON.toJSONString(queryCashParam), JSON.toJSONString(response)); if (response != null) { QueryDrawCashResponse queryDrawCashResponse = JSON.parseObject(JSON.toJSONString(response), QueryDrawCashResponse.class); if (queryDrawCashResponse == null || queryDrawCashResponse.isNotSuccess()) { return null; } QueryDrawCashResponse.Cash cash = queryDrawCashResponse.getCashList().get(0); DrawCashDetailVO vo = new DrawCashDetailVO(); vo.setCashId(cash.getCashId()); vo.setCashAmt(cash.getCashAmt()); vo.setTransStat(cash.getTransStat()); vo.setStatusDesc(cash.getTransStatusDesc()); return vo; } return null; } /** * 更新汇付会员信息 * * @param dto * @return * @throws BaseAdaPayException */ public void updateAdapayMember(Map payload) throws BaseAdaPayException { String merchantId = (String) payload.get("merchantId"); AdapayMemberAccount adapayMemberAccount = requireCurrentMemberAccount(merchantId); if (isPersonalMember(adapayMemberAccount.getAdapayMemberId())) { UpdatePersonalMemberDTO dto = JSON.parseObject(JSON.toJSONString(payload), UpdatePersonalMemberDTO.class); updatePersonalMember(dto); return; } UpdateCorpMemberDTO dto = JSON.parseObject(JSON.toJSONString(payload), UpdateCorpMemberDTO.class); updateCorpMember(dto); } public void updateCorpMember(UpdateCorpMemberDTO dto) throws BaseAdaPayException { SettleAccountDTO request = SettleAccountDTO.builder() .merchantId(dto.getMerchantId()) .businessName(dto.getName()) .provCode(dto.getProvCode()) .areaCode(dto.getAreaCode()) .socialCreditCodeExpires(dto.getSocialCreditCodeExpires()) .businessScope(dto.getBusinessScope()) .legalPerson(dto.getLegalPerson()) .legalCertId(dto.getLegalCertId()) .legalCertIdExpires(dto.getLegalCertIdExpires()) .legalMp(dto.getLegalMp()) .address(dto.getAddress()) .zipCode(dto.getZipCode()) .telphone(dto.getTelphone()) .email(dto.getEmail()) .imgList(dto.getImgList()) .build(); updateAdapayMember(request); } public void updatePersonalMember(UpdatePersonalMemberDTO dto) throws BaseAdaPayException { String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } AdapayMemberAccount adapayMemberAccount = requireCurrentMemberAccount(dto.getMerchantId()); Map memberParams = Maps.newHashMap(); memberParams.put("member_id", adapayMemberAccount.getAdapayMemberId()); memberParams.put("app_id", config.getAdapayAppId()); memberParams.put("location", dto.getLocation()); memberParams.put("email", dto.getEmail()); memberParams.put("gender", dto.getGender()); memberParams.put("nickname", dto.getNickname()); Map member = Member.update(memberParams, config.getWechatAppId()); log.info("更新个人账户param:{}, result:{}", JSON.toJSONString(memberParams), JSON.toJSONString(member)); if (member == null || AdapayStatusEnum.FAILED.getValue().equals((String) member.get("status"))) { String errorMsg = member == null ? "更新汇付个人用户失败" : (String) member.get("error_msg"); throw new BusinessException("", errorMsg); } } public Map updateAdapayMember(SettleAccountDTO dto) throws BaseAdaPayException { String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId()); if (adapayMemberAccount == null) { log.error("通过merchantId:{}, 没有查询到结算账户配置", dto.getMerchantId()); return null; } Map memberParams = Maps.newHashMap(); memberParams.put("adapay_func_code", "corp_members.update"); memberParams.put("member_id", adapayMemberAccount.getAdapayMemberId()); memberParams.put("app_id", config.getAdapayAppId()); // memberParams.put("order_no", "jsdk_order_" + System.currentTimeMillis()); memberParams.put("order_no", IdUtils.get16UUID("jsdk_order_")); memberParams.put("social_credit_code_expires", dto.getSocialCreditCodeExpires()); memberParams.put("business_scope", dto.getBusinessScope()); String name = dto.getBusinessName(); if (StringUtils.isBlank(name)) { name = dto.getNickname(); } memberParams.put("name", name); memberParams.put("prov_code", dto.getProvCode()); memberParams.put("area_code", dto.getAreaCode()); memberParams.put("legal_person", dto.getLegalPerson()); memberParams.put("legal_cert_id", dto.getLegalCertId()); memberParams.put("legal_cert_id_expires", dto.getLegalCertIdExpires()); memberParams.put("legal_mp", dto.getLegalMp()); memberParams.put("address", dto.getAddress()); memberParams.put("zip_code", dto.getZipCode()); memberParams.put("telphone", dto.getTelphone()); memberParams.put("email", dto.getEmail()); File file = ZipUtil.createZipFileFromImages(dto.getImgList()); Map member = AdapayCommon.requestAdapayFile(memberParams, file, config.getWechatAppId()); log.info("更新企业账户param:{}, result:{}", JSON.toJSONString(memberParams), JSON.toJSONString(member)); if (AdapayStatusEnum.FAILED.getValue().equals((String) member.get("status"))) { throw new BusinessException("", (String) member.get("error_msg")); } return null; } /** * 创建交易确认请求/创建分账请求 * 这个方法只适用于给一个用户分账 * * @param paymentId 支付对象id * @param adapayMemberAccount 收到该账的汇付会员信息 * @param confirmAmt 确认的金额 * @param orderCode 订单编号 */ public PaymentConfirmResponse createPaymentConfirmRequest(String paymentId, AdapayMemberAccount adapayMemberAccount, BigDecimal confirmAmt, String orderCode, String wechatAppId) { DivMember divMember = new DivMember(); divMember.setMemberId(adapayMemberAccount.getAdapayMemberId()); divMember.setAmount(AdapayUtil.formatAmount(confirmAmt)); divMember.setFeeFlag(Constants.Y); PaymentConfirmParam param = PaymentConfirmParam.builder() .paymentId(paymentId) .divMemberList(Lists.newArrayList(divMember)) .confirmAmt(confirmAmt) .orderCode(orderCode) .wechatAppId(wechatAppId) .build(); return createPaymentConfirmRequest(param); } /** * 创建交易确认请求/创建分账请求/分账主逻辑 * 这个方法支持多用户分账 */ public PaymentConfirmResponse createPaymentConfirmRequest(PaymentConfirmParam param) { List adapayMemberAccounts = param.getDivMemberList(); // 收到该账的汇付会员信息 // 排除adapayMemberAccounts中amount为0的元素 if (CollectionUtils.isNotEmpty(adapayMemberAccounts)) { adapayMemberAccounts = adapayMemberAccounts.stream().filter(item -> new BigDecimal(item.getAmount()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList()); } // 分账对象信息 一次最多7个 if (adapayMemberAccounts.size() > 7) { throw new BusinessException("", "分账人数不能超过7人"); } String paymentId = param.getPaymentId(); // 支付对象id BigDecimal confirmAmt = param.getConfirmAmt(); // 确认的金额 String orderCode = param.getOrderCode(); // 订单编号 String wechatAppId = param.getWechatAppId(); // appId // 调汇付的分账接口 确认交易 Map confirmParams = Maps.newHashMap(); // Adapay生成的支付对象id confirmParams.put("payment_id", paymentId); // 请求订单号,只能为英文、数字或者下划线的一种或多种组合,保证在app_id下唯一 confirmParams.put("order_no", IdUtils.get16UUID("PC")); // 确认金额,必须大于0,保留两位小数点,如0.10、100.05等。必须小于等于原支付金额-已确认金额-已撤销金额。 confirmParams.put("confirm_amt", AdapayUtil.formatAmount(confirmAmt)); // 参与分账的会员列表 List adapayMemberIdList = adapayMemberAccounts.stream().map(DivMember::getMemberId).collect(Collectors.toList()); // TODO 附加说明, 记录每个账户分账金额 JSONObject jsonObject = new JSONObject(); jsonObject.put("orderCode", orderCode); jsonObject.put("adapayMemberIds", StringUtils.join(adapayMemberIdList, ",")); confirmParams.put("description", jsonObject.toJSONString()); confirmParams.put("div_members", adapayMemberAccounts); // 创建交易确认请求 Map paymentConfirm = null; try { paymentConfirm = PaymentConfirm.create(confirmParams, wechatAppId); } catch (BaseAdaPayException e) { log.error("创建交易确认请求error", e); } String jsonString = JSON.toJSONString(paymentConfirm); log.info("调分账接口param:{}, result:{}", JSON.toJSONString(confirmParams), jsonString); // 删除支付确认信息缓存 redisCache.deleteObject(CacheConstants.PAYMENT_CONFIRM_LIST + paymentId); return JSONObject.parseObject(jsonString, PaymentConfirmResponse.class); } /** * 创建余额支付请求 * 汇付余额转账 * @param outMemberId 出账用户的member_id, 若为商户本身时,请传入0 * @param inMemberId 入账用户的member_id, 若为商户本身时,请传入0 * @param transAmt 交易金额, 必须大于0,保留两位小数点,如0.10、100.05等 * @param title 标题 * @param desc 描述信息 */ public BalancePaymentResponse createBalancePaymentRequest(String outMemberId, String inMemberId, String transAmt, String title, String desc, String wechatAppId) { // 获取汇付支付配置 AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map balanceParam = Maps.newHashMap(); balanceParam.put("app_id", config.getAdapayAppId()); balanceParam.put("adapay_func_code", "settle_accounts.balancePay"); balanceParam.put("order_no", IdUtils.fastSimpleUUID()); balanceParam.put("out_member_id", outMemberId); balanceParam.put("in_member_id", inMemberId); balanceParam.put("trans_amt", AdapayUtil.formatAmount(transAmt)); balanceParam.put("goods_title", title); balanceParam.put("goods_desc", desc); Map paymentResult = null; try { paymentResult = AdapayCommon.requestAdapay(balanceParam, config.getWechatAppId()); } catch (BaseAdaPayException e) { log.error("创建余额支付请求error", e); } String jsonString = JSON.toJSONString(paymentResult); log.info("创建余额支付param:{}, result:{}", JSON.toJSONString(balanceParam), jsonString); return JSONObject.parseObject(jsonString, BalancePaymentResponse.class); } /** * 创建支付确认撤销 */ public void createConfirmReverse(String paymentConfirmId, String wechatAppId) throws BaseAdaPayException { Map confirmReverseParams = Maps.newHashMap(); confirmReverseParams.put("adapay_func_code", "payments.confirm.reverse"); confirmReverseParams.put("payment_confirm_id", paymentConfirmId); confirmReverseParams.put("reason", "支付确认撤销"); confirmReverseParams.put("order_no", IdUtils.fastSimpleUUID()); Map confirmReverseResult = AdapayCommon.requestAdapay(confirmReverseParams, wechatAppId); log.info("创建支付确认撤销param:{}, result:{}", JSON.toJSONString(confirmReverseParams), JSON.toJSONString(confirmReverseResult)); } /** * 实时分账的调退款接口 * 创建退款请求 */ public RefundResponse createRefundRequest(String paymentId, BigDecimal refundAmt, String wechatAppId, String memberId, String scenarioType, String orderCode) { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 实时分账的调退款接口 Map refundParams = Maps.newHashMap(); refundParams.put("refund_amt", AdapayUtil.formatAmount(refundAmt)); refundParams.put("refund_order_no", IdUtils.fastSimpleUUID()); // expand 为扩展域 Map expendMap = Maps.newHashMap(); expendMap.put("memberId", memberId); expendMap.put("scenarioType", scenarioType); if (StringUtils.isNotBlank(orderCode)) { expendMap.put("orderCode", orderCode); } refundParams.put("expand", expendMap); refundParams.put("reason", expendMap); refundParams.put("notify_url", ADAPAY_CALLBACK_URL); Map resultResponse = null; try { resultResponse = Refund.create(paymentId, refundParams, config.getWechatAppId()); } catch (BaseAdaPayException e) { log.error("汇付支付创建退款对象error", e); } String jsonString = JSON.toJSONString(resultResponse); log.info("汇付支付创建退款对象param:{}, result:{}", JSON.toJSONString(refundParams), JSON.toJSONString(jsonString)); return JSONObject.parseObject(jsonString, RefundResponse.class); } /** * 创建交易撤销请求 * 延迟分账未确认, 调交易撤销接口退款 * delay模式的商户使用 */ public PaymentReverseResponse createPaymentReverseRequest(PaymentReverseOperation paymentReverseOperation) { String wechatAppId = paymentReverseOperation.getMerchantKey(); String paymentId = paymentReverseOperation.getPaymentId(); BigDecimal reverseAmt = paymentReverseOperation.getReverseAmt(); String memberId = paymentReverseOperation.getMemberId(); String scenarioType = paymentReverseOperation.getScenarioType(); String orderCode = paymentReverseOperation.getOrderCode(); return createPaymentReverseRequest(paymentId, reverseAmt, wechatAppId, memberId, scenarioType, orderCode); } /** * 创建交易撤销请求 * 延迟分账未确认, 调交易撤销接口退款 * delay模式的商户使用 * @param wechatAppId 微信小程序appId */ public PaymentReverseResponse createPaymentReverseRequest(String paymentId, BigDecimal reverseAmt, String wechatAppId, String memberId, String scenarioType, String orderCode) { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } // 延迟分账未确认调撤销调撤销接口退款 Map reverseParams = Maps.newHashMap(); reverseParams.put("app_id", config.getAdapayAppId()); reverseParams.put("payment_id", paymentId); reverseParams.put("reverse_amt", AdapayUtil.formatAmount(reverseAmt)); reverseParams.put("order_no", IdUtils.fastSimpleUUID()); reverseParams.put("notify_url", ADAPAY_CALLBACK_URL); // expand 为扩展域 Map expendMap = Maps.newHashMap(); expendMap.put("memberId", memberId); expendMap.put("scenarioType", scenarioType); if (StringUtils.isNotBlank(orderCode)) { expendMap.put("orderCode", orderCode); } reverseParams.put("expand", expendMap); reverseParams.put("reason", expendMap); Map paymentReverse = null; try { paymentReverse = PaymentReverse.create(reverseParams, config.getWechatAppId()); } catch (BaseAdaPayException e) { log.error("汇付支付创建交易撤销对象error", e); } String jsonString = JSON.toJSONString(paymentReverse); log.info("汇付支付创建交易撤销对象param:{}, result:{}", JSON.toJSONString(reverseParams), jsonString); return JSONObject.parseObject(jsonString, PaymentReverseResponse.class); } /** * 查询支付撤销对象 * * @return */ public List queryPaymentReverse(String paymentId, String wechatAppId) throws BaseAdaPayException { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map reverse = Maps.newHashMap(); reverse.put("payment_id", paymentId); reverse.put("app_id", config.getAdapayAppId()); Map response = PaymentReverse.queryList(reverse, config.getWechatAppId()); JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(response)); List payment_reverses = jsonObject.getList("payment_reverses", PaymentReverseResponse.class); return payment_reverses; } /** * 查询支付退款对象 */ public List queryPaymentRefund(String paymentId, String wechatAppId) throws BaseAdaPayException { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map refundParams = Maps.newHashMap(); refundParams.put("payment_id", paymentId); refundParams.put("app_id", config.getAdapayAppId()); Map response = Refund.query(refundParams, config.getWechatAppId()); PaymentRefundResponse paymentRefundResponse = JSON.parseObject(JSON.toJSONString(response), PaymentRefundResponse.class); List refunds = paymentRefundResponse.getRefunds(); return refunds; } /** * 查询支付确认对象列表 * paymentId 必传 * wechatAppId 必传 */ public QueryPaymentConfirmDetailResponse queryPaymentConfirmList(QueryPaymentConfirmDTO dto) { QueryPaymentConfirmDetailResponse response = null; // 查缓存 String redisKey = CacheConstants.PAYMENT_CONFIRM_LIST + dto.getPaymentId(); // String redisResult = redisCache.getCacheObject(redisKey); // if (StringUtils.isNotBlank(redisResult)) { // response = JSONObject.parseObject(redisResult, QueryPaymentConfirmDetailResponse.class); // return response; // } AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map param = Maps.newHashMap(); param.put("payment_id", dto.getPaymentId()); param.put("app_id", config.getAdapayAppId()); try { Map map = PaymentConfirm.queryList(param, config.getWechatAppId()); response = JSON.parseObject(JSON.toJSONString(map), QueryPaymentConfirmDetailResponse.class); // log.info("queryPaymentConfirmDetailResponse:{}", JSON.toJSONString(queryPaymentConfirmDetailResponse)); redisCache.setCacheObject(redisKey, JSON.toJSONString(response), CacheConstants.cache_expire_time_10m); } catch (BaseAdaPayException e) { log.error("查询支付确认对象列表error", e); } return response; } /** * 查询支付确认对象详情 */ public PaymentConfirmInfo queryPaymentConfirmDetail(QueryPaymentConfirmDTO dto) { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map confirmParams = Maps.newHashMap(); confirmParams.put("payment_confirm_id", dto.getPaymentConfirmId()); PaymentConfirmInfo result = null; try { Map paymentConfirm = PaymentConfirm.query(confirmParams, config.getWechatAppId()); log.info("查询支付确认对象详情:{}", JSON.toJSONString(paymentConfirm)); result = JSON.parseObject(JSON.toJSONString(paymentConfirm), PaymentConfirmInfo.class); } catch (BaseAdaPayException e) { throw new RuntimeException(e); } return result; } /** * 查询账务流水 */ public void queryAcctFlowList(QueryAcctFlowDTO dto) throws BaseAdaPayException { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map acctFlowParams = Maps.newHashMap(); acctFlowParams.put("adapay_func_code", "acct.flow.list"); acctFlowParams.put("app_id", config.getAdapayAppId()); acctFlowParams.put("member_id", dto.getAdapayMemberId()); acctFlowParams.put("acct_type", dto.getAcctType()); acctFlowParams.put("page_index", dto.getPageNo()); acctFlowParams.put("page_size", dto.getPageSize()); acctFlowParams.put("begin_date", dto.getBeginDate()); acctFlowParams.put("end_date", dto.getEndDate()); Map acctFlowList = AdapayCommon.queryAdapay(acctFlowParams, config.getWechatAppId()); log.info("查询账务流水param:{}, result:{}", JSON.toJSONString(dto), JSON.toJSONString(acctFlowList)); } /** * 查询支付列表 */ public List queryPaymentList(String startTime, String endTime) throws BaseAdaPayException { List resultList = Lists.newArrayList(); String wechatAppId = "wxbb3e0d474569481d"; AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } String appId = config.getAdapayAppId(); long begin = DateUtils.dateStrToTimestamp(startTime); // 13位时间戳 long end = DateUtils.dateStrToTimestamp(endTime); // 13位时间戳 int pageNum = 0; // 页面容量,取值范围 1~20,默认值为 10 int pageSize = 20; // 页面容量,取值范围 1~20,默认值为 10 boolean hasMore; do { pageNum += 1; // 根据时间段查询支付对象列表 Map queryListParam = Maps.newHashMap(); queryListParam.put("app_id", appId); queryListParam.put("page_index", pageNum); queryListParam.put("page_size", pageSize); queryListParam.put("created_gte", begin); queryListParam.put("created_lte", end); System.out.println("查询支付对象列表请求参数:" + JSON.toJSONString(queryListParam)); Map paymentListResult = Payment.queryList(queryListParam, wechatAppId); if (paymentListResult == null) { break; } String jsonString = JSON.toJSONString(paymentListResult); System.out.println("查询支付对象列表result:" + jsonString); JSONObject jsonObject = JSON.parseObject(jsonString); List list = jsonObject.getList("payments", AdaPayment.class, JSONReader.Feature.FieldBased); resultList.addAll(list); hasMore = jsonObject.getBoolean("has_more"); } while (hasMore); return resultList; } /** * 根据请求号,查询支付信息列表 */ public List queryPaymentInfosByOrderNo(String orderNo, String wechatAppId) throws BaseAdaPayException { List resultList = Lists.newArrayList(); List adaPayments = queryPaymentsByOrderNo(orderNo, wechatAppId); if (CollectionUtils.isNotEmpty(adaPayments)) { for (AdaPayment adaPayment : adaPayments) { PaymentInfo paymentInfo = PaymentInfo.builder() .paymentId(adaPayment.getId()) .amount(adaPayment.getPay_amt()) .build(); resultList.add(paymentInfo); } } log.info("根据请求号:{}, wechatAppId:{}, 查询支付信息列表:{}", orderNo, wechatAppId, JSON.toJSONString(resultList)); return resultList; } /** * 查询支付列表 */ public List queryPaymentsByOrderNo(String orderNo, String wechatAppId) throws BaseAdaPayException { List resultList = Lists.newArrayList(); AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } String appId = config.getAdapayAppId(); int pageNum = 0; // 页面容量,取值范围 1~20,默认值为 10 int pageSize = 20; // 页面容量,取值范围 1~20,默认值为 10 boolean hasMore; do { pageNum += 1; // 根据时间段查询支付对象列表 Map queryListParam = Maps.newHashMap(); queryListParam.put("app_id", appId); queryListParam.put("page_index", pageNum); queryListParam.put("page_size", pageSize); queryListParam.put("order_no", orderNo); // System.out.println("查询支付对象列表请求参数:" + JSON.toJSONString(queryListParam)); Map paymentListResult = Payment.queryList(queryListParam, wechatAppId); if (paymentListResult == null) { break; } String jsonString = JSON.toJSONString(paymentListResult); // System.out.println("查询支付对象列表result:" + jsonString); JSONObject jsonObject = JSON.parseObject(jsonString); List list = jsonObject.getList("payments", AdaPayment.class, JSONReader.Feature.FieldBased); resultList.addAll(list); hasMore = jsonObject.getBoolean("has_more"); } while (hasMore); return resultList; } /** * 查询支付确认撤销对象 */ public ConfirmReverseResponse queryConfirmReverse(QueryConfirmReverseDTO dto) throws BaseAdaPayException { AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); if (config == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); } Map confirmReverseQueryParams = new HashMap<>(); confirmReverseQueryParams.put("adapay_func_code", "payments.confirm.reverse.details"); confirmReverseQueryParams.put("payment_confirm_id", dto.getPaymentConfirmId()); Map confirmReverseQueryResult = AdapayCommon.queryAdapay(confirmReverseQueryParams, config.getWechatAppId()); ConfirmReverseResponse confirmReverseResponse = JSON.parseObject(JSON.toJSONString(confirmReverseQueryResult), ConfirmReverseResponse.class); log.debug("confirmReverseQueryResult:{}", JSON.toJSONString(confirmReverseResponse)); return confirmReverseResponse; } /** * 换绑银行卡 * 用户需要换绑银行卡 1-删除结算账户信息,2-使用新账户信息创建结算账户】 */ public void changeBankCard(ChangeBankCardDTO dto) throws BaseAdaPayException { String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); // 获取汇付支会员信息 AdapayMemberAccount account = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId()); if (account == null) { return; } // 1-删除结算账户信息 String adapayMemberId = account.getAdapayMemberId(); String settleAccountId = null; AdapayCorpMemberVO adapayCorpMemberVO = this.queryCorpAdapayMemberInfo(adapayMemberId, wechatAppId); if (adapayCorpMemberVO != null) { settleAccountId = adapayCorpMemberVO.getSettleAccountId(); } this.createDeleteSettleAccountRequest(adapayMemberId, settleAccountId, wechatAppId); // 2-使用新账户信息创建结算账户 SettleAccountDTO settleAccountDTO = new SettleAccountDTO(); settleAccountDTO.setCardId(dto.getCardId()); settleAccountDTO.setCardName(dto.getCardName()); settleAccountDTO.setTelNo(dto.getTelNo()); settleAccountDTO.setBankCode(dto.getBankCode()); settleAccountDTO.setBankAcctType(dto.getBankAcctType()); settleAccountDTO.setProvCode(dto.getProvCode()); settleAccountDTO.setAreaCode(dto.getAreaCode()); Map settleAccount = this.createSettleAccountRequest(settleAccountDTO, adapayMemberId, wechatAppId); if (settleAccount != null && !StringUtils.equals((String) settleAccount.get("status"), "failed")) { AdapayMemberAccount updateRecord = new AdapayMemberAccount(); updateRecord.setAdapayMemberId(adapayMemberId); updateRecord.setSettleAccountId((String) settleAccount.get("id")); adapayMemberAccountService.updateAdapayMemberAccountByMemberId(updateRecord); } } /** * 查询支付撤销状态 * @param confirm * @return * @throws BaseAdaPayException */ public boolean queryConfirmReverseStatus(PaymentConfirmInfo confirm) throws BaseAdaPayException { boolean result = false; QueryConfirmReverseDTO dto = QueryConfirmReverseDTO.builder() .paymentConfirmId(confirm.getId()) .wechatAppId(wechatAppId1) .build(); ConfirmReverseResponse confirmReverseResponse = this.queryConfirmReverse(dto); if (confirmReverseResponse.isSuccess()) { result = true; } return result; } /** * 根据paymentId查询总分账金额 * 万车充专用 * @param paymentId * @return * @throws BaseAdaPayException */ public BigDecimal getTotalSplitAmountByPaymentId(String paymentId) throws BaseAdaPayException { BigDecimal totalSplitAmount = BigDecimal.ZERO; // 查询支付确认id QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO(); dto.setPaymentId(paymentId); dto.setWechatAppId(wechatAppId1); // 查询分账信息 QueryPaymentConfirmDetailResponse response = this.queryPaymentConfirmList(dto); if (response == null) { return totalSplitAmount; } List confirms = response.getPaymentConfirms(); if (CollectionUtils.isEmpty(confirms)) { return totalSplitAmount; } for (PaymentConfirmInfo confirm : confirms) { if (queryConfirmReverseStatus(confirm)) { log.info("支付确认id:{}撤销了。。。", confirm.getId()); continue; } BigDecimal confirmedAmt = new BigDecimal(confirm.getConfirmedAmt()); // 已确认金额 // 汇总已确认金额 totalSplitAmount = totalSplitAmount.add(confirmedAmt); } return totalSplitAmount; } /** * 创建结算账户 * @param dto * @throws BaseAdaPayException */ public void createBankAccount(SettleAccountDTO dto) throws BaseAdaPayException { CreateSettleAccountDTO request = CreateSettleAccountDTO.builder() .merchantId(dto.getMerchantId()) .bankAcctType(dto.getBankAcctType()) .cardId(dto.getCardId()) .cardNo(dto.getCardNo()) .cardName(dto.getCardName()) .certId(dto.getCertId()) .certType(dto.getCertType()) .telNo(dto.getTelNo()) .bankCode(dto.getBankCode()) .bankName(dto.getBankName()) .provCode(dto.getProvCode()) .areaCode(dto.getAreaCode()) .build(); createSettleAccount(request); } /** * 删除结算账户(先删除汇付的结算账户,再逻辑删除数据库) * @param dto * @throws BaseAdaPayException */ public void deleteSettleAccount(AdapayMemberInfoDTO dto) throws BaseAdaPayException { AdapayMemberAccount adapayMemberAccount = requireCurrentMemberAccount(dto.getMerchantId()); String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(dto.getMerchantId()); String adapayMemberId = StringUtils.isNotBlank(dto.getAdapayMemberId()) ? dto.getAdapayMemberId() : adapayMemberAccount.getAdapayMemberId(); String settleAccountId = StringUtils.isNotBlank(dto.getSettleAccountId()) ? dto.getSettleAccountId() : adapayMemberAccount.getSettleAccountId(); if (StringUtils.isBlank(settleAccountId) && isCorpMember(adapayMemberId)) { AdapayCorpMemberVO corpMemberVO = queryCorpAdapayMemberInfo(adapayMemberId, wechatAppId); if (corpMemberVO != null) { settleAccountId = corpMemberVO.getSettleAccountId(); } } if (StringUtils.isBlank(settleAccountId)) { throw new BusinessException("", "未查询到结算账户"); } this.createDeleteSettleAccountRequest(adapayMemberId, settleAccountId, wechatAppId); adapayMemberAccountService.clearSettleAccountByMerchantId(dto.getMerchantId()); } public void deleteAdapayMember(DeleteAdapayMemberDTO dto) throws BaseAdaPayException { AdapayMemberAccount adapayMemberAccount = requireCurrentMemberAccount(dto.getMerchantId()); if (StringUtils.isNotBlank(dto.getAdapayMemberId()) && !StringUtils.equals(dto.getAdapayMemberId(), adapayMemberAccount.getAdapayMemberId())) { throw new BusinessException("", "汇付用户信息不匹配"); } if (CollectionUtils.isNotEmpty(selectSettleAccount(dto.getMerchantId()))) { throw new BusinessException("", "请先删除结算账户"); } adapayMemberAccountService.deleteAccountByMerchantId(dto.getMerchantId()); } private AdapayMemberAccount requireCurrentMemberAccount(String merchantId) { AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId); if (adapayMemberAccount == null) { throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_MEMBER_IS_NULL_ERROR); } return adapayMemberAccount; } private boolean isPersonalMember(String adapayMemberId) { return StringUtils.startsWith(adapayMemberId, Constants.ADAPAY_MEMBER_PREFIX); } private boolean isCorpMember(String adapayMemberId) { return StringUtils.startsWith(adapayMemberId, Constants.ADAPAY_CORP_MEMBER_PREFIX); } private SettleAccountDTO buildSettleAccountDTO(CreateSettleAccountDTO dto) { SettleAccountDTO request = SettleAccountDTO.builder() .merchantId(dto.getMerchantId()) .bankAcctType(dto.getBankAcctType()) .cardId(dto.getCardId()) .cardNo(dto.getCardNo()) .cardName(dto.getCardName()) .certId(dto.getCertId()) .certType(dto.getCertType()) .telNo(dto.getTelNo()) .bankCode(dto.getBankCode()) .bankName(dto.getBankName()) .provCode(dto.getProvCode()) .areaCode(dto.getAreaCode()) .build(); String cardId = request.getCardId(); String cardNo = request.getCardNo(); if (StringUtils.isBlank(cardId) && StringUtils.isNotBlank(cardNo)) { request.setCardId(cardNo); } if (StringUtils.isBlank(cardNo) && StringUtils.isNotBlank(cardId)) { request.setCardNo(cardId); } return request; } /** * 根据paymentIdList查询分账信息 * @param paymentIdList * @return 未分帐paymentIdList */ public List getSplitInfoByPaymentIdList(List paymentIdList) throws BaseAdaPayException { if (CollectionUtils.isEmpty(paymentIdList)) { return new ArrayList<>(); } List unSplitList = Lists.newArrayList(); // 未分帐 List splitList = Lists.newArrayList(); // 已分帐 BigDecimal total = BigDecimal.ZERO; // 总分账金额 BigDecimal totalWithdrawalAmt = BigDecimal.ZERO; // 实际到账金额汇总 BigDecimal totalFeeAmt = BigDecimal.ZERO; // 手续费金额汇总 List selfList = Lists.newArrayList(); Map map = Maps.newHashMap(); for (String paymentId : paymentIdList) { if (StringUtils.isBlank(paymentId)) { continue; } // 查询支付确认id QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO(); dto.setPaymentId(paymentId); dto.setWechatAppId(wechatAppId1); // 查询分账信息 QueryPaymentConfirmDetailResponse response = this.queryPaymentConfirmList(dto); if (response != null) { List confirms = response.getPaymentConfirms(); if (CollectionUtils.isEmpty(confirms)) { unSplitList.add(paymentId); } else { splitList.add(paymentId); for (PaymentConfirmInfo confirm : confirms) { if (this.queryConfirmReverseStatus(confirm)) { log.info("支付确认id:" + confirm.getId() + "撤销了。。。"); continue; } JSONObject jsonObject = JSON.parseObject(confirm.getDescription()); String adapayMemberId = jsonObject.getString("adapayMemberId"); if (StringUtils.isBlank(adapayMemberId)) { adapayMemberId = jsonObject.getString("adapayMemberIds"); } BigDecimal confirmAmt = new BigDecimal(confirm.getConfirmAmt()); // 本次确认金额 BigDecimal confirmedAmt = new BigDecimal(confirm.getConfirmedAmt()); // 已确认金额 BigDecimal feeAmt = new BigDecimal(confirm.getFeeAmt()); // 手续费 // 汇总已确认金额 total = total.add(confirmedAmt); // 汇总手续费金额 totalFeeAmt = totalFeeAmt.add(feeAmt); // 汇总可提现金额 totalWithdrawalAmt = totalWithdrawalAmt.add(confirmAmt).subtract(feeAmt); // confirm List divMembers = confirm.getDivMembers(); // System.out.println("confirm:" + JSON.toJSONString(divMembers)); for (DivMember divMember : divMembers) { // 放map map.merge(divMember.getMemberId(), new BigDecimal(divMember.getAmount()), BigDecimal::add); } if (StringUtils.equals(adapayMemberId, "0") || StringUtils.equals(adapayMemberId, "AM29102732")) { // 0为默认平台id, AM29102732为罗总账户 selfList.add(paymentId); } } } } else { unSplitList.add(paymentId); } } log.info("\n入参paymentId数量:{}, 已分帐数量:{}, 未分帐数量:{}, 未分帐id:{} " + "\n已分帐:{}, 总分账:{}, 数量:{}" + "\n金额明细:[总到账金额:{}, 总手续费:{}] " + "\n自己:{}, 数量:{}", paymentIdList.size(), splitList.size(), unSplitList.size(), unSplitList, JSON.toJSONString(map), total, splitList.size(), totalWithdrawalAmt, totalFeeAmt, selfList, selfList.size()); return unSplitList; } /** * 根据paymentIdList查询分账信息 */ // public Map> getSplitInfoMapByPaymentIdList(List paymentIdList) throws BaseAdaPayException { // Map> resultMap = Maps.newHashMap(); // if (CollectionUtils.isEmpty(paymentIdList)) { // return resultMap; // } // List unSplitList = Lists.newArrayList(); // 未分帐 // List splitList = Lists.newArrayList(); // 已分帐 // List selfList = Lists.newArrayList(); // 自己分帐 // // BigDecimal total = BigDecimal.ZERO; // 总分账金额 // BigDecimal totalWithdrawalAmt = BigDecimal.ZERO; // 实际到账金额汇总 // BigDecimal totalFeeAmt = BigDecimal.ZERO; // 手续费金额汇总 // // Map amountDetailMap = Maps.newHashMap(); // for (String paymentId : paymentIdList) { // if (StringUtils.isBlank(paymentId)) { // continue; // } // // // 根据paymentId查询支付确认情况 // QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO(); // dto.setPaymentId(paymentId); // dto.setWechatAppId(wechatAppId1); // QueryPaymentConfirmDetailResponse response = this.queryPaymentConfirmList(dto); // // if (response == null) { // // 未查询到分账信息,add to unSplitList // unSplitList.add(paymentId); // continue; // } // // List confirms = response.getPaymentConfirms(); // if (CollectionUtils.isEmpty(confirms)) { // // confirms为空,add to unSplitList // unSplitList.add(paymentId); // continue; // } // // // 添加到已分帐list // splitList.add(paymentId); // for (PaymentConfirmInfo confirm : confirms) { // if (this.queryConfirmReverseStatus(confirm)) { // log.info("支付确认id:" + confirm.getId() + "撤销了。。。"); // continue; // } // JSONObject jsonObject = JSON.parseObject(confirm.getDescription()); // String adapayMemberId = jsonObject.getString("adapayMemberId"); // if (StringUtils.isBlank(adapayMemberId)) { // adapayMemberId = jsonObject.getString("adapayMemberIds"); // } // // BigDecimal confirmAmt = new BigDecimal(confirm.getConfirmAmt()); // 本次确认金额 // BigDecimal confirmedAmt = new BigDecimal(confirm.getConfirmedAmt()); // 已确认金额 // BigDecimal feeAmt = new BigDecimal(confirm.getFeeAmt()); // 手续费 // // // 汇总已确认金额 // total = total.add(confirmedAmt); // // // 汇总手续费金额 // totalFeeAmt = totalFeeAmt.add(feeAmt); // // // 汇总可提现金额 // totalWithdrawalAmt = totalWithdrawalAmt.add(confirmAmt).subtract(feeAmt); // // // confirm // List divMembers = confirm.getDivMembers(); // // System.out.println("confirm:" + JSON.toJSONString(divMembers)); // for (DivMember divMember : divMembers) { // // 放map // amountDetailMap.merge(divMember.getMemberId(), new BigDecimal(divMember.getAmount()), BigDecimal::add); // } // // if (StringUtils.equals(adapayMemberId, "0") // || StringUtils.equals(adapayMemberId, "AM29102732")) { // // 0为默认平台id, AM29102732为罗总账户 // selfList.add(paymentId); // } // } // } // log.info("\n入参paymentId数量:{}, 已分帐数量:{}, 未分帐数量:{}, 未分帐id:{} " + // "\n已分帐:{}, 总分账:{}, 数量:{}" + // "\n金额明细:[总到账金额:{}, 总手续费:{}] " + // "\n自己:{}, 数量:{}", // paymentIdList.size(), splitList.size(), unSplitList.size(), unSplitList, // JSON.toJSONString(amountDetailMap), total, splitList.size(), // totalWithdrawalAmt, totalFeeAmt, // selfList, selfList.size()); // // resultMap.put("unSplitList", unSplitList); // resultMap.put("splitList", splitList); // return resultMap; // } public Map> getSplitInfoMapByPaymentIdList(List paymentIdList) throws BaseAdaPayException { Map> resultMap = Maps.newHashMap(); if (CollectionUtils.isEmpty(paymentIdList)) { return resultMap; } List unSplitList = Lists.newArrayList(); // 未分帐 List splitList = Lists.newArrayList(); // 已分帐 List selfList = Lists.newArrayList(); // 自己分帐 // 使用原子引用包装可变对象 AtomicReference total = new AtomicReference<>(BigDecimal.ZERO); AtomicReference totalWithdrawalAmt = new AtomicReference<>(BigDecimal.ZERO); AtomicReference totalFeeAmt = new AtomicReference<>(BigDecimal.ZERO); Map amountDetailMap = Maps.newHashMap(); paymentIdList.parallelStream() .filter(StringUtils::isNotBlank) .forEach(paymentId -> { // 根据paymentId查询支付确认情况 QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO(); dto.setPaymentId(paymentId); dto.setWechatAppId(wechatAppId1); QueryPaymentConfirmDetailResponse response = this.queryPaymentConfirmList(dto); if (response == null) { // 未查询到分账信息,add to unSplitList synchronized (unSplitList) { unSplitList.add(paymentId); } return; } List confirms = response.getPaymentConfirms(); if (CollectionUtils.isEmpty(confirms)) { // confirms为空,add to unSplitList synchronized (unSplitList) { unSplitList.add(paymentId); } return; } for (PaymentConfirmInfo confirm : confirms) { try { if (queryConfirmReverseStatus(confirm)) { log.info("支付确认id:" + confirm.getId() + "撤销了。。。"); // confirms为空,add to unSplitList synchronized (unSplitList) { unSplitList.add(paymentId); } continue; } } catch (BaseAdaPayException e) { throw new RuntimeException(e); } // 添加到已分帐list synchronized (splitList) { splitList.add(paymentId); } JSONObject jsonObject = JSON.parseObject(confirm.getDescription()); String adapayMemberId = jsonObject.getString("adapayMemberId"); if (StringUtils.isBlank(adapayMemberId)) { adapayMemberId = jsonObject.getString("adapayMemberIds"); } BigDecimal confirmAmt = new BigDecimal(confirm.getConfirmAmt()); // 本次确认金额 BigDecimal confirmedAmt = new BigDecimal(confirm.getConfirmedAmt()); // 已确认金额 BigDecimal feeAmt = new BigDecimal(confirm.getFeeAmt()); // 手续费 // 汇总已确认金额 total.getAndUpdate(current -> current.add(confirmedAmt)); // 汇总手续费金额 totalFeeAmt.getAndUpdate(current -> current.add(feeAmt)); // 汇总可提现金额 totalWithdrawalAmt.getAndUpdate(current -> current.add(confirmAmt).subtract(feeAmt)); // confirm List divMembers = confirm.getDivMembers(); // System.out.println("confirm:" + JSON.toJSONString(divMembers)); for (DivMember divMember : divMembers) { synchronized (amountDetailMap) { // 放map amountDetailMap.merge(divMember.getMemberId(), new BigDecimal(divMember.getAmount()), BigDecimal::add); } } if (StringUtils.equals(adapayMemberId, "0") || StringUtils.equals(adapayMemberId, "AM29102732")) { // 0为默认平台id, AM29102732为罗总账户 synchronized (selfList) { selfList.add(paymentId); } } } } ); log.info("\n入参paymentId数量:{}, 已分帐数量:{}, 未分帐数量:{}, 未分帐id:{} " + "\n已分帐:{}, 总分账:{}, 数量:{}" + "\n金额明细:[总到账金额:{}, 总手续费:{}] " + "\n自己:{}, 数量:{}", paymentIdList.size(), splitList.size(), unSplitList.size(), unSplitList, JSON.toJSONString(amountDetailMap), total, splitList.size(), totalWithdrawalAmt, totalFeeAmt, selfList, selfList.size()); resultMap.put("unSplitList", unSplitList); resultMap.put("splitList", splitList); return resultMap; } }