✨ blade-bfi-api 新增发票云全票池发票查询能力(A801-1 rim契约,queryAllPages全量翻页)
This commit is contained in:
+50
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
package org.springblade.thirdparty.bfi.constant;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 业财融合(BFI)常量类
|
||||
*
|
||||
@@ -37,6 +39,16 @@ public class BfiConstant {
|
||||
*/
|
||||
public static final String SUCCESS_CODE = "0";
|
||||
|
||||
/**
|
||||
* 收票 rim/message 契约调用成功错误码
|
||||
*/
|
||||
public static final String RIM_SUCCESS_CODE = "0000";
|
||||
|
||||
/**
|
||||
* A801-1 查询全票池发票 消息类型,固定值
|
||||
*/
|
||||
public static final String MESSAGE_TYPE_INVOICE_QUERY = "invoiceQuery";
|
||||
|
||||
/**
|
||||
* 网关认证请求头名称
|
||||
*/
|
||||
@@ -376,4 +388,42 @@ public class BfiConstant {
|
||||
* 预付信息单据类型:期初预付单
|
||||
*/
|
||||
public static final String PREPAY_BILL_TYPE_INIT_PAID = "ap_paidbill";
|
||||
|
||||
/**
|
||||
* 发票类型编码 -> 名称,编码明细参考票易通文档《发票数据结构》
|
||||
*/
|
||||
public static final Map<String, String> INVOICE_TYPE_NAMES = Map.ofEntries(
|
||||
Map.entry("1", "增值税电子普通发票"),
|
||||
Map.entry("2", "增值税电子专用发票"),
|
||||
Map.entry("3", "增值税普通发票"),
|
||||
Map.entry("4", "增值税专用发票"),
|
||||
Map.entry("5", "增值税普通发票(卷票)"),
|
||||
Map.entry("7", "通用机打发票"),
|
||||
Map.entry("8", "出租车票"),
|
||||
Map.entry("9", "火车票"),
|
||||
Map.entry("10", "飞机票"),
|
||||
Map.entry("11", "其他票"),
|
||||
Map.entry("12", "机动车销售统一发票"),
|
||||
Map.entry("13", "二手车销售统一发票"),
|
||||
Map.entry("14", "定额发票"),
|
||||
Map.entry("15", "增值税电子普通发票(通行费)"),
|
||||
Map.entry("16", "汽车票"),
|
||||
Map.entry("17", "过路(过桥)费发票"),
|
||||
Map.entry("19", "税收完税证明"),
|
||||
Map.entry("20", "轮船票"),
|
||||
Map.entry("21", "海关缴款书"),
|
||||
Map.entry("23", "通用机打电子发票"),
|
||||
Map.entry("24", "火车票退票凭证"),
|
||||
Map.entry("25", "财政电子票据"),
|
||||
Map.entry("26", "数电发票(普通发票)"),
|
||||
Map.entry("27", "数电发票(增值税专用发票)"),
|
||||
Map.entry("28", "数电发票(航空运输电子客票行程单)"),
|
||||
Map.entry("29", "数电发票(铁路电子客票)"),
|
||||
Map.entry("30", "海外发票"),
|
||||
Map.entry("31", "海外收据"),
|
||||
Map.entry("47", "增值税代扣代缴完税凭证"),
|
||||
Map.entry("72", "数电发票(通行费发票)"),
|
||||
Map.entry("83", "数电发票(机动车销售统一发票)"),
|
||||
Map.entry("84", "数电发票(二手车销售统一发票)")
|
||||
);
|
||||
}
|
||||
|
||||
+11
-12
@@ -30,20 +30,11 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 业财融合(BFI)A801-1 查询全票池发票数据参数
|
||||
* <p>
|
||||
* 请求示例:
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "queryParam": {
|
||||
* "invoiceNo": "25532000000044538098"
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
* queryParam 字段明细参考票易通文档 https://open.piaozone.com/api-145421056
|
||||
* 收票 rim/message 契约请求体,字段明细参考票易通文档 https://open.piaozone.com/api-145421056
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@@ -53,7 +44,15 @@ public class BfiInvoicePoolQueryDTO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 【必填】查询参数,键值对形式,如 invoiceNo(发票号码),字段明细参考 https://open.piaozone.com/api-145421056
|
||||
* 请求类型,固定值 invoiceQuery,由服务端填充
|
||||
*/
|
||||
private Map<String, Object> queryParam;
|
||||
private String messageType;
|
||||
/**
|
||||
* 请求id,唯一标识,由服务端填充
|
||||
*/
|
||||
private String messageId;
|
||||
/**
|
||||
* 【必填】查询条件主体
|
||||
*/
|
||||
private BfiInvoicePoolQueryDataDTO data;
|
||||
}
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 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.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 业财融合(BFI)A801-1 查询全票池发票数据 查询条件主体
|
||||
* <p>
|
||||
* 字段明细参考票易通文档 https://open.piaozone.com/api-145421056
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class BfiInvoicePoolQueryDataDTO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 页码,从1开始
|
||||
*/
|
||||
private Integer pageNo;
|
||||
/**
|
||||
* 每页数量,最大500
|
||||
*/
|
||||
private Integer pageSize;
|
||||
/**
|
||||
* 开票日期起 yyyy-MM-dd
|
||||
*/
|
||||
private String invoiceDateStart;
|
||||
/**
|
||||
* 开票日期止 yyyy-MM-dd
|
||||
*/
|
||||
private String invoiceDateEnd;
|
||||
/**
|
||||
* 发票类型编码
|
||||
*/
|
||||
private String invoiceType;
|
||||
/**
|
||||
* 增值税发票状态
|
||||
*/
|
||||
private String invoiceStatus;
|
||||
/**
|
||||
* 发票代码
|
||||
*/
|
||||
private String invoiceCode;
|
||||
/**
|
||||
* 发票号码
|
||||
*/
|
||||
private String invoiceNo;
|
||||
/**
|
||||
* 增值税用途勾选状态[0未勾选,1已勾选,2勾选认证,3扫描认证,4预勾选]
|
||||
*/
|
||||
private String authenticateFlag;
|
||||
/**
|
||||
* 单据使用状态,多个用英文逗号分隔[1未用,30在用,60已用,65已入账]
|
||||
*/
|
||||
private String expenseStatus;
|
||||
/**
|
||||
* 核算组织编码数组
|
||||
*/
|
||||
private List<String> orgNumber;
|
||||
/**
|
||||
* 采集时间起 yyyy-MM-dd
|
||||
*/
|
||||
private String createTimeStart;
|
||||
/**
|
||||
* 采集时间止 yyyy-MM-dd(票开放平台原始拼写 creatTimeEnd)
|
||||
*/
|
||||
private String creatTimeEnd;
|
||||
/**
|
||||
* 采集用户编码
|
||||
*/
|
||||
private String creatorNo;
|
||||
/**
|
||||
* 购方税号
|
||||
*/
|
||||
private String buyerTaxNo;
|
||||
/**
|
||||
* 销方税号
|
||||
*/
|
||||
private String salerTaxNo;
|
||||
/**
|
||||
* 发票流水号数组
|
||||
*/
|
||||
private List<String> serialNos;
|
||||
/**
|
||||
* 勾选时间起 yyyy-MM-dd
|
||||
*/
|
||||
private String selectTimeStart;
|
||||
/**
|
||||
* 勾选时间止 yyyy-MM-dd
|
||||
*/
|
||||
private String selectTimeEnd;
|
||||
/**
|
||||
* 抵扣税期 YYYY-MM
|
||||
*/
|
||||
private String taxPeriod;
|
||||
/**
|
||||
* 更新时间起 yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
private String updateTime;
|
||||
/**
|
||||
* 更新时间止 yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
private String updateTimeEnd;
|
||||
/**
|
||||
* 是否查询发票附件[1是,0否]
|
||||
*/
|
||||
private String queryAttach;
|
||||
}
|
||||
+10
@@ -104,6 +104,11 @@ public class BfiInvoicePoolVO implements Serializable {
|
||||
*/
|
||||
@JsonProperty("totalTaxAmount")
|
||||
private String totalTaxAmount;
|
||||
/**
|
||||
* 税率(票开放平台顶层税率字段)
|
||||
*/
|
||||
@JsonProperty("taxRate")
|
||||
private String taxRate;
|
||||
/**
|
||||
* 可用税额
|
||||
*/
|
||||
@@ -114,6 +119,11 @@ public class BfiInvoicePoolVO implements Serializable {
|
||||
*/
|
||||
@JsonProperty("buyerTaxNo")
|
||||
private String buyerTaxNo;
|
||||
/**
|
||||
* 购方名称
|
||||
*/
|
||||
@JsonProperty("buyerName")
|
||||
private String buyerName;
|
||||
/**
|
||||
* 销方税号
|
||||
*/
|
||||
|
||||
+3
-3
@@ -278,10 +278,10 @@ public interface IBfiService {
|
||||
BfiBillSaveResultVO pushClaimResult(BfiClaimPushDTO param);
|
||||
|
||||
/**
|
||||
* A801-1 查询全票池发票数据
|
||||
* A801-1 查询全票池发票数据(自动翻页汇总全量)
|
||||
*
|
||||
* @param param 查询参数,queryParam 键值对参考票易通文档
|
||||
* @return 票池发票数据列表
|
||||
* @param param 查询参数,messageType/messageId 由服务端填充;data.pageSize 必填,作为单页大小与翻页终止依据
|
||||
* @return 票池发票数据全量列表
|
||||
*/
|
||||
List<BfiInvoicePoolVO> queryInvoicePool(BfiInvoicePoolQueryDTO param);
|
||||
|
||||
|
||||
+51
-4
@@ -56,6 +56,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignBodyDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignItemDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceDownloadDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDataDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiPayApplyPushBodyDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiPayApplyPushDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiPayApplyQueryDTO;
|
||||
@@ -98,6 +99,7 @@ import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@@ -483,12 +485,29 @@ public class BfiServiceImpl implements IBfiService {
|
||||
|
||||
@Override
|
||||
public List<BfiInvoicePoolVO> queryInvoicePool(BfiInvoicePoolQueryDTO param) {
|
||||
if (param == null || param.getQueryParam() == null || param.getQueryParam().isEmpty()) {
|
||||
if (param == null || param.getData() == null) {
|
||||
throw new BfiException("查询BFI全票池发票失败,查询参数不能为空");
|
||||
}
|
||||
String accessToken = getAccessToken();
|
||||
BfiResultVO<List<BfiInvoicePoolVO>> result = commonCall("全票池发票查询", () -> client.invoicePoolQuery(accessToken, param));
|
||||
return result.getData() != null ? result.getData() : List.of();
|
||||
param.setMessageType(BfiConstant.MESSAGE_TYPE_INVOICE_QUERY);
|
||||
// A801-1 rim 契约仅返回当前页数据且无总数,统一通过通用翻页工具取全量,由调用方自行分页
|
||||
BfiInvoicePoolQueryDataDTO data = param.getData();
|
||||
long start = System.currentTimeMillis();
|
||||
log.info("调用BFI接口 全票池发票查询开始 pageSize:{}", data.getPageSize());
|
||||
List<BfiInvoicePoolVO> invoices = BfiUtil.queryAllPages(pageNo -> {
|
||||
// 翻页工具逐页注入页码;rim 契约要求每次请求携带唯一 messageId
|
||||
data.setPageNo(pageNo);
|
||||
param.setMessageId(UUID.randomUUID().toString());
|
||||
BfiResultVO<List<BfiInvoicePoolVO>> result = commonRimCall("全票池发票查询",
|
||||
() -> client.invoicePoolQuery(getAccessToken(), param));
|
||||
List<BfiInvoicePoolVO> rows = result.getData() != null ? result.getData() : List.of();
|
||||
// rim 契约无 lastPage,包装为 BfiPageVO 借助"数据不满一页即末页"规则终止翻页
|
||||
BfiPageVO<BfiInvoicePoolVO> page = new BfiPageVO<>();
|
||||
page.setRows(rows);
|
||||
page.setPageSize(data.getPageSize());
|
||||
return page;
|
||||
});
|
||||
log.info("调用BFI接口 全票池发票查询结束 耗时:{}ms,全量 {} 条", System.currentTimeMillis() - start, invoices.size());
|
||||
return invoices;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -542,6 +561,34 @@ public class BfiServiceImpl implements IBfiService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收票 rim/message 契约公共调用方法,成功错误码兼容 0 与 0000
|
||||
*
|
||||
* @param type 调用类型描述
|
||||
* @param supplier 实际调用
|
||||
* @param <T> 响应数据类型
|
||||
* @return 响应结果
|
||||
*/
|
||||
private <T> BfiResultVO<T> commonRimCall(String type, Supplier<BfiResultVO<T>> supplier) {
|
||||
try {
|
||||
BfiResultVO<T> result = supplier.get();
|
||||
if (result != null && Boolean.TRUE.equals(result.getStatus())
|
||||
&& (BfiConstant.SUCCESS_CODE.equals(result.getErrorCode()) || BfiConstant.RIM_SUCCESS_CODE.equals(result.getErrorCode()))) {
|
||||
return result;
|
||||
}
|
||||
log.error("调用BFI接口 {}异常响应参数:{}", type, JSONUtil.toJsonStr(result));
|
||||
String message = Optional.ofNullable(result).map(BfiResultVO::getMessage).filter(StringUtil::isNotBlank)
|
||||
.orElseGet(() -> Optional.ofNullable(result).map(BfiResultVO::getErrorCode)
|
||||
.map(errorCode -> "错误码 " + errorCode).orElse("响应为空或解析失败"));
|
||||
throw new BfiException("调用BFI接口" + type + "异常 " + message);
|
||||
} catch (BfiException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("调用BFI接口 {}异常", type, e);
|
||||
throw new BfiException("调用BFI接口" + type + "异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开放平台公共调用方法,校验 success 标识
|
||||
*
|
||||
|
||||
+5
-1
@@ -60,6 +60,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignBodyDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignItemDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignRefDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDataDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceSaveDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceSaveEntryDTO;
|
||||
@@ -528,8 +529,11 @@ class BfiServiceImplTest {
|
||||
BfiInvoicePoolVO invoice = new BfiInvoicePoolVO();
|
||||
when(client.invoicePoolQuery(anyString(), any(BfiInvoicePoolQueryDTO.class)))
|
||||
.thenReturn(success(List.of(invoice)));
|
||||
BfiInvoicePoolQueryDataDTO data = new BfiInvoicePoolQueryDataDTO();
|
||||
data.setInvoiceNo("25532000000044538098");
|
||||
data.setPageSize(500);
|
||||
BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO();
|
||||
param.setQueryParam(Map.of("invoiceNo", "25532000000044538098"));
|
||||
param.setData(data);
|
||||
List<BfiInvoicePoolVO> rows = service.queryInvoicePool(param);
|
||||
assertEquals(1, rows.size());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user