|
|
@@ -20,11 +20,17 @@ import com.malk.utils.UtilMap;
|
|
|
import com.malk.utils.UtilToken;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.logging.log4j.util.Strings;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
|
|
|
|
+import java.net.CookieManager;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.security.MessageDigest;
|
|
|
import java.util.*;
|
|
|
|
|
|
import static org.junit.Assert.fail;
|
|
|
@@ -98,10 +104,15 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
|
|
|
for (Map address : addressList) {
|
|
|
CustomerContactEntry customerContactEntry = new CustomerContactEntry();
|
|
|
- customerContactEntry.setFNUMBER1(UtilMap.getString(address,"ShortText1758199808715"));//地点编码
|
|
|
- customerContactEntry.setFNAME1(UtilMap.getString(address,"ShortText1758199824395"));//地点名称
|
|
|
+ String addressCode = UtilMap.getString(address, "ShortText1758199808715");
|
|
|
+ String addressName = UtilMap.getString(address, "ShortText1758199824395");
|
|
|
|
|
|
- FT_BD_CUSTCONTACT.add(customerContactEntry);
|
|
|
+ if (Strings.isNotBlank(addressCode) && Strings.isNotBlank(addressName)){
|
|
|
+ customerContactEntry.setFNUMBER1(addressCode);//地点编码
|
|
|
+ customerContactEntry.setFNAME1(addressName);//地点名称
|
|
|
+
|
|
|
+ FT_BD_CUSTCONTACT.add(customerContactEntry);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
customerModel.setFName(FName);
|
|
|
@@ -128,7 +139,10 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
customerModel.setFSOCIALCRECODE(FSOCIALCRECODE);
|
|
|
customerModel.setFINVOICETEL(FINVOICETEL);
|
|
|
customerModel.setFINVOICEADDRESS(FINVOICEADDRESS);
|
|
|
- customerModel.setFT_BD_CUSTCONTACT(FT_BD_CUSTCONTACT);
|
|
|
+
|
|
|
+ if (!FT_BD_CUSTCONTACT.isEmpty()){
|
|
|
+ customerModel.setFT_BD_CUSTCONTACT(FT_BD_CUSTCONTACT);
|
|
|
+ }
|
|
|
|
|
|
save.setModel(customerModel);
|
|
|
Gson gson2 = new Gson();
|
|
|
@@ -168,7 +182,7 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
isTrue(repoRet2);
|
|
|
customerCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
|
|
|
//回写云枢客户编号
|
|
|
- cpClient.updateCpBo("ZLKHLC",UtilMap.map("id, ShortText1758195840127",objectId,customerCode),null);
|
|
|
+// cpClient.updateCpBo("ZLKHLC",UtilMap.map("id, ShortText1758195840127",objectId,customerCode),null);
|
|
|
|
|
|
if (isTrue(repoRet2)){
|
|
|
Audit audit = new Audit();
|
|
|
@@ -413,6 +427,7 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
List<Map> saleDetailList = UtilMap.getList(saleOrderData, "Sheet1758341252878");
|
|
|
List<SaleOrderEntry> saleOrderEntryList = new ArrayList<>();
|
|
|
|
|
|
+
|
|
|
for (Map saleDetail : saleDetailList) {
|
|
|
FNumber FMaterialId = new FNumber(UtilMap.getString(saleDetail, "ShortText1758341332222"));//物料编码
|
|
|
FNumber FUnitID = new FNumber(UtilMap.getString(saleDetail, "Text1758341368975"));//销售单位
|
|
|
@@ -441,7 +456,7 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
Double FDeliveryMaxQty = UtilMap.getDouble(saleDetail, "Number1763091294543");//发货上限
|
|
|
Double FDeliveryMinQty = UtilMap.getDouble(saleDetail, "Number1763091312359");//发货下限
|
|
|
|
|
|
- //todo 订单图纸附件上传
|
|
|
+
|
|
|
|
|
|
|
|
|
SaleOrderEntry saleOrderEntry = new SaleOrderEntry();
|
|
|
@@ -469,6 +484,25 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
saleOrderEntry.setFDeliveryMaxQty(FDeliveryMaxQty);
|
|
|
saleOrderEntry.setFDeliveryMinQty(FDeliveryMinQty);
|
|
|
|
|
|
+ //todo 订单图纸附件上传
|
|
|
+ List<Map> attachments = UtilMap.getList(saleDetail, "Attachment1763102109764");
|
|
|
+ if (!attachments.isEmpty()){
|
|
|
+ Map attachment = attachments.get(0);
|
|
|
+ String refId = UtilMap.getString(attachment, "refId");
|
|
|
+ String fileName = UtilMap.getString(attachment, "name");
|
|
|
+
|
|
|
+ String escapeRefId = new String(Base64.getUrlDecoder().decode(refId), StandardCharsets.UTF_8).substring(5);
|
|
|
+
|
|
|
+ String filePath = "/home/data/cloudpivot/file/"+escapeRefId.substring(0,2)+"/"+escapeRefId.substring(2,4)+"/"+escapeRefId;
|
|
|
+
|
|
|
+// String fileName2 = "4.png";
|
|
|
+// String filePath2 = "C:\\Users\\EDY\\Pictures\\4.png";
|
|
|
+
|
|
|
+ String fileId = kdUpload(fileName, filePath);
|
|
|
+
|
|
|
+ saleOrderEntry.setF_Sl_Attachment(fileId);
|
|
|
+ }
|
|
|
+
|
|
|
saleOrderEntryList.add(saleOrderEntry);
|
|
|
}
|
|
|
|
|
|
@@ -615,4 +649,290 @@ public class JinlunServiceImpl implements JinlunService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private String kdUpload(String fileName,String filePath){
|
|
|
+ try {
|
|
|
+ // 1. 读取文件为字节数组
|
|
|
+ byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
|
|
|
+
|
|
|
+ // 2. 转换为Base64字符串
|
|
|
+ String base64String = "";
|
|
|
+
|
|
|
+ K3CloudApi client = new K3CloudApi(initIden());
|
|
|
+
|
|
|
+ // 定义分块大小(4MB)
|
|
|
+ final int CHUNK_SIZE = 4 * 1024 * 1024;
|
|
|
+
|
|
|
+ long fileSize = fileBytes.length;
|
|
|
+
|
|
|
+ String fileId = null;
|
|
|
+
|
|
|
+ //sdk无直接上传附件接口 临时将附件上传并绑定固定单据 得到fileId
|
|
|
+ Map map = new HashMap();
|
|
|
+ map.put("FileName", fileName);//文件名
|
|
|
+ map.put("FormId", "SAL_SaleOrder");//表单id
|
|
|
+ map.put("InterId", "104784");//单据内码
|
|
|
+ map.put("BillNO", "S301-251118005");//单据编号
|
|
|
+
|
|
|
+
|
|
|
+ // 如果文件小于等于4MB,直接上传
|
|
|
+ if (fileSize <= CHUNK_SIZE) {
|
|
|
+ base64String = Base64.getEncoder().encodeToString(fileBytes);
|
|
|
+
|
|
|
+ map.put("IsLast", true);//是否最后一次上传
|
|
|
+ map.put("SendByte", base64String);//文件字节数组转base64后的字符串
|
|
|
+
|
|
|
+ String resultJson = client.attachmentUpload(JSONObject.toJSONString(map));
|
|
|
+
|
|
|
+ Map parse = (Map) JSONObject.parse(resultJson);
|
|
|
+
|
|
|
+ Map map1 = UtilMap.getMap(parse, "Result");
|
|
|
+
|
|
|
+ fileId = UtilMap.getString(map1, "FileId");
|
|
|
+
|
|
|
+ return fileId;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 分块上传逻辑
|
|
|
+ int totalChunks = (int) Math.ceil((double) fileSize / CHUNK_SIZE);
|
|
|
+
|
|
|
+ for (int i = 0; i < totalChunks; i++) {
|
|
|
+ // 计算当前块的起始和结束位置
|
|
|
+ int start = i * CHUNK_SIZE;
|
|
|
+ int end = (int) Math.min(start + CHUNK_SIZE, fileSize);
|
|
|
+ int chunkLength = end - start;
|
|
|
+
|
|
|
+ // 提取当前分块的数据
|
|
|
+ byte[] chunkBytes = new byte[chunkLength];
|
|
|
+ System.arraycopy(fileBytes, start, chunkBytes, 0, chunkLength);
|
|
|
+
|
|
|
+ // 转换为Base64字符串
|
|
|
+ base64String = Base64.getEncoder().encodeToString(chunkBytes);
|
|
|
+
|
|
|
+ // 第一个块需要获取FileId,后续块需要携带FileId
|
|
|
+ boolean isLastChunk = (i == totalChunks - 1);
|
|
|
+
|
|
|
+ if (i == 0) {
|
|
|
+ // 第一个块,IsLast为false
|
|
|
+ map.put("IsLast", false);
|
|
|
+ map.put("SendByte", base64String);//文件字节数组转base64后的字符串
|
|
|
+
|
|
|
+ String resultJson = client.attachmentUpload(JSONObject.toJSONString(map));
|
|
|
+
|
|
|
+ Map parse = (Map) JSONObject.parse(resultJson);
|
|
|
+
|
|
|
+ Map map1 = UtilMap.getMap(parse, "Result");
|
|
|
+
|
|
|
+ fileId = UtilMap.getString(map1, "FileId");
|
|
|
+ } else {
|
|
|
+ // 后续块,需要携带FileId
|
|
|
+ map.put("FileId", fileId);
|
|
|
+ map.put("IsLast", isLastChunk);
|
|
|
+ map.put("SendByte", base64String);//文件字节数组转base64后的字符串
|
|
|
+
|
|
|
+ String resultJson = client.attachmentUpload(JSONObject.toJSONString(map));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println(fileId);
|
|
|
+
|
|
|
+ return fileId;
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*private String kdUpload(String fileName, String filePath) {
|
|
|
+ try {
|
|
|
+ // 定义分块大小(4MB)
|
|
|
+ final int CHUNK_SIZE = 4 * 1024 * 1024;
|
|
|
+
|
|
|
+ // 1. 读取文件为字节数组
|
|
|
+ byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
|
|
|
+ long fileSize = fileBytes.length;
|
|
|
+
|
|
|
+ String fileId = null;
|
|
|
+
|
|
|
+ // 如果文件小于等于4MB,直接上传
|
|
|
+ if (fileSize <= CHUNK_SIZE) {
|
|
|
+ String base64String = Base64.getEncoder().encodeToString(fileBytes);
|
|
|
+
|
|
|
+ Map<String, Object> body = new HashMap<>();
|
|
|
+ Map<String, Object> data = new HashMap<>();
|
|
|
+ data.put("FileName", fileName);
|
|
|
+ data.put("SendByte", base64String);
|
|
|
+ data.put("IsLast", true);
|
|
|
+ body.put("data",data);
|
|
|
+
|
|
|
+ // 调用上传接口(带会话检查)
|
|
|
+ Map<String, Object> result = uploadWithSessionCheck(body, true);
|
|
|
+
|
|
|
+ // 获取FileId
|
|
|
+ Map<String, Object> resultData = UtilMap.getMap(result, "Result");
|
|
|
+ fileId = UtilMap.getString(resultData, "FileId");
|
|
|
+
|
|
|
+ return fileId;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 分块上传逻辑
|
|
|
+ int totalChunks = (int) Math.ceil((double) fileSize / CHUNK_SIZE);
|
|
|
+
|
|
|
+ for (int i = 0; i < totalChunks; i++) {
|
|
|
+ // 计算当前块的起始和结束位置
|
|
|
+ int start = i * CHUNK_SIZE;
|
|
|
+ int end = (int) Math.min(start + CHUNK_SIZE, fileSize);
|
|
|
+ int chunkLength = end - start;
|
|
|
+
|
|
|
+ // 提取当前分块的数据
|
|
|
+ byte[] chunkBytes = new byte[chunkLength];
|
|
|
+ System.arraycopy(fileBytes, start, chunkBytes, 0, chunkLength);
|
|
|
+
|
|
|
+ // 转换为Base64字符串
|
|
|
+ String base64String = Base64.getEncoder().encodeToString(chunkBytes);
|
|
|
+
|
|
|
+ // 准备请求体
|
|
|
+ Map<String, Object> body = new HashMap<>();
|
|
|
+ Map<String,Object> data = new HashMap<>();
|
|
|
+ data.put("FileName", fileName);
|
|
|
+ data.put("SendByte", base64String);
|
|
|
+ body.put("data",data);
|
|
|
+
|
|
|
+ // 第一个块需要获取FileId,后续块需要携带FileId
|
|
|
+ boolean isLastChunk = (i == totalChunks - 1);
|
|
|
+
|
|
|
+ if (i == 0) {
|
|
|
+ // 第一个块,IsLast为false
|
|
|
+ body.put("IsLast", false);
|
|
|
+
|
|
|
+ // 调用上传接口(带会话检查)
|
|
|
+ Map<String, Object> result = uploadWithSessionCheck(body, false);
|
|
|
+
|
|
|
+ // 获取FileId
|
|
|
+ Map<String, Object> resultData = UtilMap.getMap(result, "Result");
|
|
|
+ fileId = UtilMap.getString(resultData, "FileId");
|
|
|
+ } else {
|
|
|
+ // 后续块,需要携带FileId
|
|
|
+ body.put("FileId", fileId);
|
|
|
+ body.put("IsLast", isLastChunk);
|
|
|
+
|
|
|
+ // 调用上传接口(带会话检查)
|
|
|
+ uploadWithSessionCheck(body, isLastChunk);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return fileId;
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 带会话检查的上传方法(支持单块和多块上传)
|
|
|
+ private Map<String, Object> uploadWithSessionCheck(Map<String, Object> body, boolean isLastChunk) {
|
|
|
+ while (true) {
|
|
|
+ try {
|
|
|
+ // 调用上传接口
|
|
|
+ Map<String, Object> result = (Map<String, Object>) JSONObject.parse(UtilHttp.doPost(kdWebApiConf.getXKDApiServerUrl() + "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UploadFile.common.kdsvc", null, null, body));
|
|
|
+
|
|
|
+ // 检查响应状态
|
|
|
+ checkResponseStatus(result);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ } catch (RuntimeException e) {
|
|
|
+ // 解析错误响应
|
|
|
+ try {
|
|
|
+ Map<String, Object> responseStatus = (Map<String, Object>) JSONObject.parse(e.getMessage());
|
|
|
+
|
|
|
+ // 如果是会话丢失错误
|
|
|
+ if (responseStatus != null && UtilMap.getString(((List<Map>)UtilMap.getList(responseStatus, "Errors")).get(0),"Message").equals("会话信息已丢失,请重新登录")) {
|
|
|
+ // 重新登录
|
|
|
+ kdLogin();
|
|
|
+
|
|
|
+ // 如果是最后一块上传失败,需要设置IsLast为true
|
|
|
+ if (isLastChunk) {
|
|
|
+ body.put("IsLast", true);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重试上传
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } catch (Exception parseException) {
|
|
|
+ // 如果不是会话丢失错误,直接抛出原始异常
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果不是会话丢失错误,直接抛出原始异常
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查响应状态
|
|
|
+ private void checkResponseStatus(Map<String, Object> result) {
|
|
|
+ if (result == null || !result.containsKey("Result")) {
|
|
|
+ throw new RuntimeException("无效的响应格式");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Object> resultData = UtilMap.getMap(result, "Result");
|
|
|
+ Map<String, Object> responseStatus = UtilMap.getMap(resultData, "ResponseStatus");
|
|
|
+
|
|
|
+ if (responseStatus == null || !UtilMap.getBoolean(responseStatus, "IsSuccess")) {
|
|
|
+ String message = UtilMap.getString(resultData, "Message");
|
|
|
+ // 如果有错误码,也包含在异常信息中
|
|
|
+ int errorCode = UtilMap.getInt(responseStatus, "ErrorCode");
|
|
|
+ if (errorCode != 0) {
|
|
|
+ message = "错误码: " + errorCode + ", 消息: " + message;
|
|
|
+ log.info("message: {}", message);
|
|
|
+ }
|
|
|
+ throw new RuntimeException(JSONObject.toJSONString(responseStatus));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void kdLogin(){
|
|
|
+ try {
|
|
|
+ //金蝶登录
|
|
|
+ String acctID = kdWebApiConf.getXKDApiAcctID();
|
|
|
+ String username = kdWebApiConf.getXKDApiUserName();
|
|
|
+ String appId = kdWebApiConf.getXKDApiAppID();
|
|
|
+ String appSec = kdWebApiConf.getXKDApiAppSec();
|
|
|
+ String timestamp = System.currentTimeMillis()/1000 + "";
|
|
|
+
|
|
|
+ String[] arr = {acctID,username,appId,appSec,timestamp};
|
|
|
+
|
|
|
+ Arrays.sort(arr, String::compareTo);
|
|
|
+
|
|
|
+ String str = String.join("", arr);
|
|
|
+
|
|
|
+ // 1. 创建 MessageDigest 实例,指定 SHA-256 算法
|
|
|
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
|
|
+
|
|
|
+ // 2. 输入字符串转换为字节数组,并计算哈希值
|
|
|
+ byte[] hashBytes = digest.digest(str.getBytes(StandardCharsets.UTF_8));
|
|
|
+
|
|
|
+ // 3. 将字节数组转换为十六进制字符串
|
|
|
+ StringBuilder sign = new StringBuilder();
|
|
|
+ for (byte b : hashBytes) {
|
|
|
+ String hex = Integer.toHexString(0xff & b);
|
|
|
+ if (hex.length() == 1) {
|
|
|
+ sign.append('0'); // 补零
|
|
|
+ }
|
|
|
+ sign.append(hex);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 输出结果
|
|
|
+ System.out.println("SHA-256 哈希值: " + sign.toString());
|
|
|
+
|
|
|
+ Map body = new HashMap();
|
|
|
+ body.put("acctID",acctID);
|
|
|
+ body.put("username",username);
|
|
|
+ body.put("appId",appId);
|
|
|
+ body.put("timestamp",timestamp);
|
|
|
+ body.put("sign",sign.toString());
|
|
|
+ body.put("lcid",2052);
|
|
|
+
|
|
|
+ UtilHttp.doPost(kdWebApiConf.getXKDApiServerUrl() + "Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginBySign.common.kdsvc", null, null, body);
|
|
|
+
|
|
|
+ }catch (Exception e){
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }*/
|
|
|
+
|
|
|
}
|