|
@@ -1,6 +1,7 @@
|
|
|
package com.jeeplus.modules.ruralprojectrecords.web;
|
|
package com.jeeplus.modules.ruralprojectrecords.web;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Lists;
|
|
|
import com.jeeplus.common.config.Global;
|
|
import com.jeeplus.common.config.Global;
|
|
|
import com.jeeplus.common.oss.OSSClientUtil;
|
|
import com.jeeplus.common.oss.OSSClientUtil;
|
|
@@ -9,7 +10,6 @@ import com.jeeplus.common.utils.excel.ExportExcel;
|
|
|
import com.jeeplus.common.utils.excel.ImportExcel;
|
|
import com.jeeplus.common.utils.excel.ImportExcel;
|
|
|
import com.jeeplus.common.web.BaseController;
|
|
import com.jeeplus.common.web.BaseController;
|
|
|
import com.jeeplus.modules.militaryIndustryConfidentiality.service.MilitaryIndustryConfidentialityService;
|
|
import com.jeeplus.modules.militaryIndustryConfidentiality.service.MilitaryIndustryConfidentialityService;
|
|
|
-import com.jeeplus.modules.pojectMaterialsWarehouse.entity.ProjectMaterialCollectInfo;
|
|
|
|
|
import com.jeeplus.modules.projectAccessory.dao.ProjectTemplateDao;
|
|
import com.jeeplus.modules.projectAccessory.dao.ProjectTemplateDao;
|
|
|
import com.jeeplus.modules.projectAccessory.entity.ProjectTemplateInfo;
|
|
import com.jeeplus.modules.projectAccessory.entity.ProjectTemplateInfo;
|
|
|
import com.jeeplus.modules.projectcontentinfo.dao.ProjectReportRecordDao;
|
|
import com.jeeplus.modules.projectcontentinfo.dao.ProjectReportRecordDao;
|
|
@@ -29,7 +29,6 @@ import com.jeeplus.modules.ruralprojectrecords.service.RuralProjectRecordsServic
|
|
|
import com.jeeplus.modules.ruralprojectrecords.service.RuralProjectSignatureOldMessageDisposeService;
|
|
import com.jeeplus.modules.ruralprojectrecords.service.RuralProjectSignatureOldMessageDisposeService;
|
|
|
import com.jeeplus.modules.statement.service.StatementCompanyComprehensiveService;
|
|
import com.jeeplus.modules.statement.service.StatementCompanyComprehensiveService;
|
|
|
import com.jeeplus.modules.sys.entity.User;
|
|
import com.jeeplus.modules.sys.entity.User;
|
|
|
-import com.jeeplus.modules.sys.entity.Workattachment;
|
|
|
|
|
import com.jeeplus.modules.sys.service.WorkattachmentService;
|
|
import com.jeeplus.modules.sys.service.WorkattachmentService;
|
|
|
import com.jeeplus.modules.sys.utils.UserUtils;
|
|
import com.jeeplus.modules.sys.utils.UserUtils;
|
|
|
import com.jeeplus.modules.tools.utils.SignaturePostUtil;
|
|
import com.jeeplus.modules.tools.utils.SignaturePostUtil;
|
|
@@ -37,17 +36,21 @@ import com.jeeplus.modules.utils.SftpClientUtil;
|
|
|
import com.jeeplus.modules.workactivity.entity.WorkActivityProcess;
|
|
import com.jeeplus.modules.workactivity.entity.WorkActivityProcess;
|
|
|
import com.jeeplus.modules.workactivity.service.WorkActivityProcessService;
|
|
import com.jeeplus.modules.workactivity.service.WorkActivityProcessService;
|
|
|
import com.jeeplus.modules.workclientinfo.entity.WorkClientAttachment;
|
|
import com.jeeplus.modules.workclientinfo.entity.WorkClientAttachment;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.entity.OMS.InvoiceDown.OMSInvoiceDetailInfo;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.entity.OMS.InvoiceOMSImportInfo;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.entity.OMS.OMSAccessTokenInfo;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.entity.OMS.OMSInvoiceResultDownloadData;
|
|
|
import com.jeeplus.modules.workinvoice.entity.TemporaryInvoiceInfo;
|
|
import com.jeeplus.modules.workinvoice.entity.TemporaryInvoiceInfo;
|
|
|
import com.jeeplus.modules.workinvoice.service.WorkInvoiceService;
|
|
import com.jeeplus.modules.workinvoice.service.WorkInvoiceService;
|
|
|
-import com.jeeplus.modules.workreimbursement.entity.ReimbursementVATTax;
|
|
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.utils.HttpPostJsonUtil;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.utils.OMSNationUtil;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.utils.ThreadPoolUtil;
|
|
|
import com.jeeplus.modules.workreimbursement.service.WorkReimbursementService;
|
|
import com.jeeplus.modules.workreimbursement.service.WorkReimbursementService;
|
|
|
import com.jeeplus.modules.workstaff.service.WorkStaffBasicInfoService;
|
|
import com.jeeplus.modules.workstaff.service.WorkStaffBasicInfoService;
|
|
|
import freemarker.template.Configuration;
|
|
import freemarker.template.Configuration;
|
|
|
import freemarker.template.Template;
|
|
import freemarker.template.Template;
|
|
|
import org.activiti.engine.HistoryService;
|
|
import org.activiti.engine.HistoryService;
|
|
|
-import org.apache.shiro.authz.annotation.RequiresPermissions;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
|
import org.springframework.stereotype.Controller;
|
|
import org.springframework.stereotype.Controller;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
@@ -58,6 +61,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Document;
|
|
|
import org.w3c.dom.NodeList;
|
|
import org.w3c.dom.NodeList;
|
|
|
|
|
+import redis.clients.jedis.Jedis;
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
@@ -66,6 +70,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -936,4 +941,291 @@ public class RuralProjectSignatureOldMessageDisposeController extends BaseContro
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * OMS发票测试 完整最终版【最终最终定稿,完全匹配你的所有要求】
|
|
|
|
|
+ * 精准码值规则:
|
|
|
|
|
+ * 0000=成功执行下载 | 9998=5次重试/30秒 | 0003=清token从头执行 | 0001/0002/其他码=直接执行兜底方法修改系统信息
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping(value = "/invoiceOMSView")
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ @Transactional(readOnly = false)
|
|
|
|
|
+ public Map<String,Object> invoiceOMSView(){
|
|
|
|
|
+ Map<String,Object> map = new HashMap<>();
|
|
|
|
|
+ // 调用抽离后的核心业务方法,实现流程复用(0003时可重新调用)
|
|
|
|
|
+ doInvoiceBusiness(map);
|
|
|
|
|
+ return map;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ======================== 抽离核心业务流程:方便0003时从头重新调用 =========================
|
|
|
|
|
+ private void doInvoiceBusiness(Map<String,Object> map) {
|
|
|
|
|
+ int seconds = 86400;
|
|
|
|
|
+ Jedis jedis = null;
|
|
|
|
|
+ String accessToken = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ jedis = JedisUtils.getResource();
|
|
|
|
|
+ accessToken = jedis.get("OMSAccessToken");
|
|
|
|
|
+ if(StringUtils.isBlank(accessToken)){
|
|
|
|
|
+ // 获取AccessToken 9998重试5次
|
|
|
|
|
+ accessToken = getOmsAccessTokenWithRetry(5);
|
|
|
|
|
+ if(StringUtils.isNotBlank(accessToken)){
|
|
|
|
|
+ jedis.setex("OMSAccessToken", seconds, accessToken);
|
|
|
|
|
+ map.put("token状态", "重新获取token成功,存入Redis");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ accessToken = "";
|
|
|
|
|
+ map.put("token状态", "获取token失败");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ map.put("token状态", "从Redis获取token成功");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ OMSNationUtil util = new OMSNationUtil();
|
|
|
|
|
+ String string = util.neatenData();
|
|
|
|
|
+
|
|
|
|
|
+ OMSAccessTokenInfo InvoiceTokenInfo = new OMSAccessTokenInfo();
|
|
|
|
|
+ InvoiceTokenInfo.setAppId("sscs");
|
|
|
|
|
+ InvoiceTokenInfo.setAppKey("sscs");
|
|
|
|
|
+ InvoiceTokenInfo.setExchangeId(UUID.randomUUID().toString());
|
|
|
|
|
+ InvoiceTokenInfo.setAccessToken(accessToken);
|
|
|
|
|
+ InvoiceTokenInfo.setData(string);
|
|
|
|
|
+ String jsonInvoiceStr = JSON.toJSONString(InvoiceTokenInfo);
|
|
|
|
|
+
|
|
|
|
|
+ String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/order/upload", jsonInvoiceStr);
|
|
|
|
|
+ System.out.println("✅ 订单提交接口返回值:" + jsonInvoicResultStr);
|
|
|
|
|
+ map.put("订单接口信息", jsonInvoicResultStr);
|
|
|
|
|
+
|
|
|
|
|
+ // 调用订单上传重试方法(包含所有码值规则)
|
|
|
|
|
+ if(StringUtils.isNotBlank(jsonInvoicResultStr)){
|
|
|
|
|
+ String finalAccessToken = accessToken;
|
|
|
|
|
+ String finalJsonInvoiceStr = jsonInvoiceStr;
|
|
|
|
|
+ executeOrderUploadRetry(5, jsonInvoicResultStr, finalJsonInvoiceStr, finalAccessToken, map);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ map.put("errorMsg", "系统异常:" + e.getMessage());
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if(jedis != null){
|
|
|
|
|
+ jedis.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ======================== 原有方法1:获取AccessToken 9998重试5次【无修改】 =========================
|
|
|
|
|
+ private String getOmsAccessTokenWithRetry(int remainRetryTimes) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ OMSAccessTokenInfo tokenInfo = new OMSAccessTokenInfo();
|
|
|
|
|
+ tokenInfo.setAppId("sscs");
|
|
|
|
|
+ tokenInfo.setAppKey("sscs");
|
|
|
|
|
+ tokenInfo.setExchangeId(UUID.randomUUID().toString());
|
|
|
|
|
+ String jsonStr = JSON.toJSONString(tokenInfo);
|
|
|
|
|
+ String accessTokenStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/server/accessToken", jsonStr);
|
|
|
|
|
+
|
|
|
|
|
+ if(StringUtils.isBlank(accessTokenStr)){
|
|
|
|
|
+ System.err.println("获取AccessToken失败:接口返回空,剩余重试次数:"+remainRetryTimes);
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ OMSAccessTokenInfo resultTokenInfo = JSON.parseObject(accessTokenStr, OMSAccessTokenInfo.class);
|
|
|
|
|
+ if(null == resultTokenInfo || null == resultTokenInfo.getResult()){
|
|
|
|
|
+ System.err.println("获取AccessToken失败:返回结果解析异常,剩余重试次数:"+remainRetryTimes);
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String code = resultTokenInfo.getResult().getCode();
|
|
|
|
|
+ if ("0000".equals(code)) {
|
|
|
|
|
+ String token = OMSNationUtil.extractAccessTokenFromBase64(resultTokenInfo.getData().toString());
|
|
|
|
|
+ System.out.println("✅ 获取AccessToken成功,重试次数剩余:"+remainRetryTimes);
|
|
|
|
|
+ return token;
|
|
|
|
|
+ } else if ("9998".equals(code)) {
|
|
|
|
|
+ if (remainRetryTimes > 1) {
|
|
|
|
|
+ int nextRetry = remainRetryTimes - 1;
|
|
|
|
|
+ System.err.println("⚠️ 获取AccessToken返回9998接口波动,30秒后重试,剩余次数:"+nextRetry);
|
|
|
|
|
+ Thread.sleep(30 * 1000);
|
|
|
|
|
+ return getOmsAccessTokenWithRetry(nextRetry);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ System.err.println("❌ 获取AccessToken失败:连续5次返回9998,重试次数耗尽!");
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ System.err.println("❌ 获取AccessToken失败:返回业务错误码,code="+code);
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
|
+ System.err.println("❌ 获取AccessToken失败:重试延迟被中断");
|
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
|
+ return "";
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ System.err.println("❌ 获取AccessToken失败:调用接口异常,剩余重试次数:"+remainRetryTimes);
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ======================== 核心修改【仅这一处,完美匹配你的最新要求】 =========================
|
|
|
|
|
+ private void executeOrderUploadRetry(int remainRetryTimes, String jsonInvoicResultStr, String jsonInvoiceStr, String accessToken, Map<String,Object> map) {
|
|
|
|
|
+ String jsonInvoicResult = "";
|
|
|
|
|
+ try {
|
|
|
|
|
+ OMSAccessTokenInfo resultTokenInfo = JSON.parseObject(jsonInvoicResultStr, OMSAccessTokenInfo.class);
|
|
|
|
|
+ if(null == resultTokenInfo || null == resultTokenInfo.getResult()){
|
|
|
|
|
+ System.err.println("❌ 订单上传解析失败,剩余重试次数:"+remainRetryTimes);
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken); // 解析失败也执行兜底方法
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ String code = resultTokenInfo.getResult().getCode();
|
|
|
|
|
+
|
|
|
|
|
+ // ======================== 所有码值规则 全部在这里【最终定稿】=========================
|
|
|
|
|
+ if ("0000".equals(code)) {
|
|
|
|
|
+ // ✅ 0000 成功:解析数据+存入map+触发30秒后异步下载发票
|
|
|
|
|
+ jsonInvoicResult = OMSNationUtil.extractAccessTokenFromBase64(resultTokenInfo.getData().toString());
|
|
|
|
|
+ map.put("订单接口返回值",jsonInvoicResult);
|
|
|
|
|
+ System.out.println("✅ 订单上传返回0000成功,触发发票下载接口");
|
|
|
|
|
+ ThreadPoolUtil.executeDelay(30, () -> {
|
|
|
|
|
+ executeInvoiceDownloadWithRetry(5, accessToken);
|
|
|
|
|
+ });
|
|
|
|
|
+ } else if ("9998".equals(code)) {
|
|
|
|
|
+ // ✅ 9998 接口波动:延迟30秒+重新调用接口+重试次数-1,最多5次
|
|
|
|
|
+ if (remainRetryTimes > 1) {
|
|
|
|
|
+ int nextRetry = remainRetryTimes - 1;
|
|
|
|
|
+ System.err.println("⚠️ 订单上传返回9998接口波动,30秒后重试,剩余次数:"+nextRetry);
|
|
|
|
|
+ Thread.sleep(30 * 1000);
|
|
|
|
|
+ String newResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/order/upload", jsonInvoiceStr);
|
|
|
|
|
+ map.put("订单接口信息-重试"+(6-nextRetry), newResultStr);
|
|
|
|
|
+ executeOrderUploadRetry(nextRetry, newResultStr, jsonInvoiceStr, accessToken, map);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ System.err.println("❌ 订单上传失败:连续5次9998,重试次数耗尽!");
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken); // 5次9998耗尽也执行兜底方法
|
|
|
|
|
+ map.put("订单状态", "失败:接口波动次数超限");
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if ("0003".equals(code)) {
|
|
|
|
|
+ // ✅ 0003 token失效:清除旧token → 重新获取token → 从头完整执行所有流程
|
|
|
|
|
+ System.err.println("⚠️ 订单上传返回0003(token失效),开始重新获取token并从头执行流程");
|
|
|
|
|
+ Jedis jedis = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ jedis = JedisUtils.getResource();
|
|
|
|
|
+ jedis.del("OMSAccessToken");
|
|
|
|
|
+ map.put("0003处理", "已清除旧token,准备重新获取");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if(jedis != null) jedis.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ doInvoiceBusiness(map);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // ✅ ✅ ✅ 核心修正:0001/0002/其他任意错误码 → 直接调用handleInvoiceRetryAllFail执行修改系统信息逻辑 ✅ ✅ ✅
|
|
|
|
|
+ System.err.println("❌ 订单上传返回业务错误码:"+code+"(0001/0002等),立即执行失败兜底逻辑修改系统信息!");
|
|
|
|
|
+ map.put("订单状态", "失败,错误码:"+code);
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken); // 关键:直接执行你的修改逻辑,不抛异常、不重试
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
|
+ System.err.println("❌ 订单上传重试被中断");
|
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken); // 中断也执行兜底方法
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ System.err.println("❌ 订单上传重试异常,剩余次数:"+remainRetryTimes);
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken); // 异常也执行兜底方法
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ======================== 原有方法2:发票下载接口重试5次【无任何修改,一行未动】 =========================
|
|
|
|
|
+ private void executeInvoiceDownloadWithRetry(int remainingRetryTimes, String accessToken) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ System.out.println("✅ 延迟执行成功,剩余重试次数:" + remainingRetryTimes + ",开始调用发票下载接口");
|
|
|
|
|
+
|
|
|
|
|
+ OMSInvoiceResultDownloadData getInvoiceInfo = new OMSInvoiceResultDownloadData();
|
|
|
|
|
+ getInvoiceInfo.setDeptCode("7777");
|
|
|
|
|
+ getInvoiceInfo.setOrderno("fff79669f3774c2a8be557e909a746d5");
|
|
|
|
|
+ getInvoiceInfo.setIsDetail("1");
|
|
|
|
|
+ String jsonInvoiceInfoStr = JSON.toJSONString(getInvoiceInfo);
|
|
|
|
|
+ String base64Str = Base64.getEncoder().encodeToString(jsonInvoiceInfoStr.getBytes(StandardCharsets.UTF_8));
|
|
|
|
|
+
|
|
|
|
|
+ OMSAccessTokenInfo invoiceDownInfo = new OMSAccessTokenInfo();
|
|
|
|
|
+ invoiceDownInfo.setAppId("sscs");
|
|
|
|
|
+ invoiceDownInfo.setAppKey("sscs");
|
|
|
|
|
+ invoiceDownInfo.setExchangeId(UUID.randomUUID().toString());
|
|
|
|
|
+ invoiceDownInfo.setAccessToken(accessToken);
|
|
|
|
|
+ invoiceDownInfo.setData(base64Str);
|
|
|
|
|
+ String jsonInvoiceDownStr = JSON.toJSONString(invoiceDownInfo);
|
|
|
|
|
+
|
|
|
|
|
+ String invoiceResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/invoice/download", jsonInvoiceDownStr);
|
|
|
|
|
+ System.out.println("发票开票结果invoiceResultStr:" + invoiceResultStr);
|
|
|
|
|
+
|
|
|
|
|
+ String invoceDownJsonStr = null;
|
|
|
|
|
+ boolean isSuccess = false;
|
|
|
|
|
+ if(StringUtils.isNotBlank(invoiceResultStr)){
|
|
|
|
|
+ OMSAccessTokenInfo resultDownInfo = JSON.parseObject(invoiceResultStr, OMSAccessTokenInfo.class);
|
|
|
|
|
+ if(null != resultDownInfo.getResult() && "0000".equals(resultDownInfo.getResult().getCode())){
|
|
|
|
|
+ invoceDownJsonStr = OMSNationUtil.getDownFromBase64(resultDownInfo.getData().toString());
|
|
|
|
|
+ if(StringUtils.isNotBlank(invoceDownJsonStr)){
|
|
|
|
|
+ OMSInvoiceDetailInfo invoiceInfo = JSONObject.parseObject(invoceDownJsonStr, OMSInvoiceDetailInfo.class);
|
|
|
|
|
+ if (invoiceInfo != null) {
|
|
|
|
|
+ System.out.println("✅ 第"+(6-remainingRetryTimes)+"次调用发票接口成功,拿到有效数据!");
|
|
|
|
|
+ System.out.println("getOfdUrl" + invoiceInfo.getOfdUrl());
|
|
|
|
|
+ System.out.println("getPdfUrl" + invoiceInfo.getPdfUrl());
|
|
|
|
|
+ System.out.println("getXmlUrl" + invoiceInfo.getXmlUrl());
|
|
|
|
|
+ isSuccess = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (isSuccess) {
|
|
|
|
|
+ System.out.println("✅ 发票接口调用成功,重试流程结束,执行后续业务");
|
|
|
|
|
+ return;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (remainingRetryTimes > 1) {
|
|
|
|
|
+ int nextRetryTimes = remainingRetryTimes - 1;
|
|
|
|
|
+ System.out.println("❌ 发票接口返回结果异常/数据未就绪,准备重试!剩余重试次数:" + nextRetryTimes);
|
|
|
|
|
+ ThreadPoolUtil.executeDelay(30, () -> {
|
|
|
|
|
+ executeInvoiceDownloadWithRetry(nextRetryTimes, accessToken);
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ System.err.println("❌ 发票接口调用失败,已重试5次全部失败,触发系统信息修改逻辑!");
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ System.err.println("❌ 调用发票接口抛出异常,剩余重试次数:" + remainingRetryTimes);
|
|
|
|
|
+ if (remainingRetryTimes > 1) {
|
|
|
|
|
+ int nextRetryTimes = remainingRetryTimes - 1;
|
|
|
|
|
+ ThreadPoolUtil.executeDelay(30, () -> {
|
|
|
|
|
+ executeInvoiceDownloadWithRetry(nextRetryTimes, accessToken);
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ System.err.println("❌ 发票接口调用抛出异常,已重试5次全部失败,触发系统信息修改逻辑!");
|
|
|
|
|
+ handleInvoiceRetryAllFail(accessToken);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ======================== 原有方法3:失败兜底修改系统信息【无任何修改,你的业务逻辑写这里即可】 =========================
|
|
|
|
|
+ private void handleInvoiceRetryAllFail(String accessToken) {
|
|
|
|
|
+ // ============ 你的所有【修改系统信息/更新订单状态/写失败日志】逻辑 全部写在这里!!! ============
|
|
|
|
|
+ try {
|
|
|
|
|
+ System.err.println("============ 开始执行【失败兜底-系统信息修改逻辑】 ============");
|
|
|
|
|
+
|
|
|
|
|
+ // 示例1:更新订单表的发票状态为【开票失败】
|
|
|
|
|
+ // orderService.updateInvoiceStatusByToken(accessToken, "99");
|
|
|
|
|
+
|
|
|
|
|
+ // 示例2:写入失败日志到数据库,方便人工排查和补偿处理
|
|
|
|
|
+ // invoiceFailLogService.saveFailLog(accessToken, "开票失败,错误码非0000/9998/0003", new Date());
|
|
|
|
|
+
|
|
|
|
|
+ // 示例3:标记该单据为异常,方便后台运维查看
|
|
|
|
|
+ // abnormalOrderService.saveAbnormalOrder(accessToken, "开票失败");
|
|
|
|
|
+
|
|
|
|
|
+ // 示例4:调用其他系统接口,同步失败状态
|
|
|
|
|
+ // otherSystemApi.notifyInvoiceFail(accessToken);
|
|
|
|
|
+
|
|
|
|
|
+ System.err.println("============ 【失败兜底-系统信息修改逻辑】执行完成 ============");
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ // 必加:捕获这个方法的异常,避免兜底方法报错导致线程异常
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ System.err.println("❌ 执行失败兜底方法时抛出异常:" + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|