package com.engine.salary.service.impl; import com.alibaba.fastjson.JSON; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.constant.SzyhApiConstant; import com.engine.salary.entity.datacollection.response.QuerySpecialAmountResponse; import com.engine.salary.entity.taxagent.po.TaxAgentPO; import com.engine.salary.entity.taxagent.po.TaxAgentTaxReturnPO; import com.engine.salary.entity.taxagent.response.SzyhResponseHead; import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationApiConfigPO; import com.engine.salary.entity.taxdeclaration.po.TaxDeclareRecordPO; import com.engine.salary.entity.taxpayment.dto.TaxAmountFormDTO; import com.engine.salary.entity.taxpayment.dto.TaxFeedbackResultDTO; import com.engine.salary.entity.taxpayment.dto.TaxWithheldVoucherResultDTO; import com.engine.salary.entity.taxpayment.param.TaxPaymentQueryParam; import com.engine.salary.entity.taxpayment.po.TaxPaymentRequestPO; import com.engine.salary.entity.taxpayment.response.BaseResponse; import com.engine.salary.enums.SalaryOnOffEnum; import com.engine.salary.enums.sicategory.DeleteTypeEnum; import com.engine.salary.enums.taxagent.TaxAgentTaxReturnStatusEnum; import com.engine.salary.enums.taxdeclaration.TaxDeclareStatusEnum; import com.engine.salary.enums.taxdeclaration.TaxPaymentServiceTypeEnum; import com.engine.salary.exception.SalaryRunTimeException; import com.engine.salary.mapper.taxpayment.TaxPaymentRequestMapper; import com.engine.salary.service.*; import com.engine.salary.util.*; import com.engine.salary.util.db.MapperProxyFactory; import dm.jdbc.util.IdGenerator; import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.transaction.annotation.Transactional; import weaver.hrm.User; import java.math.BigDecimal; import java.util.*; /** * @author chengliming * @date 2022-12-09 6:26 PM **/ @Slf4j public abstract class AbstractTaxPaymentService extends Service implements TaxPaymentService { protected TaxAgentTaxReturnService getTaxAgentTaxReturnService(User user) { return ServiceUtil.getService(TaxAgentTaxReturnServiceImpl.class, user); } protected TaxAgentService getTaxAgentService(User user) { return ServiceUtil.getService(TaxAgentServiceImpl.class, user); } protected TaxDeclarationApiConfigService getTaxDeclarationApiConfigService(User user) { return ServiceUtil.getService(TaxDeclarationApiConfigServiceImpl.class, user); } protected TaxDeclareRecordService getTaxDeclareRecordService(User user) { return ServiceUtil.getService(TaxDeclareRecordServiceImpl.class, user); } protected TaxPaymentRequestMapper getTaxPaymentRequestMapper() { return MapperProxyFactory.getProxy(TaxPaymentRequestMapper.class); } /** * 获取requestId * * @param returnPO * @param taxAgentName * @param param * @param apiConfig * @param clazz * @return */ protected T getRequestIdResponse(TaxAgentTaxReturnPO returnPO, String taxAgentName, TaxPaymentQueryParam param, TaxDeclarationApiConfigPO apiConfig, Class clazz) { throw new SalaryRunTimeException("暂无实现"); } protected BaseResponse getFeedbackResponse(TaxDeclarationApiConfigPO apiConfig, String requestId) { throw new SalaryRunTimeException("暂无实现"); } public TaxFeedbackResultDTO getFeedback(TaxPaymentQueryParam param) { throw new SalaryRunTimeException("暂无实现"); } /** * 发起请求获取requestId * * @param apiConfig * @param url * @param requestParam * @return */ protected T postRequest(TaxDeclarationApiConfigPO apiConfig, String url, Map requestParam, Class clazz) { String reqJson = JsonUtil.toJsonString(requestParam); log.info("getAsyncQueryResponse4Payment url: {}, params:\n{}\n", url, reqJson); Map params = new HashMap<>(1); Map header = SingnatureData.initHeader(params, apiConfig.getAppKey(), apiConfig.getAppSecret()); // 开始请求 String res = HttpUtil.doPost(url, header, reqJson, HttpUtil.JSON_TYPE); log.info("getAsyncQueryResponse4Payment response --- \n{}\n", res); return JsonUtil.parseObject(res, clazz); } /** * 发起请求获取反馈 * * @param apiConfig * @param requestId * @param url * @return */ protected String getRequest(TaxDeclarationApiConfigPO apiConfig, String requestId, String url) { Map params = new HashMap<>(1); params.put("requestId", requestId); Map header = SingnatureData.initHeader(Collections.emptyMap(), apiConfig.getAppKey(), apiConfig.getAppSecret()); return HttpUtil.getRequest(url, header, params); } protected TempWrapper checkBeforeGetRequestIdResponse(TaxPaymentQueryParam param) { TaxDeclarationApiConfigPO apiConfigPO = getTaxDeclarationApiConfigService(user).getConfig(true); TaxAgentTaxReturnPO taxReturnPO = getTaxAgentTaxReturnService(user).getByTaxAgentId(param.getTaxAgentId()); SalaryAssert.isTrue(Objects.nonNull(taxReturnPO) && TaxAgentTaxReturnStatusEnum.SUCCESS.getValue().equals(taxReturnPO.getCheckStatus()), SalaryI18nUtil.getI18nLabel(184010, "企业未通过验证,请先在【个税扣缴义务人】菜单验证企业报税信息")); TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(param.getTaxAgentId()); SalaryAssert.notNull(taxAgentPO, SalaryI18nUtil.getI18nLabel(100545, "个税扣缴义务人不存在")); TaxDeclareRecordPO taxDeclareRecord = getTaxDeclareRecordService(user).getById(param.getTaxDeclareRecordId()); SalaryAssert.notNull(taxDeclareRecord, "申报表不存在"); return new TempWrapper(apiConfigPO, taxReturnPO, taxAgentPO, taxDeclareRecord); } @Transactional(rollbackFor = Exception.class) public String getRequestId(TaxPaymentQueryParam param) { TempWrapper tempWrapper = checkBeforeGetRequestIdResponse(param); QuerySpecialAmountResponse queryResponse = getRequestIdResponse(tempWrapper.taxReturnPO, tempWrapper.taxAgentPO.getName(), param, tempWrapper.apiConfigPO, QuerySpecialAmountResponse.class); // 校验请求结果 String responseCode = Optional.ofNullable(queryResponse) .map(QuerySpecialAmountResponse::getHead) .map(SzyhResponseHead::getCode) .orElse(null); String requestId = Optional.ofNullable(queryResponse) .map(QuerySpecialAmountResponse::getBody) .map(QuerySpecialAmountResponse.QuerySpecialAmountBody::getRequestId) .orElse(null); if (!SzyhApiConstant.SUCCESS_CODE.equals(responseCode) || StringUtils.isEmpty(requestId)) { log.info("getAsyncQueryResponse4Payment code error:{}", JSON.toJSONString(queryResponse)); throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(95828, "服务异常,请稍后重试")); } // 存储 TaxPaymentRequestPO paymentRequestPO = getTaxPaymentRequestPO(param); if (paymentRequestPO != null) { if (SalaryOnOffEnum.ON.getValue().equals(paymentRequestPO.getFeedback())) { getTaxPaymentRequestMapper().updateFeedbackByRequestTypeTaxAgentIdTaxYearMonth(TaxPaymentRequestPO .builder() .requestId(requestId) .feedback(SalaryOnOffEnum.OFF.getValue()) .requestType(param.getType()) .taxAgentId(param.getTaxAgentId()) .taxYearMonth(param.getTaxYearMonth()) .build()); } } else { paymentRequestPO = TaxPaymentRequestPO.builder() .id(IdGenerator.generate()) // todo .creator((long) user.getUID()) .creator(1L) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .createTime(new Date()) .updateTime(new Date()) .deleteType(DeleteTypeEnum.NOT_DELETED.getValue()) .taxDeclareRecordId(param.getTaxDeclareRecordId()) .taxAgentId(param.getTaxAgentId()) .taxYearMonth(param.getTaxYearMonth()) .requestId(requestId) .requestType(param.getType()) .feedback(SalaryOnOffEnum.OFF.getValue()) .build(); getTaxPaymentRequestMapper().insertIgnoreNull(paymentRequestPO); } return requestId; } protected TaxPaymentRequestPO getTaxPaymentRequestPO(TaxPaymentQueryParam param) { List paymentRequests = getTaxPaymentRequestMapper().listSome(TaxPaymentRequestPO .builder() .taxAgentId(param.getTaxAgentId()) .taxYearMonth(param.getTaxYearMonth()) .build()); if (Objects.isNull(param.getCheckFeedback()) || SalaryOnOffEnum.ON.getValue().equals(param.getCheckFeedback())) { TaxPaymentRequestPO notFeedback = paymentRequests.stream().filter(e -> { boolean conditionA = getServiceType().equals(e.getRequestType()) || TaxPaymentServiceTypeEnum.QUERY_AGREEMENT.getValue().equals(e.getRequestType()); boolean conditionB = SalaryOnOffEnum.OFF.getValue().equals(e.getFeedback()); return !conditionA && conditionB; }).findFirst().orElse(null); if (Objects.nonNull(notFeedback)) { TaxPaymentServiceTypeEnum notFeedbackType = TaxPaymentServiceTypeEnum.parseByValue(notFeedback.getRequestType()); throw new SalaryRunTimeException("请先获取上次" + notFeedbackType.getDefaultLabel() + "的缴款反馈结果后,再进行其他缴款"); } } return paymentRequests.stream().filter(e -> getServiceType().equals(e.getRequestType())).findFirst().orElse(null); } protected void updateTaxPaymentRequest(TaxPaymentQueryParam param) { TaxPaymentRequestPO paymentRequest = getTaxPaymentRequestMapper().getOne(TaxPaymentRequestPO .builder() .requestType(getServiceType()) .taxAgentId(param.getTaxAgentId()) .taxYearMonth(param.getTaxYearMonth()) .build()); SalaryAssert.notNull(paymentRequest, "请先点击[三方缴款]或[银行端凭证缴款]按钮发起缴款请求后,再点击[缴款反馈]按钮"); paymentRequest.setFeedback(SalaryOnOffEnum.ON.getValue()); paymentRequest.setUpdateTime(new Date()); getTaxPaymentRequestMapper().updateIgnoreNull(paymentRequest); } protected BaseResponse checkBeforeGetFeedbackResponse(TaxPaymentQueryParam param) { TaxDeclarationApiConfigPO apiConfigPO = getTaxDeclarationApiConfigService(user).getConfig(true); TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(param.getTaxAgentId()); SalaryAssert.notNull(taxAgentPO, SalaryI18nUtil.getI18nLabel(100545, "个税扣缴义务人不存在")); TaxPaymentRequestPO paymentRequestPO = getTaxPaymentRequestPO(param); String button = TaxPaymentServiceTypeEnum.parseByValue(getServiceType()).getDefaultLabel(); if (Objects.isNull(param.getCheckFeedback()) || SalaryOnOffEnum.ON.getValue().equals(param.getCheckFeedback())) { Integer feedback = Optional.ofNullable(paymentRequestPO).map(TaxPaymentRequestPO::getFeedback).orElse(SalaryOnOffEnum.ON.getValue()); if (TaxPaymentServiceTypeEnum.QUERY_AGREEMENT.getValue().equals(getServiceType())) { SalaryAssert.isTrue(SalaryOnOffEnum.OFF.getValue().equals(feedback), SalaryI18nUtil.getI18nLabel(184011, "三方信息查询请求获取失败")); } else { SalaryAssert.isTrue(SalaryOnOffEnum.OFF.getValue().equals(feedback), String.format(SalaryI18nUtil.getI18nLabel(184012, "请先点击[%s]按钮发起缴款请求后,再点击[缴款反馈]按钮"), button)); } } BaseResponse response = getFeedbackResponse(apiConfigPO, paymentRequestPO.getRequestId()); log.info("{} data : {} , paymentRequest : {}", button, response, JsonUtil.toJsonString(paymentRequestPO)); return response; } @Override public TaxAmountFormDTO queryTaxAmount(TaxPaymentQueryParam param) { TaxDeclareRecordPO taxDeclareRecord = getTaxDeclareRecordService(user).getById(param.getTaxDeclareRecordId()); SalaryAssert.notNull(taxDeclareRecord, "个税申报记录不存在"); if (!TaxDeclareStatusEnum.DECLARE_SUCCESS_UNPAID.getValue().equals(taxDeclareRecord.getTaxDeclareStatus())) { throw new SalaryRunTimeException("当前申报状态不是[申报成功,未缴费],暂时无法获取"); } if (taxDeclareRecord.getTaxPayAmount() == null || taxDeclareRecord.getPersonNum() == null) { throw new SalaryRunTimeException("未获取到应缴信息,请先进行个税在线申报"); } TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(taxDeclareRecord.getTaxAgentId()); SalaryAssert.notNull(taxAgentPO, "个税扣缴义务人不存在"); return TaxAmountFormDTO.builder() .taxAgent(taxAgentPO.getName()) .amount(SalaryEntityUtil.thousandthConvert(taxDeclareRecord.getTaxPayAmount())) .personNum(taxDeclareRecord.getPersonNum().toString()) .build(); } protected TaxDeclareRecordPO updateTaxDeclareRecord(TaxPaymentQueryParam param, BigDecimal totalPaid) { TaxDeclareRecordPO taxDeclareRecord = getTaxDeclareRecordService(user).getById(param.getTaxDeclareRecordId()); if (TaxDeclareStatusEnum.DECLARE_SUCCESS_PAID.getValue().equals(taxDeclareRecord.getTaxDeclareStatus())) { throw new SalaryRunTimeException("当前申报表状态为已缴款,无法更新状态"); } BigDecimal taxPayAmount = SalaryEntityUtil.empty2Zero(taxDeclareRecord.getTaxPayAmount()); BigDecimal taxPurePaidAmount = SalaryEntityUtil.empty2Zero(taxDeclareRecord.getTaxPurePaidAmount()); if (SalaryEntityUtil.empty2Zero(taxDeclareRecord.getTaxPaidAmount()).equals(totalPaid) && taxPayAmount.compareTo(BigDecimal.ZERO) > 0) { throw new SalaryRunTimeException("请进行缴款后再刷新缴款状态"); } taxDeclareRecord.setTaxDeclareStatus(TaxDeclareStatusEnum.DECLARE_SUCCESS_PAID.getValue()); taxDeclareRecord.setTaxPaidAmount(totalPaid.toString()); taxDeclareRecord.setTaxPurePaidAmount(taxPurePaidAmount.add(taxPayAmount).toString()); taxDeclareRecord.setTaxPayAmount(BigDecimal.ZERO.toString()); taxDeclareRecord.setUpdateTime(new Date()); getTaxDeclareRecordService(user).updateById(taxDeclareRecord); // 填充回去后续返回数据用 taxDeclareRecord.setTaxPayAmount(taxPayAmount.toString()); return taxDeclareRecord; } @Override public void cancelWithholdingVoucher(TaxDeclarationApiConfigPO apiConfig, TaxDeclareRecordPO taxDeclareRecord, Map requestParam) { throw new SalaryRunTimeException("暂无实现"); } @Override public TaxWithheldVoucherResultDTO getWithheldVoucher(TaxPaymentQueryParam param) { throw new SalaryRunTimeException("暂无实现"); } @Override public void syncWithholdingFeedback(TaxPaymentQueryParam param) { throw new SalaryRunTimeException("暂无实现"); } @Override public void cancelWithholdingVoucher(TaxPaymentQueryParam param) { throw new SalaryRunTimeException("暂无实现"); } @Data @AllArgsConstructor public static class TempWrapper { private TaxDeclarationApiConfigPO apiConfigPO; private TaxAgentTaxReturnPO taxReturnPO; private TaxAgentPO taxAgentPO; private TaxDeclareRecordPO taxDeclareRecord; } }