批量开票接口

beta
kk 2 years ago
parent 8fee541187
commit 6b8c1444a4
  1. 173
      jianshui-admin/src/main/java/com/jianshui/api/controller/http/invoice/v1/InvoiceController.java
  2. 7
      jianshui-invoice/src/main/java/com/jianshui/invoice/domain/InvoiceBack.java
  3. 2
      jianshui-invoice/src/main/java/com/jianshui/invoice/mapper/BillInfoMapper.java
  4. 2
      jianshui-invoice/src/main/java/com/jianshui/invoice/service/impl/adapter/request/AisinoInvoiceRequestAdapterImpl.java
  5. 35
      jianshui-invoice/src/main/java/com/jianshui/invoice/service/impl/api/AisinoConsoleInvoiceApiZhongQiServiceImpl.java
  6. 88
      jianshui-invoice/src/main/resources/mapper/invoice/BillInfoMapper.xml

@ -1,6 +1,8 @@
package com.jianshui.api.controller.http.invoice.v1;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
@ -11,13 +13,16 @@ import com.jianshui.common.exception.jianshui.JianshuiParamErrorException;
import com.jianshui.common.exception.jianshui.JianshuiServiceException;
import com.jianshui.common.utils.StringUtils;
import com.jianshui.common.utils.http.HttpHelper;
import com.jianshui.common.utils.uuid.IdUtils;
import com.jianshui.invoice.constant.elephant.ElephantConstants;
import com.jianshui.invoice.domain.BillInfo;
import com.jianshui.invoice.domain.FindRedInfo;
import com.jianshui.invoice.domain.InvoiceBack;
import com.jianshui.invoice.domain.ele.EleNewMessage;
import com.jianshui.invoice.domain.ele.EleOuterMessage;
import com.jianshui.invoice.domain.ele.FindRedInfoDTO;
import com.jianshui.invoice.domain.ele.HZSQDMessage;
import com.jianshui.invoice.mapper.InvoiceBackMapper;
import com.jianshui.invoice.task.InvoiceBackTask;
import com.jianshui.invoice.utils.elephant.ElephantUtils;
import com.jianshui.platform.dto.InvoiceAdd.BillInfoPDTO;
@ -44,6 +49,7 @@ import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
/**
@ -75,6 +81,9 @@ public class InvoiceController {
@Autowired
private InvoiceAddPService addService;
@Autowired
private InvoiceBackMapper invoiceBackMapper;
/**
@ -1752,61 +1761,149 @@ public class InvoiceController {
* @throws Exception
*/
@Validated
@ApiOperation("开票请求接口-(蓝字发票开具,红字发票开具)")
@ApiOperation("开票请求接口-(蓝字发票开具,红字发票开具)-异步接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "identity", value = "身份认证", dataType = "java.lang.Void", example = "1130", required = true),
@ApiImplicitParam(name = "order", value = "请求体", dataType = "java.lang.Void", required = true)})
@PostMapping({"/api/invoice/v1/addInvoiceBatch", "/api/invoice/v1/addInvoiceBatch/{identity}", "/invoice/addInvoiceBatch"})
public Object addInvoiceBatch(HttpServletRequest request, String identity) throws Exception {
// TODO: 2023/11/2 批量开票接口
// 摘成异步逻辑,状态码过来所有的错误记录数据库,记录请求过来的数据先
public void addInvoiceBatch(HttpServletRequest request, String identity) throws Exception {
// 1-前置条件判断
InvoiceBack invoiceBack = new InvoiceBack();
invoiceBack.setUpdateTime(new Date());
invoiceBack.setCreateTime(new Date());
invoiceBack.setId(IdUtil.randomUUID());
invoiceBack.setSystemOrderno(IdUtil.randomUUID());
invoiceBack.setStatus("1");
invoiceBack.setIdentity(identity);
invoiceBack.setBackMsg("");
invoiceBack.setBackUrl("");
// 1-1 identity校验
if (StringUtils.isEmpty(identity)) {
return AjaxResult.error(ErrorCode.EMPTY_IDENTITY);
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("身份认证参数为空!");
log.info("[重汽批量开票接口]身份认证参数为空!");
return;
}
Companyservice companyservice = iCompanyserviceService.selectCompanyserviceByIdentity(identity);
// 1-2 企业信息校验
Companyservice companyservice = null;
try {
companyservice = iCompanyserviceService.selectCompanyserviceByIdentity(identity);
} catch (Exception e) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("企业信息不存在!");
log.info("[重汽批量开票接口]获取企业信息异常!identity={},e={}",identity,e);
return;
}
if (companyservice == null) {
return AjaxResult.error(ErrorCode.COMPANY_NOT_FOUND);
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("企业信息不存在!");
log.info("[重汽批量开票接口]企业信息不存在!identity={}",identity);
return;
}
// 获得入口报文适配器
String requestAdapterKey = serviceManageService.getRequestAdapterKey("invoice", companyservice.getCompanyid());
IInvoiceRequestService invoiceRequestService = invoiceRequestFactory.getService(requestAdapterKey);
JSONObject decryptResult = invoiceRequestService.decrypt(request, companyservice, "add");
// 报文处理
BillInfo billInfo = decryptResult.toJavaObject(BillInfo.class);
if (billInfo == null) {
throw new JianshuiParamErrorException(ErrorCode.ERROR_PARAMS, companyservice, "invoice");
// 1-3 获得入口报文适配器
JSONObject decryptResult = null;
try {
String requestAdapterKey = serviceManageService.getRequestAdapterKey("invoice", companyservice.getCompanyid());
IInvoiceRequestService invoiceRequestService = invoiceRequestFactory.getService(requestAdapterKey);
decryptResult = invoiceRequestService.decrypt(request, companyservice, "add");
} catch (Exception e) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("请求解密失败!");
log.info("[重汽批量开票接口]请求解密失败!identity={}",identity);
return;
}
// 2-报文处理
cn.hutool.json.JSONObject billJson = null;
try {
billJson = JSONUtil.parseObj(decryptResult);
} catch (Exception e) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("未匹配到发票报文!");
log.info("[重汽批量开票接口]报文格式化异常!identity={},e={}",identity,e);
return;
}
if(billJson.get("billInfo") == null ){
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("未匹配到发票报文!");
log.info("[重汽批量开票接口]未匹配到发票报文!identity={}",identity);
return;
}
billInfo.setSource("2");
// 获得请求实例,并且进行扣费
String serviceKey = serviceManageService.getCompanyServiceSupplier("invoice", companyservice.getCompanyid());
serviceManageService.companyConsume("invoice", companyservice.getCompanyid());
billInfo.setServiceSupplierKey(serviceKey);
IInvoiceApiService invoiceService = invoiceServiceFactory.getService(serviceKey);
HXResponse result = invoiceService.addInvoice(billInfo, companyservice);
// HXResponse result = preHandleDecryptResult(decryptResult, "add", companyservice);
String responseAdapterKey = serviceManageService.getResponseAdapterKey("invoice", companyservice.getCompanyid());
IInvoiceResponseService invoiceResponseService = invoiceResponseFactory.getService(responseAdapterKey);
return invoiceResponseService.response(result, companyservice, "add");
}
JSONArray billJsonArray = null;
try {
billJsonArray = JSONUtil.parseArray(billJson.get("billInfo"));
} catch (Exception e) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("发票报文为空!");
log.info("[重汽批量开票接口]发票报文获取异常!identity={},e={}",identity,e);
return;
}
if(billJsonArray.size() == 0){
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("发票报文为空!");
log.info("[重汽批量开票接口]发票报文为空!identity={}",identity);
return;
}
// 3-报文递交开票
for (Object billInfoObj : billJsonArray) {
BillInfo billInfo = BeanUtil.copyProperties(billInfoObj,BillInfo.class);
if (billInfo == null) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("报文格式错误!");
log.info("[重汽批量开票接口]报文格式错误!identity={}",identity);
continue;
}
billInfo.setSource("2");
// 4-获得请求实例,并且进行扣费
IInvoiceApiService invoiceService = null;
try {
String serviceKey = serviceManageService.getCompanyServiceSupplier("invoice", companyservice.getCompanyid());
serviceManageService.companyConsume("invoice", companyservice.getCompanyid());
billInfo.setServiceSupplierKey(serviceKey);
invoiceService = invoiceServiceFactory.getService(serviceKey);
} catch (Exception e) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("扣费失败!");
log.info("[重汽批量开票接口]扣费失败!identity={},e={}",identity,e);
continue;
}
// 5-开票
try {
HXResponse resultHx = invoiceService.addInvoice(billInfo, companyservice);
log.info("[重汽批量开票接口]开票identity={},返回结果result={}",identity,resultHx);
if(!resultHx.isSuccess()){
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg(resultHx.getMessage());
invoiceBack.setSystemOrderno(billInfo.getSystemOrderno());
invoiceBack.setStatus("0");
invoiceBackMapper.insertInvoiceBack(invoiceBack);
log.info("[重汽批量开票接口]提交开票异常,开票失败!identity={},msg={}",identity,resultHx.getMessage());
continue;
}
} catch (Exception e) {
invoiceBack.setResultCode("9999");
invoiceBack.setResultMsg("开票失败!");
invoiceBack.setSystemOrderno(billInfo.getSystemOrderno());
invoiceBack.setStatus("0");
invoiceBackMapper.insertInvoiceBack(invoiceBack);
log.info("[重汽批量开票接口]提交开票异常,开票失败!identity={},e={}",identity,e);
continue;
}
}
log.info("[重汽批量开票接口]{},执行完成!",identity);
}

@ -51,15 +51,16 @@ public class InvoiceBack
private String resultCode;
/** 更新时间*/
private String updateTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
public String getUpdateTime() {
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}

@ -100,4 +100,6 @@ public interface BillInfoMapper extends BaseMapper<BillInfo> {
public BillInfo selectByOutTradeOrderno(@Param(("companyId")) Long companyId, @Param("out_trade_orderno") String outTradeOrderno);
public BillInfo selectByOutTradeOrdernoNotDel(@Param(("companyId")) Long companyId, @Param("out_trade_orderno") String outTradeOrderno, @Param("updateBy") String updateBy);
}

@ -103,7 +103,7 @@ public class AisinoInvoiceRequestAdapterImpl implements IInvoiceRequestService {
// 平台解密
try {
// TODO: 2023/9/20
// order = AisinoInvoiceDecryptUtil.decrypt(order, JKey);
order = AisinoInvoiceDecryptUtil.decrypt(order, JKey);
} catch (Exception e) {
e.printStackTrace();
throw new JianshuiParamErrorException(ErrorCode.DECRYPT_ERROR, companyservice, "invoice");

@ -115,22 +115,22 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
@Override
public HXResponse addInvoice(BillInfo billInfo, Companyservice companyservice) throws IllegalAccessException, InstantiationException {
String outNO = billInfo.getOutTradeOrderno() != null ? billInfo.getOutTradeOrderno() : "";
if (StrUtil.isEmpty(outNO)) {
return new HXResponse("订单号为空,请检查报文!");
}
// TODO: 2023/11/6 错误先抛出到这里,后面整理到controller统一管理
// 1.订单唯一校验。新增历史订单部分(删除)。
// 订单号唯一校验 start
/*String outNO = billInfo.getOutTradeOrderno() != null ? billInfo.getOutTradeOrderno() : "";
String outNO = billInfo.getOutTradeOrderno() != null ? billInfo.getOutTradeOrderno() : "";
if (StrUtil.isEmpty(outNO)) {
return new HXResponse("订单号为空,请检查报文!");
}
BillInfo billInfoValidate = billInfoMapper.selectByOutTradeOrderno(companyservice.getCompanyid(), outNO);
// update_by 0未删除 1已删除
BillInfo billInfoValidate = billInfoMapper.selectByOutTradeOrdernoNotDel(companyservice.getCompanyid(), outNO,"0");
if (BeanUtil.isNotEmpty(billInfoValidate)) {
return new HXResponse("订单号不允许重复!!!");
}*/
}
// end
// 预处理:处理billinfo,计算税额等
// 2.预处理:处理billinfo,计算税额等
try {
billInfo = BillInfoUtils.processBillInfo(billInfo, companyservice);
} catch (JianshuiParamErrorException e) {
@ -235,7 +235,11 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
}
//明细处理前条件校验
ValidateUtils.validate(aisinoConsoleInvoiceAddDTO, companyservice, null);
try {
ValidateUtils.validate(aisinoConsoleInvoiceAddDTO, companyservice, null);
} catch (RuntimeException e) {
return new HXResponse("订单必填字段校验失败!{}",e.getMessage() != null ? e.getMessage().substring(0,100):"");
}
//发票明细处理
List<AisinoConsoleInvoiceAddDetailDTO> invoiceItems = new ArrayList<>();
@ -314,7 +318,7 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
//返回报文解析
if (ajaxResult.isError()) {
throw new JianshuiServiceException(ajaxResult.getMsg());
return new HXResponse(ajaxResult.getMsg());
}
cn.hutool.json.JSONObject resultJSON = JSONUtil.parseObj(ajaxResult.get("data"));
@ -327,7 +331,7 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
}
AisinoConsoleInvoiceAddVO aisinoConsoleInvoiceAddVO = BeanUtil.copyProperties(resultJSON, AisinoConsoleInvoiceAddVO.class);
if (StrUtil.isEmpty(aisinoConsoleInvoiceAddVO.getInfoNumber())) {
throw new JianshuiServiceException("开具的发票号码不存在!");
return new HXResponse("开具的发票号码不存在!");
}
//更新发票状态
billInfo.setState(2);
@ -373,7 +377,6 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
// TODO: 2023/9/26 增加主动回调方式,可配置
// TODO: 2023/10/25 回调改成异步的,执行10次,直到获取到结果
ICompanyservicePropService companyserviceProp = SpringUtils.getBean(ICompanyservicePropService.class);
CompanyserviceProp secretIdProp = companyserviceProp.selectPropByKey(companyservice.getCompanyid(), "aisino_callback_url");
if (BeanUtil.isNotEmpty(secretIdProp) && secretIdProp.getValue() != null && !"".equals(secretIdProp.getValue())) {
@ -923,7 +926,7 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
throw new JianshuiServiceException(ajaxResult.getMsg());
}
/** sb控制台和文档不一样*/
/** 控制台和文档不一样*/
String retdata = ajaxResult.get("data") != null ? ajaxResult.get("data").toString() : "";
if (StrUtil.isEmpty(retdata)) {
return new HXResponse("9999", "下载失败");
@ -943,14 +946,14 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
// Map<String, Object> map = new HashMap<>();
data = Base64.decodeStr(data, "GB2312");
if (data.indexOf("<DATA>") != -1 && data.indexOf("</DATA>") != -1) {
if (data.contains("<DATA>") && data.contains("</DATA>")) {
String dataChild = data.substring(data.indexOf("<DATA>") + 6, data.indexOf("</DATA>"));
cn.hutool.json.JSONObject dataChildJson = JSONUtil.parseObj(dataChild);
String RedInvReqBill = dataChildJson.get("RedInvReqBill").toString();
// TODO: 2023/11/4 这里处理
// TODO: 2023/11/4 多条明细的这里和单条的不一样,重汽只用多条的
// cn.hutool.json.JSONArray jsonArray = JSONUtil.parseArray(RedInvReqBill);
cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(RedInvReqBill);
@ -970,7 +973,7 @@ public class AisinoConsoleInvoiceApiZhongQiServiceImpl implements IInvoiceApiSer
return new HXResponse("9999", "系统异常!!!");
}
return new HXResponse("0000", red);
return new HXResponse("0000", "查询成功!",red,true);
}
}

@ -478,6 +478,94 @@
limit 1
</select>
<select id="selectByOutTradeOrdernoNotDel" resultMap="BillInfoBillDetailResult">
select a.id,
a.company_id,
a.system_orderno,
a.out_trade_orderno,
a.fpqqlsh,
a.invoice_type,
a.buyer_name,
a.buyer_taxnum,
a.buyer_address,
a.buyer_telephone,
a.buyer_bank,
a.buyer_account,
a.buyer_email,
a.buyer_phone,
a.seller_name,
a.seller_taxnum,
a.seller_address,
a.seller_telephone,
a.seller_account,
a.message,
a.seller_bank,
a.clerk,
a.payee,
a.checker,
a.red_invoice_info_code,
a.fjh,
a.terminal_number,
a.remark,
a.kptype,
a.origin_system_orderno,
a.bmbbh,
a.origin_fpdm,
a.origin_fphm,
a.tsfs,
a.qdbz,
a.qdxmmc,
a.dkbz,
a.cpybz,
a.state,
a.source,
a.service_supplier_key,
a.bill_type,
a.business_remark,
a.taxfreeamt,
a.invoiced_time,
a.create_by,
a.tax,
a.callback_url,
a.create_time,
a.taxamt,
a.update_by,
a.update_time,
a.deleted_time,
b.id as sub_id,
b.bill_info_id as sub_bill_info_id,
b.index as sub_index,
b.good_name as sub_good_name,
b.num as sub_num,
b.price as sub_price,
b.hsbz as sub_hsbz,
b.taxrate as sub_taxrate,
b.spec as sub_spec,
b.unit as sub_unit,
b.spbm as sub_spbm,
b.bmbbh as sub_bmbbh,
b.zsbm as sub_zsbm,
b.fphxz as sub_fphxz,
b.yhzcbs as sub_yhzcbs,
b.zzstsgl as sub_zzstsgl,
b.lslbs as sub_lslbs,
b.kce as sub_kce,
b.taxfreeamt as sub_taxfreeamt,
b.tax as sub_tax,
b.taxamt as sub_taxamt,
b.tspz as sub_tspz,
b.create_by as sub_create_by,
b.create_time as sub_create_time,
b.update_by as sub_update_by,
b.updated_time as sub_updated_time
from bill_info a
left join bill_detail b on b.bill_info_id = a.id
where a.company_id = #{companyId}
and a.out_trade_orderno = #{out_trade_orderno}
and update_by = #{updateBy}
limit 1
</select>
<insert id="insertBillInfo" parameterType="BillInfo" useGeneratedKeys="true" keyProperty="id">
insert into bill_info

Loading…
Cancel
Save