✨ A303-5开票结果回写支持Base64解码响应并补充关键日志
This commit is contained in:
+37
-20
@@ -44,6 +44,8 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplyQueryDTO;
|
|||||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplySaveDTO;
|
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplySaveDTO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplySaveEntryDTO;
|
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplySaveEntryDTO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
||||||
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyOpenApiBillVO;
|
||||||
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyOpenApiInvoiceVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO;
|
||||||
@@ -738,6 +740,7 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
if (Func.isEmpty(applications)) {
|
if (Func.isEmpty(applications)) {
|
||||||
return "金蝶开票结果回写:无待回写开票申请";
|
return "金蝶开票结果回写:无待回写开票申请";
|
||||||
}
|
}
|
||||||
|
log.info("金蝶开票结果回写开始:待回写开票申请{}笔", applications.size());
|
||||||
// 按 serialNo(金蝶开票申请单编号)分批(≤50/批)调 A303-5,销方税号与 A303-1 同源(开票单位→客商档案),按税号分组查询
|
// 按 serialNo(金蝶开票申请单编号)分批(≤50/批)调 A303-5,销方税号与 A303-1 同源(开票单位→客商档案),按税号分组查询
|
||||||
Map<String, InvoiceApplication> applicationBySerialNo = new LinkedHashMap<>();
|
Map<String, InvoiceApplication> applicationBySerialNo = new LinkedHashMap<>();
|
||||||
applications.forEach(application -> {
|
applications.forEach(application -> {
|
||||||
@@ -766,6 +769,7 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
}
|
}
|
||||||
serialNosBySellerTaxNo.computeIfAbsent(sellerTaxNo, key -> new ArrayList<>()).add(entry.getKey());
|
serialNosBySellerTaxNo.computeIfAbsent(sellerTaxNo, key -> new ArrayList<>()).add(entry.getKey());
|
||||||
}
|
}
|
||||||
|
log.info("金蝶开票结果回写:按销方税号分组完成,共{}组,销方税号无法解析跳过{}笔", serialNosBySellerTaxNo.size(), unresolved);
|
||||||
int invoiceWritten = 0;
|
int invoiceWritten = 0;
|
||||||
int failed = 0;
|
int failed = 0;
|
||||||
int invoicedCount = 0;
|
int invoicedCount = 0;
|
||||||
@@ -773,34 +777,28 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
List<String> groupSerialNos = group.getValue();
|
List<String> groupSerialNos = group.getValue();
|
||||||
for (int from = 0; from < groupSerialNos.size(); from += INVOICE_RESULT_QUERY_BATCH) {
|
for (int from = 0; from < groupSerialNos.size(); from += INVOICE_RESULT_QUERY_BATCH) {
|
||||||
List<String> batch = groupSerialNos.subList(from, Math.min(from + INVOICE_RESULT_QUERY_BATCH, groupSerialNos.size()));
|
List<String> batch = groupSerialNos.subList(from, Math.min(from + INVOICE_RESULT_QUERY_BATCH, groupSerialNos.size()));
|
||||||
|
String batchSerialNos = String.join(",", batch);
|
||||||
|
log.info("金蝶开票结果回写批次查询:销方税号=[{}],单据编号=[{}],数量={}", group.getKey(), batchSerialNos, batch.size());
|
||||||
try {
|
try {
|
||||||
BfiInvoiceApplyOpenApiQueryDTO param = new BfiInvoiceApplyOpenApiQueryDTO();
|
BfiInvoiceApplyOpenApiQueryDTO param = new BfiInvoiceApplyOpenApiQueryDTO();
|
||||||
param.setSerialNo(String.join(",", batch));
|
param.setSerialNo(batchSerialNos);
|
||||||
param.setSellerTaxpayerId(group.getKey());
|
param.setSellerTaxpayerId(group.getKey());
|
||||||
BfiOpenApiResultVO<List<Object>> result = bfiService.queryInvoiceApplyInvoice(param);
|
BfiOpenApiResultVO<List<BfiInvoiceApplyOpenApiBillVO>> result = bfiService.queryInvoiceApplyInvoice(param);
|
||||||
if (result == null || !result.isSuccess() || result.getData() == null) {
|
if (result == null || !result.isSuccess() || result.getData() == null) {
|
||||||
failed++;
|
failed++;
|
||||||
log.warn("金蝶开票结果回写批次查询未成功:serialNo=[{}]", String.join(",", batch));
|
log.warn("金蝶开票结果回写批次查询未成功:serialNo=[{}]", batchSerialNos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (Object billItem : result.getData()) {
|
log.info("金蝶开票结果回写批次查询成功:serialNo=[{}],返回单据数={}", batchSerialNos, result.getData().size());
|
||||||
if (!(billItem instanceof Map)) {
|
for (BfiInvoiceApplyOpenApiBillVO bill : result.getData()) {
|
||||||
continue;
|
String billNo = bill.getBillNo();
|
||||||
}
|
|
||||||
Map<?, ?> billMap = (Map<?, ?>) billItem;
|
|
||||||
String billNo = firstText(billMap, "billNo", "billno");
|
|
||||||
InvoiceApplication application = applicationBySerialNo.get(billNo);
|
InvoiceApplication application = applicationBySerialNo.get(billNo);
|
||||||
if (application == null || !(billMap.get("invoiceList") instanceof List)) {
|
if (application == null || bill.getInvoiceList() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int inserted = 0;
|
int inserted = 0;
|
||||||
for (Object invoiceItem : (List<?>) billMap.get("invoiceList")) {
|
for (BfiInvoiceApplyOpenApiInvoiceVO invoice : bill.getInvoiceList()) {
|
||||||
if (!(invoiceItem instanceof Map)) {
|
String invoiceNo = invoice.getInvoiceNumber();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Map<?, ?> invoice = (Map<?, ?>) invoiceItem;
|
|
||||||
// 宽松提取关键字段(票易通原文,字段名联调校准后收敛),原文整体 JSON 留档
|
|
||||||
String invoiceNo = firstText(invoice, "invoiceNo", "invoice_no", "invoiceNumber");
|
|
||||||
if (Func.isBlank(invoiceNo)) {
|
if (Func.isBlank(invoiceNo)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -809,17 +807,20 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
.eq(InvoiceApplicationInvoice::getInvoiceApplicationId, application.getId())
|
.eq(InvoiceApplicationInvoice::getInvoiceApplicationId, application.getId())
|
||||||
.eq(InvoiceApplicationInvoice::getInvoiceNo, invoiceNo));
|
.eq(InvoiceApplicationInvoice::getInvoiceNo, invoiceNo));
|
||||||
if (exists != null && exists > 0) {
|
if (exists != null && exists > 0) {
|
||||||
|
log.debug("金蝶开票结果回写:发票号码[{}]已存在,跳过", invoiceNo);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
InvoiceApplicationInvoice record = new InvoiceApplicationInvoice();
|
InvoiceApplicationInvoice record = new InvoiceApplicationInvoice();
|
||||||
record.setInvoiceApplicationId(application.getId());
|
record.setInvoiceApplicationId(application.getId());
|
||||||
record.setSerialNo(billNo);
|
record.setSerialNo(billNo);
|
||||||
record.setInvoiceNo(invoiceNo);
|
record.setInvoiceNo(invoiceNo);
|
||||||
record.setInvoiceDate(parseInvoiceDate(firstText(invoice, "invoiceDate", "invoice_date", "issueDate", "billingDate")));
|
record.setInvoiceDate(parseInvoiceDateTimestamp(invoice.getInvoiceDate()));
|
||||||
record.setInvoiceAmount(parseDecimal(firstText(invoice, "amountWithTax", "totalAmount", "invoiceAmount", "priceTaxTotal")));
|
record.setInvoiceAmount(invoice.getIncludeTaxAmount());
|
||||||
record.setRawJson(JsonUtil.toJson(invoice));
|
record.setRawJson(JsonUtil.toJson(invoice));
|
||||||
invoiceApplicationInvoiceMapper.insert(record);
|
invoiceApplicationInvoiceMapper.insert(record);
|
||||||
inserted++;
|
inserted++;
|
||||||
|
log.info("金蝶开票结果回写:写入发票,申请单号=[{}],单据编号=[{}],发票号码=[{}],含税金额=[{}]",
|
||||||
|
application.getApplicationNo(), billNo, invoiceNo, invoice.getIncludeTaxAmount());
|
||||||
}
|
}
|
||||||
if (inserted > 0) {
|
if (inserted > 0) {
|
||||||
invoiceWritten += inserted;
|
invoiceWritten += inserted;
|
||||||
@@ -827,14 +828,17 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
application.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_INVOICED);
|
application.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_INVOICED);
|
||||||
updateById(application);
|
updateById(application);
|
||||||
invoicedCount++;
|
invoicedCount++;
|
||||||
|
log.info("金蝶开票结果回写:开票申请[{}]状态推进为invoiced,本次写入发票{}张", application.getApplicationNo(), inserted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
failed++;
|
failed++;
|
||||||
log.error("金蝶开票结果回写批次异常:serialNo=[{}]", String.join(",", batch), exception);
|
log.error("金蝶开票结果回写批次异常:serialNo=[{}]", batchSerialNos, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.info("金蝶开票结果回写完成:待查开票申请{}笔(销方税号无法解析跳过{}笔),回写发票{}张(开票完成{}笔,失败批次{}个)",
|
||||||
|
applications.size(), unresolved, invoiceWritten, invoicedCount, failed);
|
||||||
return "金蝶开票结果回写完成:待查开票申请" + applications.size() + "笔(销方税号无法解析跳过" + unresolved
|
return "金蝶开票结果回写完成:待查开票申请" + applications.size() + "笔(销方税号无法解析跳过" + unresolved
|
||||||
+ "笔),回写发票" + invoiceWritten + "张(开票完成" + invoicedCount + "笔,失败批次" + failed + "个)";
|
+ "笔),回写发票" + invoiceWritten + "张(开票完成" + invoicedCount + "笔,失败批次" + failed + "个)";
|
||||||
}
|
}
|
||||||
@@ -877,6 +881,19 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 解析时间戳格式的开票日期(毫秒时间戳),无法解析返回 null */
|
||||||
|
private LocalDateTime parseInvoiceDateTimestamp(Long timestamp) {
|
||||||
|
if (timestamp == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(timestamp), java.time.ZoneId.systemDefault());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
log.warn("金蝶开票结果开票日期时间戳解析失败:[{}]", timestamp);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 宽松解析金额文本,无法解析返回 null */
|
/** 宽松解析金额文本,无法解析返回 null */
|
||||||
private BigDecimal parseDecimal(String text) {
|
private BigDecimal parseDecimal(String text) {
|
||||||
if (Func.isBlank(text)) {
|
if (Func.isBlank(text)) {
|
||||||
|
|||||||
+2
-2
@@ -361,10 +361,10 @@ public interface IBfiClient {
|
|||||||
*
|
*
|
||||||
* @param accessToken 访问令牌,通过 getToken 获取
|
* @param accessToken 访问令牌,通过 getToken 获取
|
||||||
* @param param 请求参数,data 为原文 JSON 的 Base64 编码
|
* @param param 请求参数,data 为原文 JSON 的 Base64 编码
|
||||||
* @return 发票查询结果
|
* @return 发票查询结果,data 为 Base64 编码字符串
|
||||||
*/
|
*/
|
||||||
@PostMapping(INVOICE_APPLY_OPEN_API_URL)
|
@PostMapping(INVOICE_APPLY_OPEN_API_URL)
|
||||||
BfiOpenApiResultVO<List<Object>> invoiceApplyOpenApi(@RequestHeader(BfiConstant.HEADER_ACCESS_TOKEN) String accessToken, @RequestBody BfiInvoiceApplyOpenApiBodyDTO param);
|
BfiOpenApiResultVO<String> invoiceApplyOpenApi(@RequestHeader(BfiConstant.HEADER_ACCESS_TOKEN) String accessToken, @RequestBody BfiInvoiceApplyOpenApiBodyDTO param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A303-2 收票单新增(批量保存)
|
* A303-2 收票单新增(批量保存)
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* BladeX Commercial License Agreement
|
||||||
|
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||||
|
* <p>
|
||||||
|
* Use of this software is governed by the Commercial License Agreement
|
||||||
|
* obtained after purchasing a license from BladeX.
|
||||||
|
* <p>
|
||||||
|
* 1. This software is for development use only under a valid license
|
||||||
|
* from BladeX.
|
||||||
|
* <p>
|
||||||
|
* 2. Redistribution of this software's source code to any third party
|
||||||
|
* without a commercial license is strictly prohibited.
|
||||||
|
* <p>
|
||||||
|
* 3. Licensees may copyright their own code but cannot use segments
|
||||||
|
* from this software for such purposes. Copyright of this software
|
||||||
|
* remains with BladeX.
|
||||||
|
* <p>
|
||||||
|
* Using this software signifies agreement to this License, and the software
|
||||||
|
* must not be used for illegal purposes.
|
||||||
|
* <p>
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. THE AUTHOR IS
|
||||||
|
* NOT LIABLE FOR ANY CLAIMS ARISING FROM SECONDARY OR ILLEGAL DEVELOPMENT.
|
||||||
|
* <p>
|
||||||
|
* Author: Chill Zhuang (bladejava@qq.com)
|
||||||
|
*/
|
||||||
|
package org.springblade.thirdparty.bfi.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业财融合(BFI)A303-5 开票申请发票查询返回单据信息
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BfiInvoiceApplyOpenApiBillVO implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 单据编号
|
||||||
|
*/
|
||||||
|
private String billNo;
|
||||||
|
/**
|
||||||
|
* 发票列表
|
||||||
|
*/
|
||||||
|
private List<BfiInvoiceApplyOpenApiInvoiceVO> invoiceList;
|
||||||
|
}
|
||||||
+341
@@ -0,0 +1,341 @@
|
|||||||
|
/**
|
||||||
|
* BladeX Commercial License Agreement
|
||||||
|
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||||
|
* <p>
|
||||||
|
* Use of this software is governed by the Commercial License Agreement
|
||||||
|
* obtained after purchasing a license from BladeX.
|
||||||
|
* <p>
|
||||||
|
* 1. This software is for development use only under a valid license
|
||||||
|
* from BladeX.
|
||||||
|
* <p>
|
||||||
|
* 2. Redistribution of this software's source code to any third party
|
||||||
|
* without a commercial license is strictly prohibited.
|
||||||
|
* <p>
|
||||||
|
* 3. Licensees may copyright their own code but cannot use segments
|
||||||
|
* from this software for such purposes. Copyright of this software
|
||||||
|
* remains with BladeX.
|
||||||
|
* <p>
|
||||||
|
* Using this software signifies agreement to this License, and the software
|
||||||
|
* must not be used for illegal purposes.
|
||||||
|
* <p>
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. THE AUTHOR IS
|
||||||
|
* NOT LIABLE FOR ANY CLAIMS ARISING FROM SECONDARY OR ILLEGAL DEVELOPMENT.
|
||||||
|
* <p>
|
||||||
|
* Author: Chill Zhuang (bladejava@qq.com)
|
||||||
|
*/
|
||||||
|
package org.springblade.thirdparty.bfi.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业财融合(BFI)A303-5 开票申请发票查询返回发票明细
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BfiInvoiceApplyOpenApiInvoiceVO implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 发票ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 发票代码
|
||||||
|
*/
|
||||||
|
private String invoiceCode;
|
||||||
|
/**
|
||||||
|
* 发票号码
|
||||||
|
*/
|
||||||
|
private String invoiceNumber;
|
||||||
|
/**
|
||||||
|
* 开票日期(时间戳)
|
||||||
|
*/
|
||||||
|
private Long invoiceDate;
|
||||||
|
/**
|
||||||
|
* 发票类型
|
||||||
|
*/
|
||||||
|
private String invoiceType;
|
||||||
|
/**
|
||||||
|
* 发票状态
|
||||||
|
*/
|
||||||
|
private Integer invoiceStatus;
|
||||||
|
/**
|
||||||
|
* 发票属性
|
||||||
|
*/
|
||||||
|
private Integer invoiceProperty;
|
||||||
|
/**
|
||||||
|
* 发票来源
|
||||||
|
*/
|
||||||
|
private String invoiceSource;
|
||||||
|
/**
|
||||||
|
* 单据编号
|
||||||
|
*/
|
||||||
|
private String billNo;
|
||||||
|
/**
|
||||||
|
* 流水号
|
||||||
|
*/
|
||||||
|
private String serialNo;
|
||||||
|
/**
|
||||||
|
* 购方名称
|
||||||
|
*/
|
||||||
|
private String buyerName;
|
||||||
|
/**
|
||||||
|
* 购方纳税人识别号
|
||||||
|
*/
|
||||||
|
private String buyerTaxpayerId;
|
||||||
|
/**
|
||||||
|
* 购方地址及电话
|
||||||
|
*/
|
||||||
|
private String buyerAddressAndTel;
|
||||||
|
/**
|
||||||
|
* 购方银行及账号
|
||||||
|
*/
|
||||||
|
private String buyerBankAndAccount;
|
||||||
|
/**
|
||||||
|
* 购方性质
|
||||||
|
*/
|
||||||
|
private Integer buyerProperty;
|
||||||
|
/**
|
||||||
|
* 购方收件人邮箱
|
||||||
|
*/
|
||||||
|
private String buyerRecipientMail;
|
||||||
|
/**
|
||||||
|
* 购方收件人电话
|
||||||
|
*/
|
||||||
|
private String buyerRecipientPhone;
|
||||||
|
/**
|
||||||
|
* 销方名称
|
||||||
|
*/
|
||||||
|
private String sellerName;
|
||||||
|
/**
|
||||||
|
* 销方纳税人识别号
|
||||||
|
*/
|
||||||
|
private String sellerTaxpayerId;
|
||||||
|
/**
|
||||||
|
* 销方地址及电话
|
||||||
|
*/
|
||||||
|
private String sellerAddressAndTel;
|
||||||
|
/**
|
||||||
|
* 销方银行及账号
|
||||||
|
*/
|
||||||
|
private String sellerBankAndAccount;
|
||||||
|
/**
|
||||||
|
* 不含税金额
|
||||||
|
*/
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
/**
|
||||||
|
* 税额
|
||||||
|
*/
|
||||||
|
private BigDecimal totalTaxAmount;
|
||||||
|
/**
|
||||||
|
* 价税合计
|
||||||
|
*/
|
||||||
|
private BigDecimal includeTaxAmount;
|
||||||
|
/**
|
||||||
|
* 可红冲金额
|
||||||
|
*/
|
||||||
|
private BigDecimal canRedAmount;
|
||||||
|
/**
|
||||||
|
* 可红冲税额
|
||||||
|
*/
|
||||||
|
private BigDecimal canRedTaxAmount;
|
||||||
|
/**
|
||||||
|
* 合并差额税额
|
||||||
|
*/
|
||||||
|
private BigDecimal mergeDifferTaxAmount;
|
||||||
|
/**
|
||||||
|
* 开票人
|
||||||
|
*/
|
||||||
|
private String drawer;
|
||||||
|
/**
|
||||||
|
* 收款人
|
||||||
|
*/
|
||||||
|
private String payee;
|
||||||
|
/**
|
||||||
|
* 复核人
|
||||||
|
*/
|
||||||
|
private String reviewer;
|
||||||
|
/**
|
||||||
|
* 作废人
|
||||||
|
*/
|
||||||
|
private String canceler;
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
/**
|
||||||
|
* 校验码
|
||||||
|
*/
|
||||||
|
private String checkCode;
|
||||||
|
/**
|
||||||
|
* 合同编号
|
||||||
|
*/
|
||||||
|
private String contractNo;
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
private String deviceNo;
|
||||||
|
/**
|
||||||
|
* 终端编号
|
||||||
|
*/
|
||||||
|
private String terminalNo;
|
||||||
|
/**
|
||||||
|
* 机构名称
|
||||||
|
*/
|
||||||
|
private String orgName;
|
||||||
|
/**
|
||||||
|
* 原发票代码
|
||||||
|
*/
|
||||||
|
private String originalInvoiceCode;
|
||||||
|
/**
|
||||||
|
* 原发票号码
|
||||||
|
*/
|
||||||
|
private String originalInvoiceNumber;
|
||||||
|
/**
|
||||||
|
* 红冲单据号
|
||||||
|
*/
|
||||||
|
private String redInfoBillNo;
|
||||||
|
/**
|
||||||
|
* 红冲原因
|
||||||
|
*/
|
||||||
|
private String redReason;
|
||||||
|
/**
|
||||||
|
* 作废原因
|
||||||
|
*/
|
||||||
|
private String abolishReason;
|
||||||
|
/**
|
||||||
|
* 发票文件URL
|
||||||
|
*/
|
||||||
|
private String invoiceFileUrl;
|
||||||
|
/**
|
||||||
|
* 发票图片URL
|
||||||
|
*/
|
||||||
|
private String invoiceImageUrl;
|
||||||
|
/**
|
||||||
|
* 开具状态
|
||||||
|
*/
|
||||||
|
private String issueStatus;
|
||||||
|
/**
|
||||||
|
* 下载标记
|
||||||
|
*/
|
||||||
|
private Integer downloadFlag;
|
||||||
|
/**
|
||||||
|
* 打印标记
|
||||||
|
*/
|
||||||
|
private Integer printFlag;
|
||||||
|
/**
|
||||||
|
* 库存标记
|
||||||
|
*/
|
||||||
|
private Integer inventoryFlag;
|
||||||
|
/**
|
||||||
|
* 特殊红冲标记
|
||||||
|
*/
|
||||||
|
private Integer specialRedFlag;
|
||||||
|
/**
|
||||||
|
* 拆分合并标记
|
||||||
|
*/
|
||||||
|
private String splitOrMergeFlag;
|
||||||
|
/**
|
||||||
|
* 商品明细列表
|
||||||
|
*/
|
||||||
|
private List<BfiInvoiceApplyOpenApiGoodsVO> goods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业财融合(BFI)A303-5 开票申请发票查询返回商品明细
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class BfiInvoiceApplyOpenApiGoodsVO implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 明细ID
|
||||||
|
*/
|
||||||
|
private String detailId;
|
||||||
|
/**
|
||||||
|
* 明细行号
|
||||||
|
*/
|
||||||
|
private Integer detailRowNo;
|
||||||
|
/**
|
||||||
|
* 序号
|
||||||
|
*/
|
||||||
|
private Integer seq;
|
||||||
|
/**
|
||||||
|
* 商品名称
|
||||||
|
*/
|
||||||
|
private String goodsName;
|
||||||
|
/**
|
||||||
|
* 规格型号
|
||||||
|
*/
|
||||||
|
private String specification;
|
||||||
|
/**
|
||||||
|
* 单位
|
||||||
|
*/
|
||||||
|
private String units;
|
||||||
|
/**
|
||||||
|
* 数量
|
||||||
|
*/
|
||||||
|
private String quantity;
|
||||||
|
/**
|
||||||
|
* 单价
|
||||||
|
*/
|
||||||
|
private String price;
|
||||||
|
/**
|
||||||
|
* 金额
|
||||||
|
*/
|
||||||
|
private BigDecimal amount;
|
||||||
|
/**
|
||||||
|
* 税率
|
||||||
|
*/
|
||||||
|
private String taxRate;
|
||||||
|
/**
|
||||||
|
* 税额
|
||||||
|
*/
|
||||||
|
private BigDecimal taxAmount;
|
||||||
|
/**
|
||||||
|
* 含税金额
|
||||||
|
*/
|
||||||
|
private BigDecimal includeTaxAmount;
|
||||||
|
/**
|
||||||
|
* 含税单价
|
||||||
|
*/
|
||||||
|
private String includeTaxPrice;
|
||||||
|
/**
|
||||||
|
* 行性质
|
||||||
|
*/
|
||||||
|
private Integer lineProperty;
|
||||||
|
/**
|
||||||
|
* 税收分类编码
|
||||||
|
*/
|
||||||
|
private String revenueCode;
|
||||||
|
/**
|
||||||
|
* 税收分类名称
|
||||||
|
*/
|
||||||
|
private String revenueName;
|
||||||
|
/**
|
||||||
|
* 单据来源ID
|
||||||
|
*/
|
||||||
|
private String billSourceId;
|
||||||
|
/**
|
||||||
|
* 优惠标记
|
||||||
|
*/
|
||||||
|
private Integer privilegeFlag;
|
||||||
|
/**
|
||||||
|
* 优惠内容
|
||||||
|
*/
|
||||||
|
private String privilegeContent;
|
||||||
|
/**
|
||||||
|
* 征税标记
|
||||||
|
*/
|
||||||
|
private String taxFlag;
|
||||||
|
/**
|
||||||
|
* 零税率标记
|
||||||
|
*/
|
||||||
|
private String zeroTaxRateFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -53,6 +53,7 @@ import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
|||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiExchangeRateVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiExchangeRateVO;
|
||||||
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyOpenApiBillVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO;
|
||||||
@@ -231,9 +232,9 @@ public interface IBfiService {
|
|||||||
* A303-5 开票申请发票查询
|
* A303-5 开票申请发票查询
|
||||||
*
|
*
|
||||||
* @param param 查询原文参数,单据编号多个用英文逗号隔开,上限50个
|
* @param param 查询原文参数,单据编号多个用英文逗号隔开,上限50个
|
||||||
* @return 发票查询结果,data 内容参考票易通文档
|
* @return 发票查询结果,data 为单据及发票明细列表
|
||||||
*/
|
*/
|
||||||
BfiOpenApiResultVO<List<Object>> queryInvoiceApplyInvoice(BfiInvoiceApplyOpenApiQueryDTO param);
|
BfiOpenApiResultVO<List<BfiInvoiceApplyOpenApiBillVO>> queryInvoiceApplyInvoice(BfiInvoiceApplyOpenApiQueryDTO param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A303-2 收票单新增(批量保存)
|
* A303-2 收票单新增(批量保存)
|
||||||
|
|||||||
+15
-2
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.thirdparty.bfi.service.impl;
|
package org.springblade.thirdparty.bfi.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import feign.Response;
|
import feign.Response;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -76,6 +77,7 @@ import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
|||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiExchangeRateVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiExchangeRateVO;
|
||||||
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyOpenApiBillVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO;
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO;
|
import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO;
|
||||||
@@ -398,7 +400,7 @@ public class BfiServiceImpl implements IBfiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BfiOpenApiResultVO<List<Object>> queryInvoiceApplyInvoice(BfiInvoiceApplyOpenApiQueryDTO param) {
|
public BfiOpenApiResultVO<List<BfiInvoiceApplyOpenApiBillVO>> queryInvoiceApplyInvoice(BfiInvoiceApplyOpenApiQueryDTO param) {
|
||||||
if (param == null || StringUtil.isBlank(param.getSerialNo()) || StringUtil.isBlank(param.getSellerTaxpayerId())) {
|
if (param == null || StringUtil.isBlank(param.getSerialNo()) || StringUtil.isBlank(param.getSellerTaxpayerId())) {
|
||||||
throw new BfiException("查询BFI开票申请发票失败,单据编号与销方税号不能为空");
|
throw new BfiException("查询BFI开票申请发票失败,单据编号与销方税号不能为空");
|
||||||
}
|
}
|
||||||
@@ -409,7 +411,18 @@ public class BfiServiceImpl implements IBfiService {
|
|||||||
body.setInterfaceCode(BfiConstant.INVOICE_APPLY_OPEN_API_CODE);
|
body.setInterfaceCode(BfiConstant.INVOICE_APPLY_OPEN_API_CODE);
|
||||||
body.setData(data);
|
body.setData(data);
|
||||||
String accessToken = getAccessToken();
|
String accessToken = getAccessToken();
|
||||||
BfiOpenApiResultVO<List<Object>> result = commonOpenApiCall("开票申请发票查询", () -> client.invoiceApplyOpenApi(accessToken, body));
|
BfiOpenApiResultVO<String> rawResult = commonOpenApiCall("开票申请发票查询", () -> client.invoiceApplyOpenApi(accessToken, body));
|
||||||
|
// 响应 data 为 Base64 编码字符串,需解码后解析为 JSON
|
||||||
|
BfiOpenApiResultVO<List<BfiInvoiceApplyOpenApiBillVO>> result = new BfiOpenApiResultVO<>();
|
||||||
|
result.setErrorCode(rawResult.getErrorCode());
|
||||||
|
result.setSuccess(rawResult.getSuccess());
|
||||||
|
if (rawResult.isSuccess() && StringUtil.isNotBlank(rawResult.getData())) {
|
||||||
|
String decodedJson = new String(Base64.getDecoder().decode(rawResult.getData()), StandardCharsets.UTF_8);
|
||||||
|
JSONObject decodedObj = JSONUtil.parseObj(decodedJson);
|
||||||
|
result.setErrorCode(decodedObj.getStr("errorCode"));
|
||||||
|
result.setSuccess(decodedObj.getBool("success"));
|
||||||
|
result.setData(decodedObj.getBeanList("data", BfiInvoiceApplyOpenApiBillVO.class));
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -385,10 +385,13 @@ class BfiServiceImplTest {
|
|||||||
@Test
|
@Test
|
||||||
void queryInvoiceApplyInvoiceShouldEncodeBase64Data() {
|
void queryInvoiceApplyInvoiceShouldEncodeBase64Data() {
|
||||||
mockAccessToken();
|
mockAccessToken();
|
||||||
BfiOpenApiResultVO<List<Object>> openApiResult = new BfiOpenApiResultVO<>();
|
// 模拟接口返回 base64 编码的 data
|
||||||
|
String responseData = "{\"data\":[{\"billNo\":\"KPSQ-1\",\"invoiceList\":[]}],\"errorCode\":\"0\",\"success\":true}";
|
||||||
|
String encodedData = Base64.getEncoder().encodeToString(responseData.getBytes(StandardCharsets.UTF_8));
|
||||||
|
BfiOpenApiResultVO<String> openApiResult = new BfiOpenApiResultVO<>();
|
||||||
openApiResult.setSuccess(true);
|
openApiResult.setSuccess(true);
|
||||||
openApiResult.setErrorCode("S0000");
|
openApiResult.setErrorCode("S0000");
|
||||||
openApiResult.setData(List.of());
|
openApiResult.setData(encodedData);
|
||||||
when(client.invoiceApplyOpenApi(anyString(), any())).thenReturn(openApiResult);
|
when(client.invoiceApplyOpenApi(anyString(), any())).thenReturn(openApiResult);
|
||||||
BfiInvoiceApplyOpenApiQueryDTO param = new BfiInvoiceApplyOpenApiQueryDTO();
|
BfiInvoiceApplyOpenApiQueryDTO param = new BfiInvoiceApplyOpenApiQueryDTO();
|
||||||
param.setSerialNo("KPSQ-1,KPSQ-2");
|
param.setSerialNo("KPSQ-1,KPSQ-2");
|
||||||
|
|||||||
Reference in New Issue
Block a user