Merge remote-tracking branch 'origin/feature/kingdee-attachment-sync' into feature/payment-apply-bfi-sync
# Conflicts: # blade-common/src/main/java/org/springblade/common/feign/CustomFeignLogger.java # blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java # blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceApplicationServiceImpl.java # blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceReceiptServiceImpl.java # blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PaymentApplicationServiceImpl.java # blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeApBillSyncSupport.java # blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeArBillSyncSupport.java
This commit is contained in:
+10
@@ -27,7 +27,12 @@ package org.springblade.thirdparty.bfi.config;
|
||||
|
||||
import feign.Request;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import org.springblade.thirdparty.bfi.interceptor.BfiRequestInterceptor;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -61,4 +66,9 @@ public class BfiFeignClientConfig {
|
||||
public Request.Options options() {
|
||||
return new Request.Options(10, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
|
||||
return new SpringFormEncoder(new SpringEncoder(messageConverters));
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -48,6 +48,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiVerifyTokenDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiWithdrawTokenDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiApBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiArBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiAttachmentUploadVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||
@@ -65,11 +66,14 @@ import org.springblade.thirdparty.bfi.pojo.vo.BfiTokenVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiVerifyTokenVO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.cloud.openfeign.SpringQueryMap;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -106,6 +110,7 @@ public interface IBfiClient {
|
||||
String CLAIM_BILL_PUSH_URL = "${thirdParty.bfi.claimBillPushUrl:/ierp/kapi/v2/awrp/cas/cas/cas_claimbill/claimbillPush}";
|
||||
String INVOICE_POOL_QUERY_URL = "${thirdParty.bfi.invoicePoolQueryUrl:/ierp/kapi/v2/awrp/rim/rim_invoice/query}";
|
||||
String INVOICE_DOWNLOAD_URL = "${thirdParty.bfi.invoiceDownloadUrl:/ierp/kapi/v2/awrp/bosext/attachment/download}";
|
||||
String ATTACHMENT_UPLOAD_URL = "${thirdParty.bfi.attachmentUploadUrl:/ierp/kapi/v2/frame/attachment/uploadFile}";
|
||||
|
||||
/**
|
||||
* A100-1 获取令牌
|
||||
@@ -451,4 +456,17 @@ public interface IBfiClient {
|
||||
*/
|
||||
@PostMapping(INVOICE_DOWNLOAD_URL)
|
||||
Response invoiceDownload(@RequestHeader(BfiConstant.HEADER_ACCESS_TOKEN) String accessToken, @RequestBody BfiInvoiceDownloadDTO param);
|
||||
|
||||
/**
|
||||
* A902 附件上传到指定单据(multipart/form-data)
|
||||
*
|
||||
* @param accessToken 访问令牌,通过 getToken 获取
|
||||
* @param file 附件文件
|
||||
* @param attachmentUploadFileArgs 上传参数 JSON 字符串:{"entityNumber":"ap_payapply","billPkId":2386455983883835392,"controlKey":"attachmentpanel"}
|
||||
* @return 上传结果,data.path 即金蝶侧文件路径
|
||||
*/
|
||||
@PostMapping(value = ATTACHMENT_UPLOAD_URL, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
BfiResultVO<BfiAttachmentUploadVO> uploadAttachment(@RequestHeader(BfiConstant.HEADER_ACCESS_TOKEN) String accessToken,
|
||||
@RequestPart("file") MultipartFile file,
|
||||
@RequestPart("attachmentUploadFileArgs") String attachmentUploadFileArgs);
|
||||
}
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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 com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 业财融合(BFI)A902 附件上传返回数据
|
||||
* <p>
|
||||
* 响应示例:
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "data": {"path": "211e6ce5c9805c00"},
|
||||
* "errorCode": "0",
|
||||
* "status": true
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class BfiAttachmentUploadVO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 金蝶侧文件路径(附件面板回显/排查用)
|
||||
*/
|
||||
private String path;
|
||||
}
|
||||
+13
@@ -49,6 +49,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceSaveDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiRecBillQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiApBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiArBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiAttachmentUploadVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||
@@ -293,4 +294,16 @@ public interface IBfiService {
|
||||
* @return 文件流响应,调用方负责关闭
|
||||
*/
|
||||
Response downloadInvoice(String path);
|
||||
|
||||
/**
|
||||
* A902 附件上传到指定单据
|
||||
*
|
||||
* @param entityNumber 星瀚单据标识(如 ap_payapply)
|
||||
* @param billPkId 星瀚单据内码(保存/查询响应返回的 id)
|
||||
* @param controlKey 附件面板标识,统一 attachmentpanel
|
||||
* @param fileName 附件名称(含扩展名)
|
||||
* @param fileContent 附件内容
|
||||
* @return 上传结果,path 即金蝶侧文件路径
|
||||
*/
|
||||
BfiAttachmentUploadVO uploadAttachment(String entityNumber, String billPkId, String controlKey, String fileName, byte[] fileContent);
|
||||
}
|
||||
|
||||
+34
@@ -73,6 +73,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiVerifyTokenDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiWithdrawTokenDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiApBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiArBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiAttachmentUploadVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||
@@ -91,6 +92,8 @@ import org.springblade.thirdparty.bfi.pojo.vo.BfiTokenVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiVerifyTokenVO;
|
||||
import org.springblade.thirdparty.bfi.service.IBfiService;
|
||||
import org.springblade.thirdparty.bfi.util.BfiUtil;
|
||||
import org.springblade.thirdparty.bfi.util.InMemoryMultipartFile;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -533,12 +536,15 @@ public class BfiServiceImpl implements IBfiService {
|
||||
BfiInvoiceDownloadDTO param = new BfiInvoiceDownloadDTO();
|
||||
param.setPath(path);
|
||||
String accessToken = getAccessToken();
|
||||
long start = System.currentTimeMillis();
|
||||
log.info("调用BFI接口 进项发票下载开始 path:{}", path);
|
||||
try {
|
||||
Response response = client.invoiceDownload(accessToken, param);
|
||||
if (response == null || response.status() != 200) {
|
||||
log.error("调用BFI接口 进项发票下载异常响应状态:{}", response == null ? "无响应" : response.status());
|
||||
throw new BfiException("调用BFI接口进项发票下载异常,响应状态:" + (response == null ? "无响应" : response.status()));
|
||||
}
|
||||
log.info("调用BFI接口 进项发票下载结束 耗时:{}ms", System.currentTimeMillis() - start);
|
||||
return response;
|
||||
} catch (BfiException e) {
|
||||
throw e;
|
||||
@@ -548,6 +554,34 @@ public class BfiServiceImpl implements IBfiService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BfiAttachmentUploadVO uploadAttachment(String entityNumber, String billPkId, String controlKey, String fileName, byte[] fileContent) {
|
||||
if (StringUtil.isBlank(entityNumber) || StringUtil.isBlank(billPkId)) {
|
||||
throw new BfiException("上传BFI附件失败,entityNumber与billPkId不能为空");
|
||||
}
|
||||
if (StringUtil.isBlank(fileName) || fileContent == null || fileContent.length == 0) {
|
||||
throw new BfiException("上传BFI附件失败,附件名称与内容不能为空");
|
||||
}
|
||||
String accessToken = getAccessToken();
|
||||
// A902 参数原文 JSON:{"entityNumber":"ap_payapply","billPkId":2386455983883835392,"controlKey":"attachmentpanel"}
|
||||
JSONObject args = new JSONObject();
|
||||
args.set("entityNumber", entityNumber);
|
||||
args.set("billPkId", billPkId);
|
||||
args.set("controlKey", StringUtil.isBlank(controlKey) ? "attachmentpanel" : controlKey);
|
||||
InMemoryMultipartFile file = new InMemoryMultipartFile("file", fileName, MediaType.APPLICATION_OCTET_STREAM_VALUE, fileContent);
|
||||
long start = System.currentTimeMillis();
|
||||
log.info("调用BFI接口 附件上传开始 entityNumber:{},billPkId:{},文件:{},大小:{}字节",
|
||||
entityNumber, billPkId, fileName, fileContent.length);
|
||||
BfiResultVO<BfiAttachmentUploadVO> result = commonCall("附件上传", () -> client.uploadAttachment(accessToken, file, args.toString()));
|
||||
BfiAttachmentUploadVO uploadVO = result.getData();
|
||||
if (uploadVO == null || StringUtil.isBlank(uploadVO.getPath())) {
|
||||
log.error("调用BFI接口 附件上传返回数据为空:{}", JSONUtil.toJsonStr(result));
|
||||
throw new BfiException("调用BFI接口附件上传异常,返回数据为空");
|
||||
}
|
||||
log.info("调用BFI接口 附件上传结束 耗时:{}ms,kingdeePath:{}", System.currentTimeMillis() - start, uploadVO.getPath());
|
||||
return uploadVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共调用方法,统一校验响应结果
|
||||
*
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* 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.util;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 内存字节数组版 MultipartFile:A902 附件上传经 Feign multipart 发送时使用,
|
||||
* 文件内容已整体读入内存(单文件软限制 20MB,见 KingdeeAttachmentConstant)
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class InMemoryMultipartFile implements MultipartFile {
|
||||
|
||||
private final String name;
|
||||
private final String originalFilename;
|
||||
private final String contentType;
|
||||
private final byte[] content;
|
||||
|
||||
public InMemoryMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
|
||||
this.name = name;
|
||||
this.originalFilename = originalFilename;
|
||||
this.contentType = contentType;
|
||||
this.content = content == null ? new byte[0] : content;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return content.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public byte[] getBytes() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public InputStream getInputStream() {
|
||||
return new ByteArrayInputStream(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(@NonNull File destination) throws IOException {
|
||||
try (FileOutputStream outputStream = new FileOutputStream(destination)) {
|
||||
outputStream.write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user