package com.zy.asrs.task.kingdee.handler; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.zy.asrs.entity.DocType; import com.zy.asrs.entity.ErpSecret; import com.zy.asrs.entity.Order; import com.zy.asrs.entity.OrderDetlPakin; import com.zy.asrs.service.ApiLogService; import com.zy.asrs.service.DocTypeService; import com.zy.asrs.service.OrderService; import com.zy.asrs.service.impl.ErpSecretServiceImpl; import com.zy.asrs.task.AbstractHandler; import com.zy.asrs.task.core.ReturnT; import com.zy.asrs.utils.OrderInAndOutUtil; import com.zy.common.utils.HttpHandler; import com.zy.erp.kingdee.enums.KingDeeUtilType; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Set; /** * Created by Monkey D. Luffy on 2023.10.21 */ @Slf4j @Service public class SubmitOrderSyncHandler extends AbstractHandler { @Value("${erp.address.URL}") private String URL; @Value("${erp.address.imPurinbillBatchSubmit}") private String imPurinbillBatchSubmit; @Autowired private LoginAuthenticationHandler loginAuthenticationHandler; @Autowired private ErpSecretServiceImpl erpSecretService; @Autowired private OrderService orderService; @Autowired private ApiLogService apiLogService; @Autowired private DocTypeService docTypeService; @Value("${erp.login.accountId}") private String accountId; @Value("${erp.login.xAcfwIdentity}") private String xAcfwIdentity; private String path; @Transactional public ReturnT start(Order order) { SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd"); // 获取 Token ErpSecret erpSecret = erpSecretService.selectOne(new EntityWrapper().eq("account_id", accountId)); // 获取 DocType DocType docType = docTypeService.selectById(order.getDocType()); if (docType == null) return SUCCESS; // 获取 KingDee 类型 KingDeeUtilType kingDeeUtilType = KingDeeUtilType.get(docType.getDocName()); // 构建请求参数 JSONObject add = buildRequestParams(order, kingDeeUtilType, sdf1, sdf2); if (add == null) return FAIL.setMsg("请求参数构建失败"); // 发送请求并处理响应 return sendRequestAndProcessResponse(order, erpSecret, add); } private JSONObject buildRequestParams(Order order, KingDeeUtilType kingDeeUtilType, SimpleDateFormat sdf1, SimpleDateFormat sdf2) { switch (kingDeeUtilType.formId) { case "PUR_RECEIVEBIll": // 进仓通知单提交 path = imPurinbillBatchSubmit; JSONArray idArray = new JSONArray(); idArray.add(order.getNumber()); JSONObject dataObj = new JSONObject(); dataObj.fluentPut("id", idArray); return new JSONObject().fluentPut("data", dataObj); default: throw new IllegalArgumentException("Unsupported formId: " + kingDeeUtilType.formId); } } private ReturnT sendRequestAndProcessResponse(Order order, ErpSecret erpSecret, JSONObject add) { String response = ""; boolean success = false; try { // 设置请求头 HashMap headers = buildRequestHeaders(erpSecret); // 发送请求,将 JSONObject 转换为 String response = new HttpHandler.Builder() .setHeaders(headers) .setUri(URL) .setPath(path) .setJson(add.toJSONString()) // 将 JSONObject 转换为 String .build() .doPost(); // 解析响应 JSONObject jsonResponse = JSON.parseObject(response); // 判断是否因为 token 过期 (errorCode = 401) if ("401".equals(jsonResponse.getString("errorCode"))) { log.error("认证失败,尝试重新获取 Token"); loginAuthenticationHandler.start(); // 刷新 token // 重新获取新的 token erpSecret = erpSecretService.selectOne(new EntityWrapper().eq("account_id", accountId)); // 重新从数据库获取新的 token // 使用新的 token 重试请求 headers.put("accesstoken", erpSecret.getAccessToken()); response = new HttpHandler.Builder() .setHeaders(headers) .setUri(URL) .setPath(path) .setJson(add.toJSONString()) // 将 JSONObject 转换为 String .build() .doPost(); } // 解析返回的响应 JSONObject data = jsonResponse.getJSONObject("data"); String errorCode = jsonResponse.getString("errorCode"); boolean status = jsonResponse.getBooleanValue("status"); // 检查接口调用的整体状态 if ("0".equals(errorCode) && status) { // 获取成功与失败的数量 int successCount = data.getInteger("successCount"); int failCount = data.getInteger("failCount"); if (failCount == 0) { success = true; log.info("接口调用成功,成功的操作数量: {}", successCount); } else { log.error("接口调用失败,失败的操作数量: {}", failCount); // 如果有失败的单据,遍历 result 数组查看失败的详细信息 JSONArray resultArray = data.getJSONArray("result"); for (int i = 0; i < resultArray.size(); i++) { JSONObject resultItem = resultArray.getJSONObject(i); if (!resultItem.getBoolean("billStatus")) { // 单据处理失败,记录错误信息 String billNo = resultItem.getString("number"); // 获取返回的单据号 JSONArray errors = resultItem.getJSONArray("errors"); // 获取错误信息 // 打印单据号和错误信息 log.error("单据号: {}, 错误信息: {}", billNo, errors); } } } order.setSettle(9L); // 更新状态为已提交完成 10->9 orderService.updateById(order); } else { log.error("接口调用失败,错误信息: {}", jsonResponse.getString("message")); } } catch (Exception e) { log.error("请求失败", e); return FAIL.setMsg(e.getMessage()); } finally { // 保存接口日志 saveApiLog(add, response, success); } return success ? SUCCESS : FAIL; } private HashMap buildRequestHeaders(ErpSecret erpSecret) { HashMap headers = new HashMap<>(); headers.put("accesstoken", erpSecret.getAccessToken()); headers.put("x-acgw-identity", xAcfwIdentity); // 自定义请求头 return headers; } private void saveApiLog(JSONObject add, String response, boolean success) { try { apiLogService.save( "单据上报提交", URL + path, null, "127.0.0.1", add.toJSONString(), response, success ); } catch (Exception e) { log.error("接口日志保存失败", e); } } }