fyz hai 13 horas
achega
3848c075ca
Modificáronse 24 ficheiros con 1752 adicións e 0 borrados
  1. 33 0
      mjava-mankalong/src/main/java/com/malk/mankalong/Boot.java
  2. 77 0
      mjava-mankalong/src/main/java/com/malk/mankalong/common/Result.java
  3. 22 0
      mjava-mankalong/src/main/java/com/malk/mankalong/controller/DDController.java
  4. 54 0
      mjava-mankalong/src/main/java/com/malk/mankalong/controller/DLController.java
  5. 69 0
      mjava-mankalong/src/main/java/com/malk/mankalong/delegate/DDDelegate.java
  6. 63 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Income/fct_ar.java
  7. 12 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Income/fct_ar_b.java
  8. 17 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Income/fct_ar_plan.java
  9. 59 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Payment/fct_ap.java
  10. 12 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Payment/fct_ap_b.java
  11. 13 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Payment/fct_ap_plan.java
  12. 11 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ContentDTO.java
  13. 15 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ContentFile.java
  14. 14 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/Parties.java
  15. 40 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ZhiYuanDTO.java
  16. 38 0
      mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ZhiYuanVO.java
  17. 694 0
      mjava-mankalong/src/main/java/com/malk/mankalong/service/Impl/PayServiceImpl.java
  18. 14 0
      mjava-mankalong/src/main/java/com/malk/mankalong/service/PayService.java
  19. 61 0
      mjava-mankalong/src/main/resources/application-dev.yml
  20. 49 0
      mjava-mankalong/src/main/resources/application-prod.yml
  21. 152 0
      mjava-mankalong/src/main/resources/json/form.json
  22. 26 0
      mjava-mankalong/src/main/resources/json/formtest.json
  23. 168 0
      mjava-mankalong/src/test/java/test.java
  24. 39 0
      mjava-mankalong/src/test/resource/server.sh

+ 33 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/Boot.java

@@ -0,0 +1,33 @@
+package com.malk.mankalong;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+
+import javax.persistence.EntityManager;
+
+/**
+ * corp项目: 扫描公共模块
+ * -
+ * 若是无需数据库模块, 配置无效地址也可启动, 引入mjava不支持直接 @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) 配置
+ * 需要配置 jpa.hibernate.ddl-auto 为 none. 标识对表没有任何操作. 若不设置为 none, flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+ */
+@EnableJpaAuditing
+@SpringBootApplication(scanBasePackages = {"com.malk"},exclude={DataSourceAutoConfiguration.class})
+public class Boot {
+
+    public static void main(String... args) {
+        SpringApplication.run(Boot.class, args);
+    }
+
+    /**
+     * 让Spring管理JPAQueryFactory [不使用Qualifier详见mjava-Boot]
+     */
+    @Bean
+    public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+        return new JPAQueryFactory(entityManager);
+    }
+}

+ 77 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/common/Result.java

@@ -0,0 +1,77 @@
+package com.malk.mankalong.common;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 统一响应结构
+ *
+ * @param <T> 响应数据泛型
+ * @author malk
+ */
+@Data
+public class Result<T> implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 状态码,"200" 表示正常 */
+    private String code;
+
+    /** 响应消息 */
+    private String message;
+
+    /** 响应数据 */
+    private T data;
+
+    public Result() {
+    }
+
+    public Result(String code, String message, T data) {
+        this.code = code;
+        this.message = message;
+        this.data = data;
+    }
+
+    /**
+     * 成功响应(无数据)
+     */
+    public static <T> Result<T> success() {
+        return new Result<>("200", "操作成功", null);
+    }
+
+    /**
+     * 成功响应(带数据)
+     */
+    public static <T> Result<T> success(T data) {
+        return new Result<>("200", "操作成功", data);
+    }
+
+    /**
+     * 成功响应(自定义消息)
+     */
+    public static <T> Result<T> success(String message, T data) {
+        return new Result<>("200", message, data);
+    }
+
+    /**
+     * 失败响应
+     */
+    public static <T> Result<T> error(String message) {
+        return new Result<>("500", message, null);
+    }
+
+    /**
+     * 失败响应(自定义code)
+     */
+    public static <T> Result<T> error(String code, String message) {
+        return new Result<>(code, message, null);
+    }
+
+    /**
+     * 授权失败响应
+     */
+    public static <T> Result<T> authError() {
+        return new Result<>("500", "授权检验失败:Authorization 不正确", null);
+    }
+}

+ 22 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/controller/DDController.java

@@ -0,0 +1,22 @@
+package com.malk.mankalong.controller;
+
+import com.malk.controller.DDCallbackController;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 钉钉事件回调 3_1
+ * -
+ * [子项目直接继承即可有调用, 无需实现]
+ * -
+ * 注解 @RequestMapping 路径不能重复 [主子项目属同一个项目];
+ * 获取项目回调请求地址, https://mc.cloudpure.cn/frp/xxx/dd/callback [调试代理: frp + nginx]
+ */
+@Slf4j
+@RestController
+@RequestMapping("/dd")
+public class DDController extends DDCallbackController {
+
+
+}

+ 54 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/controller/DLController.java

@@ -0,0 +1,54 @@
+package com.malk.mankalong.controller;
+
+/**
+ * 错误抛出与拦截详见 CatchException
+ */
+
+import com.malk.mankalong.entity.Content.ZhiYuanDTO;
+import com.malk.mankalong.service.PayService;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+@Slf4j
+@RestController
+@RequestMapping
+public class DLController {
+
+    @Autowired
+    private YDService ydService;
+    @Autowired
+    private YDClient ydClient;
+    @Autowired
+    private PayService payService;
+
+    @PostMapping(value = "test")
+    McR testToken() {
+        return McR.success();
+    }
+
+    @PostMapping(value = "createContract")
+    McR testGet(@RequestBody Map data){
+//        payService.testupload();
+        return McR.success();
+//        return McR.success();
+    }
+
+    @PostMapping(value = "startProcess")
+    McR startProcess(@RequestBody Map data){
+        String stringObjectMap = payService.startProcess(data);
+//        payService.testupload();
+        return McR.success(stringObjectMap);
+//        return McR.success();
+    }
+
+    @PostMapping(value = "createSubjectInfo")
+    McR createSubjectInfo(@RequestBody Map data){
+        return payService.createSubjectInfo(data);
+    }
+}

+ 69 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/delegate/DDDelegate.java

@@ -0,0 +1,69 @@
+package com.malk.mankalong.delegate;
+
+import com.malk.mankalong.service.PayService;
+import com.malk.delegate.DDEvent;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+/**
+ * OA审批事件 [主项目也有实现, 添加 @Primary 优先注入主项目实现]
+ * -
+ * 取消方案: 撤销和拒绝流程不继续执行连接器, 因此不使用连接器与轮询审批记录方案 [低效而且占用较高钉钉api调次数];
+ * 优化方案: 通过事件订阅实现实时同步所有审批状态, 定时查询钉钉回调失败记录 [配置钉钉事件Delegate, 添加定时任务]
+ */
+@Slf4j
+@Service
+@Primary
+public class DDDelegate implements DDEvent {
+
+    private static final String PAYMENT_CONTRACT = "PROC-DAB53435-D2A5-467F-910E-8AEEEFC4B0EA";
+    private static final String INCOME_CONTRACT = "PROC-8BD93A79-5907-4D59-82C7-F75AE6A79419";
+
+    @Autowired
+    PayService payService;
+    // 审批任务回调执行业务逻辑
+    @Async
+    @Override
+    public void executeEvent_Task_Finish(String processInstanceId, String processCode, boolean isAgree, String remark) {
+        log.info("executeEvent_Task_Finish");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Task_Start(String processInstanceId, String processCode) {
+        log.info("executeEvent_Task_Start");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Task_Redirect(String processInstanceId, String processCode) {
+        log.info("executeEvent_Task_Redirect");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Instance_Start(String processInstanceId, String processCode) {
+        log.info("executeEvent_Instance_Start");
+    }
+
+
+    // 审批实例回调执行业务逻辑
+    @Async
+    @Override
+    public void executeEvent_Instance_Finish(String processInstanceId, String processCode, boolean isAgree, boolean isTerminate, String staffId) {
+        log.info("executeEvent_Instance_Finish");
+        String approveResult = isAgree ? "agree" : "refuse";
+//        if (isTerminate) approveResult = "terminated";
+        if  (isAgree){
+            if (processCode.equals(PAYMENT_CONTRACT)){
+
+            } else if (processCode.equals(INCOME_CONTRACT)) {
+
+            }
+        }
+        log.info("审批实例回调执行业务逻辑, {}", approveResult);
+    }
+}

+ 63 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Income/fct_ar.java

@@ -0,0 +1,63 @@
+package com.malk.mankalong.entity.BIP.Income;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class fct_ar implements Serializable {
+    private static final long serialVersionUID = -8311118627395331518L;
+    private String actualinvalidate;	//否	实际终止日期
+    private String actualvalidate;	//否	实际生效日期
+    private String billmaker;	//否	制单人
+    private String blatest;	//否	是否最新版本
+    private String btriatradeflag;	//否	三角贸易
+    private String cbilltypecode;	//否	单据类型
+    private String ccurrencyid;	//否	本位币
+    private String corigcurrencyid;	//是	币种
+    private String cprojectid;	//否	项目
+    private String ctname;	//是	合同名称
+    private String ctrantypeid;	//否	合同类型
+    private String dbilldate;	//否	单据日期
+    private String dmakedate;	//否	制单日期
+    private String fstatusflag;	//否	合同状态
+    private String invallidate;	//否	计划终止日期
+    private String nexchangerate;	//是	折本汇率
+    private String nglobalexchgrate;	//否	全局本位币汇率
+    private String ngroupexchgrate;	//否	集团本位币汇率
+    private String norigcopamount;	//否	累计原币开票金额
+    private String norigplanamount;	//否	累计原币预收款金额
+    private String norigpshamount;	//否	累计原币收款金额
+    private String ntotalastnum;	//否	总数量
+    private String ntotalcopamount;	//否	累计本币开票金额
+    private String ntotalgpamount;	//否	累计本币收款金额
+    private String ntotalorigmny;	//是	原币价税合计
+    private String ntotaltaxmny;	//否	本币价税合计
+    private String organizer;	//是	承办组织
+    private String overrate;	//是	超合同收款比例
+    private String pk_customer; //	是	客户(传统一社会信用代码)
+    private String pk_fct_ar;	//否	收款合同主键
+    private String pk_group;	//否	集团
+    private String pk_org;	//是	财务组织
+    private String pk_org_v;	//否	财务组织版本
+    private String pk_payterm;	//否	收款协议
+    private String subscribedate;	//是	签字盖章日期
+    private String valdate;	//是	计划生效日期
+    private String vbillcode;	//是	合同编码
+    private String version;	//否	版本号
+    private String vtrantypecode;	//是	合同类型编码
+    private String openct;	//是	敞口合同
+    private String mountcalculation;	//否	计算
+    private String earlysign;	//否	期初标志
+    private String signorg;	//否	签字组织
+    private String Vallidate;	//是	计划终止日期
+    private String pk_ratetype;	//否	组织汇率类型
+    private String ratedate;	//否	组织汇率来源日期
+    private String personnelid;	//是	承办人员
+    private String depid;	//是	承办部门
+    private String bankaccount;	//是	本方银行账号
+    private List<fct_ar_b> fct_ar_b;//	否	Array	合同基本
+    private List<fct_ar_plan> fct_ar_plan; //收款计划
+
+}

+ 12 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Income/fct_ar_b.java

@@ -0,0 +1,12 @@
+package com.malk.mankalong.entity.BIP.Income;
+
+import lombok.Data;
+
+@Data
+public class fct_ar_b {
+    private String crowno;	//是	行号
+    private String inoutcome;	//否	收支项目
+    private String norigtaxmny;	//是	累计原币价税金额
+    private String ntaxmny;	//是	累计本币价税金额
+    private String pk_financeorg;	//是	财务组织
+}

+ 17 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Income/fct_ar_plan.java

@@ -0,0 +1,17 @@
+package com.malk.mankalong.entity.BIP.Income;
+
+import lombok.Data;
+
+@Data
+public class fct_ar_plan {
+   private String planrate;	//是	计划比例
+   private String begindate;	//是	起算日期
+   private String accountdate;	//是	账期天数
+   private String accountnum;	//是	账期号
+   private String enddate;	//是	计划到期日
+   private String planmoney;	//是	计划金额
+   private String receivetype;	//是	预收款
+   private String moneytype;	//是	收支项目
+   private String reymontype;	//是	收款类型
+   private String pk_financeorg;	//是	财务组织
+}

+ 59 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Payment/fct_ap.java

@@ -0,0 +1,59 @@
+package com.malk.mankalong.entity.BIP.Payment;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class fct_ap {
+    private String actualinvalidate;	//否	实际终止日期
+    private String actualvalidate;	//否	实际生效日期
+    private String billmaker;	//否	制单人
+    private String blatest;	//否	是否最新版本
+    private String btriatradeflag;	//否	三角贸易
+    private String cbilltypecode;	//否	单据类型
+    private String ccurrencyid;	//否	本位币
+    private String corigcurrencyid;	//是	币种
+    private String cprojectid;	//否	项目
+    private String ctname;	//是	合同名称
+    private String ctrantypeid;	//否	合同类型
+    private String dbilldate;	//否	单据日期
+    private String dmakedate;	//否	制单日期
+    private String fstatusflag;	//否	合同状态
+    private String nexchangerate;	//是	折本汇率
+    private String nglobalexchgrate;	//否	全局本位币汇率
+    private String ngroupexchgrate;	//否	集团本位币汇率
+    private String norigcopamount;	//否	累计原币开票金额
+    private String ntotalastnum;	//否	总数量
+    private String ntotalcopamount;	//否	累计本币开票金额
+    private String ntotalorigmny;	//是	原币价税合计
+    private String ntotaltaxmny;	//否	本币价税合计
+    private String organizer;	//是	承办组织
+    private String overrate;	//是	超合同收款比例
+    private String cvendorid;	//是	供应商(传统一社会信用代码)
+    private String pk_group;	//否	集团
+    private String pk_org;	//是	财务组织
+    private String pk_org_v;	//否	财务组织版本
+    private String pk_payterm;	//否	付款协议
+    private String subscribedate;	//是	签字盖章日期
+    private String valdate;	//是	计划生效日期
+    private String vbillcode;	//否	合同编码
+    private String version;	//否	版本号
+    private String vtrantypecode;	//是	合同类型编码
+    private String paymontype;	//是	付款类型
+    private String openct;	//是	敞口合同
+    private String mountcalculation;	//否	计算
+    private String earlysign;	//否	期初标志
+    private String invallidate;	//是	计划终止日期
+    private String signorg;	//是	签约组织
+    private String pk_ratetype;	//否	组织汇率类型
+    private String ratedate;	//否	组织汇率来源日期
+    private String vdef30;	//是	签约供应商
+    private String personnelid;	//是	承办人员
+    private String depid;	//是	承办部门
+    private String ourbankaccount;	//是	本方银行账号
+    private String bankaccount;	//是	收款银行账号
+    private String ctaxcodeid;	//是	税目
+    private List<fct_ap_b> fct_ap_b;	 //否	合同基本
+    private List<fct_ap_plan> fct_ap_plan;	//否	付款计划
+}

+ 12 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Payment/fct_ap_b.java

@@ -0,0 +1,12 @@
+package com.malk.mankalong.entity.BIP.Payment;
+
+public class fct_ap_b {
+    private String pk_financeorg;	//是	财务组织
+    private String crowno;	//是	行号
+    private String inoutcome;	//否	收支项目
+    private String norigtaxmny;	//是	累计原币价税金额
+    private String ntaxmny;	//是	累计本币价税金额
+    private String ntax;	//是	税额
+    private String norigtax;	//是	原币税额
+    private String norigmny;	//是	无税金额
+}

+ 13 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/BIP/Payment/fct_ap_plan.java

@@ -0,0 +1,13 @@
+package com.malk.mankalong.entity.BIP.Payment;
+
+public class fct_ap_plan {
+    private String pk_financeorg;	//是	财务组织
+    private String planrate;	//是	计划比例
+    private String begindate;	//是	起算日期
+    private String accountdate;	//是	账期
+    private String enddate;	//是	计划到期日
+    private String planmoney;	//是	计划金额
+    private String paytype;	//是	预付款
+    private String moneytype;	//是	收支项目
+    private String accountnum;	//是	账期号
+}

+ 11 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ContentDTO.java

@@ -0,0 +1,11 @@
+package com.malk.mankalong.entity.Content;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class ContentDTO implements Serializable {
+    private static final long serialVersionUID = -8311118627395331518L;
+    private ZhiYuanVO ImportContractInfoRequest;//钉盘空间id
+}

+ 15 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ContentFile.java

@@ -0,0 +1,15 @@
+package com.malk.mankalong.entity.Content;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class ContentFile implements Serializable {
+    private static final long serialVersionUID = -8311118627395331518L;
+    private String spaceId;//钉盘空间id
+    private String fileId;//钉盘文件id
+    private String fileName;//文件名
+    private String fileType;//文件种类
+    private String fileSize;//文件大小
+}

+ 14 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/Parties.java

@@ -0,0 +1,14 @@
+package com.malk.mankalong.entity.Content;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class Parties implements Serializable {
+    private static final long serialVersionUID = 4820142670157009063L;
+    private String name;//主体名称
+    private String responsiblePerson;//负责人
+
+
+}

+ 40 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ZhiYuanDTO.java

@@ -0,0 +1,40 @@
+package com.malk.mankalong.entity.Content;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+@Data
+public class ZhiYuanDTO implements Serializable {
+    private static final long serialVersionUID = 4820142670157009063L;
+//    @NotBlank
+//    private String contractId;//合同编号
+    @NotBlank
+    private String contractName;//合同名称
+    @NotBlank
+    private String downloadUrl;//文件下载地址
+    @NotBlank
+    private String type;//文件下载地址
+//    @NotBlank
+//    private String amountType;//金额类型
+//    @NotBlank
+//    private String ownerStaffId;//所属人工号
+//    @NotBlank
+//    private String amount;//金额
+//    @NotBlank
+//    private String signTime;//签署时间Unix毫秒级时间戳
+//    @NotBlank
+//    private String ownerDeptNo;//所属人部门编号
+//    private String ownerDeptName;//所属人部门名称
+//    @NotBlank
+//    private String effectiveStatus;//履约状态
+//    @NotBlank
+//    private String startDate;//Unix毫秒级时间戳
+//    @NotBlank
+//    private String endDate;//Unix毫秒级时间戳
+//    private List<Parties> ourParties;//我方主体
+//    private List<Parties> otherParties;//他方主体
+
+
+}

+ 38 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/entity/Content/ZhiYuanVO.java

@@ -0,0 +1,38 @@
+package com.malk.mankalong.entity.Content;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class ZhiYuanVO implements Serializable {
+    private static final long serialVersionUID = 4820142670157009063L;
+    @NotBlank
+    private String contractId;//合同编号
+    @NotBlank
+    private String contractName;//合同名称
+    @NotBlank
+    private String amountType;//金额类型
+    @NotBlank
+    private String ownerStaffId;//所属人工号
+    @NotBlank
+    private String amount;//金额
+    @NotBlank
+    private Long signTime;//签署时间Unix毫秒级时间戳
+    @NotBlank
+    private String ownerDeptNo;//所属人部门编号
+    private String ownerDeptName;//所属人部门名称
+    @NotBlank
+    private String effectiveStatus;//履约状态
+    @NotBlank
+    private String startDate;//Unix毫秒级时间戳
+    @NotBlank
+    private String endDate;//Unix毫秒级时间戳
+    private List<String> ourParties;//我方主体
+    private List<String> otherParties;//他方主体
+    private List<String> contentFiles;//他方主体
+
+
+}

+ 694 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/service/Impl/PayServiceImpl.java

@@ -0,0 +1,694 @@
+package com.malk.mankalong.service.Impl;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.mankalong.service.PayService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McR;
+import com.malk.server.dingtalk.DDConf;
+import com.malk.server.dingtalk.DDR_New;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Personnel;
+import com.malk.service.dingtalk.DDClient_Workflow;
+import com.malk.service.dingtalk.DDService;
+import com.malk.utils.UtilFile;
+import com.malk.utils.UtilHttp;
+import com.malk.utils.UtilMap;
+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 java.io.*;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Service
+@Slf4j
+public class PayServiceImpl implements PayService {
+
+    @Autowired
+    private DDClient ddClient;
+    @Autowired
+    private DDClient_Workflow ddClient_workflow;
+    @Autowired
+    private DDClient_Personnel ddClientPersonnel;
+    @Value(value = "${dingtalk.appKey}")
+    private String APP_EKY;
+    @Value(value = "${dingtalk.appSecret}")
+    private String APP_SECRET;
+    @Value(value = "${dingtalk.agentId}")
+    private Long agentId;
+    @Value(value = "${dingtalk.unionId}")
+    private String unionId;
+    @Value(value = "${dingtalk.spaceId}")
+    private String spaceId;
+    @Value(value = "${dingtalk.parentId}")
+    private String parentId;
+    @Value(value = "${saveFile.path}")
+    private String saveFilePath;
+    @Value(value = "${dingtalk.parentUuid}")
+    private String parentDentryUuid;
+    @Value("${aliwork.appType}")
+    private String appType;
+    @Value("${aliwork.systemToken}")
+    private String systemToken;
+    @Autowired
+    private DDConf ddConf;
+    @Autowired
+    DDService ddService;
+    @Autowired
+    private YDService ydService;
+    @Autowired
+    private YDClient ydClient;
+
+    private static final String API_TOKEN = "/common/unAuth/tokens/generate";
+    private static final String POST_DATA_URL = "/common/document";
+    private static final String FIND_BY_CODES = "/common/users/v2/findByCodes";
+    private static final String FIND_COMPANY = "/common/departments/v2/findByCode";
+    private ConcurrentHashMap<String, LocalDateTime> tokenStore = new ConcurrentHashMap<>();
+    //出差类型枚举
+    private static final Map<String, String> AMOUNT_TYPE = new HashMap<>();
+
+    static {
+        AMOUNT_TYPE.put("收款", "收入");
+        AMOUNT_TYPE.put("付款", "支出");
+        AMOUNT_TYPE.put("不结算", "无金额");
+        AMOUNT_TYPE.put("收支双向", "无金额");
+    }
+    private static final Map<String, String> ATTACHMENT_ENUM = new HashMap<>();
+    static {
+        ATTACHMENT_ENUM.put("attachmentUrl","附件");
+        ATTACHMENT_ENUM.put("contractTextUrl","合同正文");
+        ATTACHMENT_ENUM.put("contractScanUrl","上传生效的合同扫描件");
+        ATTACHMENT_ENUM.put("contractPreApprovalFlow","合同前置审批流程");
+        ATTACHMENT_ENUM.put("procurementResult","oa请示、采购结果");
+        ATTACHMENT_ENUM.put("decisionDocument","决策文件、会议纪要、中标通知书等");
+    }
+    //所有的枚举
+    private static final Map<String, String> ALLENUM = new HashMap<>();
+    static {
+        //签署法人实体
+        ALLENUM.put("option_aoscience_bio_nantong_co_l__c", "澳斯康生物(南通)股份有限公司");
+        ALLENUM.put("option_gansu_jianshun_biotech_co__c", "甘肃健顺生物科技有限公司");
+        ALLENUM.put("option_jianshun_bio_tech_nantong__c", "健顺生物科技(南通)有限公司");
+        ALLENUM.put("option_shanghai_aoskang_bio_pharm__c", "上海澳斯康生物制药有限公司");
+    }
+
+    /**
+     * 从Content-Disposition头获取文件名
+     */
+    private static String getFileNameFromConnection(HttpURLConnection connection) {
+        String contentDisposition = connection.getHeaderField("Content-Disposition");
+        if (contentDisposition != null) {
+            // 查找filename=后面的内容
+            String[] parts = contentDisposition.split(";");
+            for (String part : parts) {
+                if (part.trim().startsWith("filename=")) {
+                    String fileName = part.substring(part.indexOf('=') + 1).trim();
+                    // 去除引号并解码URL编码
+                    fileName = fileName.replace("\"", "");
+                    try {
+                        return URLDecoder.decode(fileName, StandardCharsets.UTF_8.name());
+                    } catch (UnsupportedEncodingException e) {
+                        return fileName;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    //下载宜搭附件
+    private String downloadFile(String fileURL, String contractName, String type, String savePath) throws IOException {
+        //若是宜搭附件url 则需获得附件临时免登地址
+//        fileURL = ydClient.convertTemporaryUrl(fileURL);
+
+        URL url = new URL(fileURL);
+        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
+        httpConn.setRequestMethod("GET");
+        httpConn.setInstanceFollowRedirects(true); // 强制跟随重定向(必加!)
+        httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
+        httpConn.setConnectTimeout(10000);
+        httpConn.setReadTimeout(20000);
+        httpConn.setDoInput(true);
+        httpConn.setDoOutput(false);
+        int responseCode = httpConn.getResponseCode();
+
+        // 获取文件名
+//        String fileName = getFileNameFromConnection(httpConn);
+        String fileName = contractName + "." + type;
+        // 检查HTTP响应代码是否为200
+        if (responseCode == HttpURLConnection.HTTP_OK) {
+            InputStream inputStream = httpConn.getInputStream();
+            FileOutputStream outputStream = new FileOutputStream(savePath + fileName);
+
+            byte[] buffer = new byte[8192];
+            int bytesRead = -1;
+
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+
+            outputStream.close();
+            inputStream.close();
+        } else {
+            System.out.println("无法下载文件。HTTP响应代码: " + responseCode);
+        }
+        httpConn.disconnect();
+        return fileName;
+    }
+
+    /**
+     * 上传文件至钉盘
+     * @param filePath 文件存储地址
+     * @param conflictStrategy 覆盖或其他上传方式
+     * @return
+     */
+    private Map uploadToDingTalk(String filePath,String conflictStrategy) {
+        //获取当前时间戳
+        long beginTimestamp = System.currentTimeMillis();
+        System.out.println("开始上传附件:" + DateUtil.format(new Date(beginTimestamp), "yyyy-MM-dd HH:mm:ss"));
+
+        //文件
+        File file = new File(filePath);
+
+        //获取文件上传信息
+        Map param = new HashMap();
+        param.put("unionId",unionId);
+        Map body = new HashMap();
+        body.put("protocol","HEADER_SIGNATURE");
+        body.put("multipart",false);
+
+        DDR_New ddr = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v1.0/storage/spaces/" + spaceId + "/files/uploadInfos/query", ddConf.initTokenHeader(ddClient.getAccessToken()), param, body, DDR_New.class);
+        String uploadKey = ddr.getUploadKey();
+        Map headerSignatureInfo = ddr.getHeaderSignatureInfo();
+        Map<String,String> headers = (Map<String,String>) headerSignatureInfo.get("headers");
+        List<String> resourceUrls = (List<String>) headerSignatureInfo.get("resourceUrls");
+        String resourceUrl = resourceUrls.get(0);
+
+        Map dentry = new HashMap();
+        //使用OSS的header加签方式上传文件
+        try {
+            URL url = new URL(resourceUrl);
+            HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+            if (headers != null) {
+                for (Map.Entry<String, String> entry : headers.entrySet()) {
+                    connection.setRequestProperty(entry.getKey(), entry.getValue());
+                }
+            }
+            connection.setDoOutput(true);
+            connection.setRequestMethod("PUT");
+            connection.setUseCaches(false);
+            connection.setReadTimeout(10000);
+            connection.setConnectTimeout(10000);
+            connection.connect();
+            OutputStream out = connection.getOutputStream();
+            InputStream is = new FileInputStream(file);
+            byte[] b =new byte[1024];
+            int temp;
+            while ((temp=is.read(b))!=-1){
+                out.write(b,0,temp);
+            }
+            out.flush();
+            out.close();
+            int responseCode = connection.getResponseCode();
+            connection.disconnect();
+            if (responseCode == 200) {
+                System.out.println("上传成功");
+            } else {
+                System.out.println("上传失败");
+            }
+            //提交文件
+            Map body2 = new HashMap();
+            Map option = new HashMap();
+            option.put("conflictStrategy",conflictStrategy);
+            body2.put("uploadKey",uploadKey);
+            body2.put("name",file.getName());
+            body2.put("option",option);
+            DDR_New ddrNew = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v2.0/storage/spaces/files/"+parentDentryUuid+"/commit", ddClient.initTokenHeader(), param, body2, DDR_New.class);
+            dentry = ddrNew.getDentry();
+
+        }catch (IOException e){
+            log.info("上传文件异常:{}",e);
+        }
+
+        long endTimestamp = System.currentTimeMillis();
+        System.out.println("上传文件结束:" + DateUtil.format(new Date(endTimestamp), "yyyy-MM-dd HH:mm:ss"));
+        System.out.println("上传文件耗时:" + (endTimestamp - beginTimestamp)/1000.0 + "s");
+        return dentry;
+    }
+
+    private Map<String, Object> convert(Object object) throws Exception {
+        Map<String, Object> map = new HashMap<>();
+        Class<?> clazz = object.getClass();
+        for (Field field : clazz.getDeclaredFields()) {
+            field.setAccessible(true);
+            String value = field.get(object) != null ? field.get(object).toString() : "";
+            map.put(field.getName(), value);
+        }
+        return map;
+    }
+
+    /**
+     * 获取钉钉员工手机号
+     * @param workingEmployeeIds 钉钉人员id
+     * @return
+     */
+    public List<String> getDeptIdByUserId(List<String> workingEmployeeIds) {
+        log.info("根据钉钉人员id获取员工部门id:{}",workingEmployeeIds.toString());
+        List<String> filterList = new ArrayList<>();
+        filterList.add("sys00-mainDeptId");
+        List<Map> employeeInfos = ddClientPersonnel.getEmployeeInfos(ddClient.getAccessToken(), workingEmployeeIds, agentId, filterList);
+        List<String> personList = new ArrayList<>();
+        employeeInfos.forEach(e -> {
+            List<Map> mapList = (List<Map>) e.get("field_data_list");
+            mapList.forEach(m -> {
+                List<Map> valueList = (List<Map>) m.get("field_value_list");
+                String value = valueList.get(0).get("value").toString();
+                personList.add(value);
+            });
+        });
+        return personList;
+    }
+
+    private Map MATE;
+
+    /**
+     * 加载json
+     */
+    private Map _getMeta() {
+        if (ObjectUtil.isNull(MATE)) {
+            MATE = (Map) UtilFile.readJsonObjectFromResource("json/form.json"); // 本地匹配宜搭组件ID
+//            MATE = (Map) UtilFile.readJsonObjectFromResource("static/json/formtest.json"); // 本地匹配宜搭组件ID
+        }
+        return MATE;
+    }
+    /**
+     * 整合传参数据为OA审批 name - value 数据格式
+     * @param code 单据类型
+     * @param data 传参
+     * @param meta json
+     * @param formValue OA审批数据格式
+     */
+    private void IntegrationData(String code, Map data, Map meta, List<Map> formValue) {
+        log.info("开始处理接口参数数据转为OA审批接口数据格式");
+        //json数据列
+        Map<String, ?> component = (Map) ((Map) meta.get(code)).get("compIds");
+        for (String key : component.keySet()) {
+            Map formData = UtilMap.empty();
+            if (key.startsWith("tableField_")) {
+                String[] split = key.split("_");
+                List<Map> rows = UtilMap.getList(data,split[1]);
+                List<List<Map>> lastList = new ArrayList<>();
+                Map<String, String> compIds = (Map) component.get(key);
+                if (rows.size() > 0 ){
+                    for (Map row : rows) {
+                        List<Map> details = new ArrayList<>();
+                        for (String prop : compIds.keySet()) {
+                            Map detail = UtilMap.empty();
+                            detail.put("value", row.get(compIds.get(prop)));
+                            detail.put("name", prop);
+                            if (prop.contains("我方主体名称")){
+                                detail.put("bizAlias","contract_mine_company_name");
+                            } else if (prop.contains("对方主体名称")) {
+                                detail.put("bizAlias","contract_opposite_company_name");
+                            }
+                            details.add(detail);
+                        }
+                        lastList.add(details);
+                    }
+                    formData.put( "value", JSON.toJSONString(lastList));
+                    formData.put( "name",((Map) meta.get(code)).get(split[1]).toString());
+                }else {
+                    List<Map> details = new ArrayList<>();
+                    for (String prop : compIds.keySet()) {
+                        Map detail = UtilMap.empty();
+                        if ("quantity".equals(compIds.get(prop))){
+                            detail.put("value", "0");
+                            detail.put("name", prop);
+                        }else {
+                            detail.put("value", "无");
+                            detail.put("name", prop);
+                        }
+                        details.add(detail);
+                    }
+                    lastList.add(details);
+                    formData.put( "value", JSON.toJSONString(lastList));
+                    formData.put( "name",((Map) meta.get(code)).get(split[1]).toString());
+                }
+            } else {
+                if (data.containsKey(component.get(key))){
+                    if (ObjectUtil.isNotNull(data.get(component.get(key)))){
+                        Object value = data.get(component.get(key));
+                        formData.put("name", key);
+                        formData.put("value",value.toString());
+                        if ("RelatedReceipt".equals(component.get(key))){
+                            List<String> ids = new ArrayList<>();
+                            ids.add(value.toString());
+                            formData.put("name", key);
+                            formData.put("value",JSON.toJSONString(ids));
+                        }
+                        if (ALLENUM.containsKey(value.toString())){
+                            formData.put("value",ALLENUM.get(value.toString()));
+                        }
+
+                    }
+                }
+            }
+            if (formData.size()>0){
+                formValue.add(formData);
+            }
+        }
+        final String[] token = {""};
+        final boolean[] isHave = {false};
+        ATTACHMENT_ENUM.forEach((k,v)->{
+            if (data.containsKey(k) && hasValid(data,k)){
+                log.info("开始处理附件上传");
+                List<Map> attachment = (List<Map>) data.get(k);
+                List<Map<String, Object>> resultList = new ArrayList<>();
+                attachment.forEach(e->{
+                    String[] split = UtilMap.getString(e, "name").split("\\.");
+                    String fileName = split[0];
+                    if (split.length > 2){
+                        for (int i = 1; i < split.length -1; i++) {
+                            fileName = fileName + "." + split[i];
+                        }
+                    }
+                    String fileType = split[split.length-1];
+                    Map map = ddService.uploadFileFormUrlForOverflow(ddClient.getAccessToken(), "603864663125953014", e.get("downloadUrl").toString() + "?token=" + token[0], fileName, fileType);
+//                    Map map = ddService.uploadFileFormUrlForOverflow(ddClient.getAccessToken(), data.get(((Map) meta.get(code)).get("creator")).toString(), e.get("downloadUrl").toString() + "?token=" + token[0], fileName, fileType);
+                    Map<String, Object> result = UtilMap.map("spaceId, fileName, fileSize, fileType, fileId", UtilMap.getString(map, "spaceId"), fileName,
+                            UtilMap.getString(map, "size"), UtilMap.getString(map, "extension"), UtilMap.getString(map, "id"));
+                    resultList.add(result);
+                });
+                formValue.add(UtilMap.map("name, value",v,JSON.toJSONString(resultList)));
+            }
+        });
+
+    }
+    /**
+     * 整合传参及OA数据格式
+     * @param code 单据类型
+     * @param data 传参
+     * @return 流程实例id
+     */
+    private String dataProcessing(String code, Map data){
+        //加载json映射
+        Map meta = _getMeta();
+        //表单字段映射
+        List<Map> formValue = new ArrayList<>();
+        log.info("code:{} ",code);
+        IntegrationData(code, data, meta, formValue);
+        List<String> workingEmployeeIds = new ArrayList<>();
+        workingEmployeeIds.add(data.get(((Map) meta.get(code)).get("creator")).toString());
+        List<String> deptIdByUserId = getDeptIdByUserId(workingEmployeeIds);
+        if (code.startsWith("HTSPD")){
+            formValue.add(UtilMap.map("name, value","发起部门",deptIdByUserId.get(0)));
+            formValue.add(UtilMap.map("name, value","合同编号生成方式, 选择已有合同编号"));
+//            formValue.add(UtilMap.map("name, value","合同编号规则, 测试合同编号"));
+            return ddClient_workflow.doProcessInstancesNew(ddClient.getAccessToken(), data.get(((Map) meta.get(code)).get("creator")).toString(),((Map) meta.get(code)).get("processCode").toString(), formValue, deptIdByUserId.get(0));
+//            return ddClient_workflow.doProcessInstancesNew(ddClient.getAccessToken(), data.get(((Map) meta.get(code)).get("creator")).toString(), "PROC-B5E48D42-87FA-4C4E-9CD8-9178EEF1F0D3", formValue, deptIdByUserId.get(0));
+        }
+        return ddClient_workflow.doProcessInstancesNew(ddClient.getAccessToken(), data.get(((Map) meta.get(code)).get("creator")).toString(), ((Map) meta.get(code)).get("processCode").toString(), formValue, deptIdByUserId.get(0));
+//        return code;
+    }
+
+    /**
+     * 发起流程审批
+     * @param code
+     * @param data
+     * @return 流程实例id和地址
+     */
+    @Override
+    public Map<String, Object> startProcess(String code, Map data) {
+        String instanceId = dataProcessing(code, data);
+        JSONObject jsonObject = JSONObject.parseObject(instanceId);
+        if (!ObjectUtil.isNotNull(jsonObject.get("instanceId"))){
+            return UtilMap.map("ddProcessId, dtUrl, reqMsg",  jsonObject.get("instanceId"), "error", instanceId);
+        }
+        String url = "https://applink.dingtalk.com/approval/detail?corpId=ding226da4276814d290a1320dcb25e91351&instanceId=" + jsonObject.get("instanceId");
+        return UtilMap.map("ddProcessId, dtUrl, reqMsg",  jsonObject.get("instanceId"),  url, instanceId);
+    }
+
+    /**
+     * object附件判空
+     * @param data
+     * @param key
+     * @return
+     */
+    public boolean hasValid(Map data,String key) {
+
+        Object flowObj = data.get(key);
+        if (ObjectUtil.isNull(flowObj)) {
+            return false;
+        }
+        if (!(flowObj instanceof List)) {
+            return false;
+        }
+        List<?> flowList = (List<?>) flowObj;
+        if (flowList.isEmpty()) {
+            return false;
+        }
+        for (Object item : flowList) {
+            if (item instanceof Map) {
+                Map<?, ?> itemMap = (Map<?, ?>) item;
+                Object url = itemMap.get("downloadUrl");
+                if (url != null && !url.toString().trim().isEmpty()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String startProcess(Map data) {
+        Map formData = ydClient.queryData(YDParam.builder()
+                        .appType(appType)
+                        .systemToken(systemToken)
+                        .formInstanceId(UtilMap.getString(data,"formInstanceId"))
+                        .build(),
+                YDConf.FORM_QUERY.retrieve_id).getFormData();
+
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        //附件
+        String key = UtilMap.getString(data, "attachmentKey");
+        String value = UtilMap.getString(formData, key);
+
+        //写入OA审批的数据格式
+        List<Map> formValue = new ArrayList<>();
+
+        //处理宜搭附件绑定至OA审批
+        JSONArray jsonArray = JSONArray.parseArray(value);
+        jsonArray.forEach(e->{
+            JSONObject jsonObject = JSONObject.parseObject(e.toString());
+            String downloadUrl = jsonObject.getString("downloadUrl");
+
+            String fileFullName = jsonObject.getString("name");
+            String url = ydClient.convertTemporaryUrl(downloadUrl, appType, systemToken);
+
+            Map map = ddService.uploadFileFormUrlForOverflow(ddClient.getAccessToken(), "603864663125953014", url, fileFullName, fileFullName.split("\\.")[1]);
+            Map<String, Object> result = UtilMap.map("spaceId, fileName, fileSize, fileType, fileId", UtilMap.getString(map, "spaceId"), fileFullName,
+                    UtilMap.getString(map, "size"), UtilMap.getString(map, "extension"), UtilMap.getString(map, "id"));
+            resultList.add(result);
+        });
+        formValue.add(UtilMap.map("name, value","合同正文, " + JSON.toJSONString(resultList)));
+
+        //合同编号生成方式
+        formValue.add(UtilMap.map("name, value","合同编号生成方式, 手动填写"));
+        //印章类型
+        formValue.add(UtilMap.map("name, value","印章类型, 公章"));
+
+        //合同编号
+        key = UtilMap.getString(data, "codeKey");
+        value = UtilMap.getString(formData, key);
+        formValue.add(UtilMap.map("name, value","合同编号, 111111111111" + value));
+
+        //合同名称
+        key = UtilMap.getString(data, "nameKey");
+        value = UtilMap.getString(formData, key);
+        formValue.add(UtilMap.map("name, value","合同名称, " + value));
+
+        //金额类型
+        key = UtilMap.getString(data, "amountType");
+        value = UtilMap.getString(formData, key);
+        formValue.add(UtilMap.map("name, value","金额类型, " + AMOUNT_TYPE.get(value)));
+
+        //合同总额(元)
+        key = UtilMap.getString(data, "totalAmount");
+        value = UtilMap.getString(formData, key);
+        formValue.add(UtilMap.map("name, value","合同总额(元), " + value));
+
+        //固定合同期限类型
+        formValue.add(UtilMap.map("name, value","合同期限类型, 固定期限"));
+
+        //合同期限开始日期
+        key = UtilMap.getString(data, "startTime");
+        List list = UtilMap.getList(formData, key);
+        String startFormat = LocalDateTime.ofInstant(
+                Instant.ofEpochMilli(Long.parseLong(list.get(0).toString())),
+                ZoneId.of("Asia/Shanghai")
+        ).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        formValue.add(UtilMap.map("name, value","合同期限开始日期, " + startFormat));
+
+        //合同期限结束日期
+        String endFormat = LocalDateTime.ofInstant(
+                Instant.ofEpochMilli(Long.parseLong(list.get(1).toString())),
+                ZoneId.of("Asia/Shanghai")
+        ).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        formValue.add(UtilMap.map("name, value","合同期限结束日期, " + endFormat));
+
+        //签署方式
+        formValue.add(UtilMap.map("name, value","签署方式, 电子签署"));
+
+
+        if (data.containsKey("otherAttachment")){
+            //合同附件
+            key = UtilMap.getString(data, "otherAttachment");
+            value = UtilMap.getString(formData, key);
+            resultList.clear();
+
+            //处理宜搭附件绑定至OA审批
+            jsonArray = JSONArray.parseArray(value);
+            jsonArray.forEach(e->{
+                JSONObject jsonObject = JSONObject.parseObject(e.toString());
+                String downloadUrl = jsonObject.getString("downloadUrl");
+                String fileFullName = jsonObject.getString("name");
+                String url = ydClient.convertTemporaryUrl(downloadUrl, appType, systemToken);
+
+                Map map = ddService.uploadFileFormUrlForOverflow(ddClient.getAccessToken(), "603864663125953014", url, fileFullName, fileFullName.split("\\.")[1]);
+                Map<String, Object> result = UtilMap.map("spaceId, fileName, fileSize, fileType, fileId", UtilMap.getString(map, "spaceId"), fileFullName,
+                        UtilMap.getString(map, "size"), UtilMap.getString(map, "extension"), UtilMap.getString(map, "id"));
+                resultList.add(result);
+            });
+            formValue.add(UtilMap.map("name, value","合同附件, " + JSON.toJSONString(resultList)));
+        }
+
+        //我方主体
+        List<List<Map>> ourLastList = new ArrayList<>();
+        List<Map> ourDetails = new ArrayList<>();
+
+        key = UtilMap.getString(data, "ourDetail");
+        value = UtilMap.getString(formData, key);
+
+        Map ourDetail = UtilMap.empty();
+        ourDetail.put("value", value);
+        ourDetail.put("name", "我方主体名称");
+        ourDetail.put("bizAlias","contract_mine_company_name");
+
+        ourDetails.add(ourDetail);
+//        ourDetails.add(UtilMap.map("name, value", "我方负责人, 待补充"));
+        ourLastList.add(ourDetails);
+        formValue.add(UtilMap.map("name, value","我方信息",JSON.toJSONString(ourLastList)));
+
+        //他方主体
+        List<List<Map>> otherLastList = new ArrayList<>();
+        List<Map> otherDetails = new ArrayList<>();
+
+        key = UtilMap.getString(data, "otherDetail");
+        value = UtilMap.getString(formData, key);
+
+        Map otherDetail = UtilMap.empty();
+        otherDetail.put("value", value);
+        otherDetail.put("name", "对方主体名称");
+        otherDetail.put("bizAlias","contract_opposite_company_name");
+
+        otherDetails.add(otherDetail);
+//        otherDetails.add(UtilMap.map("name, value", "对方负责人, 待补充"));
+        otherLastList.add(otherDetails);
+        formValue.add(UtilMap.map("name, value","对方信息",JSON.toJSONString(otherLastList)));
+
+
+        List<String> workingEmployeeIds = new ArrayList<>();
+        workingEmployeeIds.add("603864663125953014");
+        List<String> deptIdByUserId = getDeptIdByUserId(workingEmployeeIds);
+
+        return ddClient_workflow.doProcessInstancesNew(ddClient.getAccessToken(), "603864663125953014","PROC-CCD914BE-E89B-4E4B-B5D3-9569BF26AE22", formValue, deptIdByUserId.get(0));
+    }
+
+
+    @Override
+    public McR createSubjectInfo(Map data) {
+
+        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                .appType(appType)
+                .systemToken(systemToken)
+                .formUuid("FORM-B7DBC8CA2A284FDC9F38E814CC043B17DIMN")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_mrlipwdt", "332624199910200042424")))
+//                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_mrlipwdt", UtilMap.getString(data,"creditCode"))))
+                .build());
+
+        if (!ObjectUtil.isNotNull(dataList) && dataList.size() == 0){
+            String url = "https://connector.dingtalk.com/webhook/subflow/6f842eadb97994cceaa04991";
+
+            String jsonBody = JSON.toJSONString(data);
+            log.info("发起HTTP请求 URL={}, 请求体={}", url, jsonBody);
+
+            try {
+                HttpResponse response = HttpRequest.post(url)
+                        .header("Content-Type", "application/json")
+                        .body(jsonBody)
+                        .execute();
+
+                String responseBody = response.body();
+                int status = response.getStatus();
+                log.info("HTTP响应 URL={}, status={}, 响应体={}", url, status, responseBody);
+
+                if (status == 200) {
+                    // 解析远端返回的统一响应结构
+                    return McR.success(responseBody);
+                } else {
+                    log.error("HTTP请求失败 URL={}, status={}, body={}", url, status, responseBody);
+                    return McR.error(String.valueOf(status),responseBody);
+                }
+            } catch (Exception e) {
+                log.error("HTTP请求异常 URL={}", url, e);
+                McR.errorParam("HTTP请求异常: " + e.getMessage());
+            }
+        }else {
+            dataList.forEach(e->{
+                String emp = UtilMap.getString(e, "employeeField_msczhgcx_id");
+                JSONArray jsonArray = JSONArray.parseArray(emp);
+                jsonArray.add(UtilMap.getString(data,"staffId"));
+//                creatorUserId
+                ydClient.operateData(YDParam.builder()
+                        .appType(appType)
+                        .systemToken(systemToken)
+                        .formInstanceId(UtilMap.getString(e, "formInstanceId"))
+                        .useLatestVersion(true)
+                        .updateFormDataJson(JSON.toJSONString(UtilMap.map("employeeField_msczhgcx", jsonArray)))
+                        .build(), YDConf.FORM_OPERATION.update);
+            });
+            try {
+                Thread.sleep(16000);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+            ydClient.operateData(YDParam.builder()
+                    .appType(appType)
+                    .systemToken(systemToken)
+                    .processInstanceId(UtilMap.getString(data, "formInstanceId"))
+                    .build(), YDConf.FORM_OPERATION.terminate);
+        }
+        return McR.success("该相对方已存在");
+    }
+
+}

+ 14 - 0
mjava-mankalong/src/main/java/com/malk/mankalong/service/PayService.java

@@ -0,0 +1,14 @@
+package com.malk.mankalong.service;
+
+import com.malk.server.common.McR;
+
+import java.util.Map;
+
+public interface PayService {
+
+    Map<String, Object> startProcess(String code, Map data);
+
+    String startProcess(Map data);
+
+    McR createSubjectInfo(Map data);
+}

+ 61 - 0
mjava-mankalong/src/main/resources/application-dev.yml

@@ -0,0 +1,61 @@
+# 环境配置
+server:
+  port: 8109
+  servlet:
+    context-path: /api/mankalong
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    hikari:
+      connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci           # SqlServer, Oracle 无需设置类型
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: test
+    password: test123
+    url: jdbc:mysql://47.110.74.198:3306?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    hibernate:
+      ddl-auto: none      # JPA对表没有任何操作
+    show-sql: true
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+# filepath
+#file:
+#  path:
+#    file: /Users/malk/server/_Tool/var/mjava/tmp/file/
+#    image: /Users/malk/server/_Tool/var/mjava/tmp/image/
+#    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
+#  source:
+#    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+#logging:
+#  file:
+#    path: /Users/malk/server/_Tool/var/mjava/log
+
+# dingtalk
+dingtalk:
+  agentId: 4787306953
+  appKey: dingjnogqdvdmtuhnviq
+  appSecret: 5_Un9HkATekf8BJk9iAKywggYFPkc5934U8qEiHPSx6E_s07ZM1_4a5TnAwQwUI3
+  corpId:
+  aesKey:
+  token:
+  unionId: ut05hb7w9kxwTKt7iSNabvgiEiE #测试unionid
+  spaceId: 851452912 #钉盘-团队文件-全员文件夹
+  operator: ""   # OA管理员账号
+  parentId: 194258821321
+  parentUuid: XPwkYGxZV3Nqqzp2IlrdvGXmWAgozOKL
+
+saveFile:
+  path: C:\Users\86137\Desktop\
+
+aliwork:
+  appType: "APP_HDE0VZYLFWWRL6ZXYMY1"
+  systemToken: "JL766171RHB77S41N3PQ047G284S38925KIRMFIU"
+
+

+ 49 - 0
mjava-mankalong/src/main/resources/application-prod.yml

@@ -0,0 +1,49 @@
+# 环境配置
+server:
+  port: 8111
+  servlet:
+    context-path: /api/guangdian
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    hikari:
+      connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci           # SqlServer, Oracle 无需设置类型
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: test
+    password: test123
+    url: jdbc:mysql://47.110.74.198:3306?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+#    url: jdbc:mysql://127.0.0.1:3306?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+#  jpa:
+#    hibernate:
+#      ddl-auto: none      # JPA对表没有任何操作
+#    show-sql: true
+#    database: MYSQL
+#    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+# dingtalk
+dingtalk:
+  agentId: 4787306953
+  appKey: dingjnogqdvdmtuhnviq
+  appSecret: 5_Un9HkATekf8BJk9iAKywggYFPkc5934U8qEiHPSx6E_s07ZM1_4a5TnAwQwUI3
+  corpId:
+  aesKey:
+  token:
+  unionId: ut05hb7w9kxwTKt7iSNabvgiEiE #测试unionid
+  spaceId: 851452912 #钉盘-团队文件-全员文件夹
+  operator: ""   # OA管理员账号
+  parentId: 194258821321
+  parentUuid: XPwkYGxZV3Nqqzp2IlrdvGXmWAgozOKL
+saveFile:
+  path: /home/server/mankalong/file/
+
+aliwork:
+  appType: "APP_HDE0VZYLFWWRL6ZXYMY1"
+  systemToken: "JL766171RHB77S41N3PQ047G284S38925KIRMFIU"
+
+

+ 152 - 0
mjava-mankalong/src/main/resources/json/form.json

@@ -0,0 +1,152 @@
+{
+  "NSWBD": {
+    "processCode": "PROC-4685C389-FF2B-4FE2-A802-FEBB7BB9CDDE",
+    "creator": "proposerCode",
+    "attachmentUrl": {
+      "downloadUrl": "downloadUrl",
+      "name": "name"
+    },
+    "compIds": {
+      "时间": "time",
+      "收文号": "receiveNo",
+      "紧急程度": "urgencyLevel",
+      "办文人员": "handler",
+      "批文部门": "approveDept",
+      "文件标题": "fileTitle",
+      "董事长批示": "chairmanComment",
+      "总经理批示": "managerComment",
+      "相关分管领导批示": "deputyLeaderComment",
+      "拟文部门签批": "draftDeptApproval",
+      "相关部门意见": "relatedDeptOpinion",
+      "备注": "remark"
+    }
+  },
+  "HTSPD-JT": {
+    "processCode": "PROC-7C20FBC6-5C55-41C5-8786-08DEAF6E2050",
+    "creator": "proposerCode",
+    "contractTextUrl": {
+      "downloadUrl": "downloadUrl",
+      "name": "name"
+    },
+    "contractScanUrl": {
+      "downloadUrl": "downloadUrl",
+      "name": "name"
+    },
+    "contractPreApprovalFlow": {
+      "downloadUrl": "downloadUrl",
+      "name": "name"
+    },
+    "ourPartyInfo": "我方信息",
+    "counterpartyInfo": "对方信息",
+    "compIds": {
+      "发起人": "proposerName",
+      "日期": "date",
+      "合同文本预审": "contractTextPreliminaryReview",
+      "合同预审流程": "contractPreliminaryReviewFlow",
+      "合同名称": "contractName",
+      "金额类型": "amountType",
+      "合同总额(元)": "contractTotalAmount",
+      "发起方式": "initiateMethod",
+      "合同期限类型": "contractTermType",
+      "tableField_ourPartyInfo": {
+        "我方主体名称": "ourPartySubjectName"
+      },
+      "合同正文": "contractMainText",
+      "tableField_counterpartyInfo": {
+        "对方主体名称": "counterpartySubjectName"
+      },
+      "签署方式": "signMethod",
+      "是否涉及其他相关部门": "isInvolveOtherDepts",
+      "是否需王旭协同": "isNeedLandCoordination",
+      "请选择该合同的审批人": "contractApprover"
+    }
+  },
+  "HTSPD-YD": {
+    "processCode": "PROC-4BE72E7B-2862-4803-8CAD-BD2BB69C77A4",
+    "creator": "proposerCode",
+    "ourPartyInfo": "我方信息",
+    "counterpartyInfo": "对方信息",
+    "compIds": {
+      "发起人": "proposerName",
+      "合同类型": "contractType",
+      "其他合同类型": "otherContractType",
+      "合同文本预审": "contractTextPreReview",
+      "是否关联其他部门审批": "isRelateOtherDeptApproval",
+      "合同名称": "contractName",
+      "金额类型": "amountType",
+      "合同总额(元)": "contractTotalAmount",
+      "发起方式": "initiateMethod",
+      "合同期限类型": "contractTermType",
+      "合同说明": "contractRemark",
+      "tableField_ourPartyInfo": {
+        "我方主体名称": "ourPartySubjectName"
+      },
+      "合同正文": "contractMainText",
+      "tableField_counterpartyInfo": {
+        "对方主体名称": "counterpartySubjectName"
+      },
+      "签署方式": "signMethod",
+      "印章类型": "sealType",
+      "风险告知同意并勾选1": "riskTypeAgreementCheck1",
+      "风险告知1": "riskNotification1",
+      "风险告知同意并勾选2": "riskTypeAgreementCheck2",
+      "风险告知2": "riskNotification2"
+    }
+  },
+  "HTSPD-GF": {
+  "processCode": "PROC-5CF4FE9C-96F6-42BF-876B-ADA383356808",
+  "creator": "proposerCode",
+  "contractTextUrl": {
+    "downloadUrl": "downloadUrl",
+    "name": "name"
+  },
+  "contractScanUrl": {
+    "downloadUrl": "downloadUrl",
+    "name": "name"
+  },
+  "contractPreApprovalFlow": {
+    "downloadUrl": "downloadUrl",
+    "name": "name"
+  },
+  "ourPartyInfo": "我方信息",
+  "counterpartyInfo": "对方信息",
+  "compIds": {
+    "发起人": "proposerName",
+    "合同名称": "contractName",
+    "金额类型": "amountType",
+    "合同总额(元)": "contractTotalAmount",
+    "发起方式": "initiateMethod",
+    "合同期限类型": "contractTermType",
+    "签署方式": "signMethod",
+    "tableField_ourPartyInfo": {
+      "我方主体名称": "ourPartySubjectName"
+    },
+    "合同正文": "contractMainText",
+    "tableField_counterpartyInfo": {
+      "对方主体名称": "counterpartySubjectName"
+    },
+    "合同前置审批": "frontApproval",
+    "oa请示、采购结果": "procurementResult",
+    "决策文件、会议纪要、中标通知书等": "decisionDocument",
+    "合同是否需要审核": "isReview",
+    "政企类合同金额(元)": "governmentAmt",
+    "市场经营支出类合同金额(元)": "marketOperationAmt",
+    "综合服务合同金额(元)": "integratedServicesAmt",
+    "采购类合同金额(元)": "buyAmt",
+    "借款合同金额(元)": "loanAmt",
+    "对外投资项目类别": "outProjectType",
+    "战略合同项目类别": "strategyProjectType",
+    "非结构性存款类(固定资产/股权等)金额(元)": "nonStructuralAmt",
+    "结构性存款等合同金额(元)": "structuralAmt",
+    "融资担保合同金额(元)": "financingAmt",
+    "一般战略合同金额(元)": "generalStrategyAmt",
+    "赞助捐赠合同金额(元)": "sponsorshipAmt",
+    "其他合同金额(元)": "otherContractAmt",
+    "其他合同类型": "otherContractType",
+    "风险告知同意并勾选": "riskTypeAgreementCheck",
+    "风险告知": "riskNotification",
+    "合同文本预审": "contractTextPreReview",
+    "合同类型": "contractType"
+  }
+}
+}

+ 26 - 0
mjava-mankalong/src/main/resources/json/formtest.json

@@ -0,0 +1,26 @@
+{
+  "processCode": "PROC-7C20FBC6-5C55-41C5-8786-08DEAF6E2050",
+  "creator": "proposerCode",
+  "compIds": {
+    "发起人": "proposerCode",
+    "合同名称": "contractName",
+    "金额类型": "amountType",
+    "合同总额(元)": "contractTotalAmount",
+    "发起方式": "initiateMethod",
+    "合同期限类型": "contractTermType",
+    "合同期限开始日期": "contractTermType",
+    "合同期限结束时间": "contractTermType",
+    "合同编号生成方式": "contractTermType",
+    "合同编号": "contractTermType",
+    "tableField_ourPartyInfo": {
+      "我方主体名称": "ourPartySubjectName"
+    },
+    "合同正文": "contractMainText",
+    "tableField_counterpartyInfo": {
+      "对方主体名称": "counterpartySubjectName"
+    },
+    "签署方式": "signMethod",
+    "合同说明": "signMethod",
+    "合同附件": "signMethod"
+  }
+}

+ 168 - 0
mjava-mankalong/src/test/java/test.java

@@ -0,0 +1,168 @@
+import com.alibaba.fastjson.JSONObject;
+import com.malk.mankalong.Boot;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Boot.class)
+public class test {
+//    public static void main(String[] args) throws Exception {
+//        String ip = "127.0.0.1";
+//        String port = "8080";
+//        String biz_center = "001";
+//        String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApzpqAg5xEk6E9o7ISP0pQO1Vdg6V8GozPHrVuBh6SOADw0je6qKfgvAn/s5RabyfBGfrFZ5kybPIPyizqCoqaDN5sX6tnyo3nxvuJCywK1CVr9X01P02GOJOx9EdJDZxp9e2Q/cbj/c8+amxId8brVCAm3OT8kM9UZUzohFassJuOVlA1TJ6A+u5MZ7cGM3/UQS6QJVD6N/8PraBfsdxxsXt0M4f0Lkalaxf8rVT+VHBK8jLxp9XaUWRJG6yatMMoFCIMZ6TNjOCSJ1ZDAlJ/pU5VY79RyS5jfkd+70YzUKlZjMJ/psO+ZEVFPu/yfMfS8M16c8xrXDzFcI1wcbBXwIDAQAB";
+//        String client_id = "zdgl";
+//        String client_secret = "4b0618a08ea84ff2ac93";
+//        String username = "JT001";
+//        String password = "1234qwer@";
+//        IAPIUtils util = null;
+//        util= new APICurUtils();
+//        util.init(ip, port, biz_center, client_id, client_secret, pubKey, username, password);
+//        String token = util.getToken();
+//        String url = "nccloud/api/gl/accountrep/accountbalance";
+//        util.setApiUrl(url);
+//
+//        String json = "{\r\n" +
+//                "  \"ufinterface\": {\r\n" +
+//                "    \"billtype\": \"supbankacc\",\r\n" +
+//                "    \"sender\": \"ZDGL\",\r\n" +
+//                "    \"replace\": \"Y\",\r\n" +
+//                "    \"bill\": {\r\n" +
+//                "      \"billhead\": {\r\n" +
+//                "        \"custbankVO\": {\r\n" +
+//                "          \"pk_cust\": \"KS01000000006\",\r\n" +
+//                "          \"pk_org\": \"01\"\r\n" +
+//                "        },\r\n" +
+//                "        \"bankaccbasVO\": {\r\n" +
+//                "          \"pk_group\": \"01\",\r\n" +
+//                "          \"accopendate\": \"\",\r\n" +
+//                "          \"enablestate\": \"2\",\r\n" +
+//                "          \"orgnumber\": \"\",\r\n" +
+//                "          \"accnum\": \"6222788\",\r\n" +
+//                "          \"pk_netbankinftp\": \"\",\r\n" +
+//                "          \"city\": \"\",\r\n" +
+//                "          \"pk_bankdoc\": \"01000001\",\r\n" +
+//                "          \"pk_org\": \"01\",\r\n" +
+//                "          \"accattribute\": \"0\",\r\n" +
+//                "          \"province\": \"\",\r\n" +
+//                "          \"tel\": \"\",\r\n" +
+//                "          \"accname\": \"\",\r\n" +
+//                "          \"pk_banktype\": \"01\",\r\n" +
+//                "          \"customernumber\": \"\",\r\n" +
+//                "          \"address\": \"\",\r\n" +
+//                "          \"accstate\": \"0\",\r\n" +
+//                "          \"accclass\": \"3\",\r\n" +
+//                "          \"combinenum\": \"123123\",\r\n" +
+//                "          \"accountproperty\": \"0\",\r\n" +
+//                "          \"contactpsn\": \"\",\r\n" +
+//                "          \"bankarea\": \"\",\r\n" +
+//                "		  \"bankaccsub\": {\r\n" +
+//                "						\"item\": {\r\n" +
+//                "							\"isdefault\": \"N\",\r\n" +
+//                "							\"pk_currtype\": \"CNY\"\r\n" +
+//                "						}\r\n" +
+//                "					}\r\n" +
+//                "        }\r\n" +
+//                "      }\r\n" +
+//                "    },\r\n" +
+//                "    \"isexchange\": \"Y\",\r\n" +
+//                "    \"account\": \"001\",\r\n" +
+//                "    \"groupcode\": \"01\"\r\n" +
+//                "  }\r\n" +
+//                "}";
+//
+//        JSONObject json2 = JSONObject.parseObject(json);
+//        String result = util.getAPIRetrun(token, json2.toJSONString());
+//        System.out.println(result);
+//
+//    }
+
+
+    public static void main(String[] args) {
+        String urlStr = "https://oa.cbyun.com.cn/seeyon/rest/token";
+        String jsonInput = "{\"userName\":\"restDing\",\"password\":\"507228d7-8768-4a2d-a1c3-5b49af9b30de\"}";
+
+        HttpURLConnection connection = null;
+        try {
+            // 1. 创建连接
+            URL url = new URL(urlStr);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setRequestMethod("POST");
+            connection.setRequestProperty("Content-Type", "application/json");
+            connection.setDoOutput(true); // 允许输出
+            connection.setDoInput(true);  // 允许输入
+            connection.setConnectTimeout(5000);
+            connection.setReadTimeout(5000);
+
+            // 2. 写入请求体
+            try (OutputStream os = connection.getOutputStream()) {
+                byte[] input = jsonInput.getBytes(StandardCharsets.UTF_8);
+                os.write(input, 0, input.length);
+            }
+
+            // 3. 获取响应码
+            int responseCode = connection.getResponseCode();
+            if (responseCode == HttpURLConnection.HTTP_OK) {
+                // 4. 读取响应内容
+                StringBuilder response = new StringBuilder();
+                try (BufferedReader br = new BufferedReader(
+                        new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
+                    String line;
+                    while ((line = br.readLine()) != null) {
+                        response.append(line);
+                    }
+                }
+                String jsonResponse = response.toString();
+                System.out.println("响应原始内容: " + jsonResponse);
+                JSONObject jsonObject = JSONObject.parseObject(jsonResponse);
+
+                // 5. 解析 id 字段(手动提取,避免依赖 JSON 库)
+                String id = jsonObject.getString("id");
+                if (id != null) {
+                    System.out.println("获取到的 id: " + id);
+                } else {
+                    System.out.println("未找到 id 字段");
+                }
+            } else {
+                System.err.println("请求失败,HTTP 状态码: " + responseCode);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    /**
+     * 从简单的 JSON 字符串中提取 "id" 字段的值
+     * 例如输入 {"id":"xxx"} 返回 xxx(去除前后引号)
+     * @param json 响应 JSON 字符串
+     * @return id 值,未找到返回 null
+     */
+    private static String extractIdFromJson(String json) {
+        // 查找 "id":" 的位置
+        String key = "\"id\":\"";
+        int startIndex = json.indexOf(key);
+        if (startIndex == -1) {
+            return null;
+        }
+        startIndex += key.length(); // 移动到值的开始位置
+        int endIndex = json.indexOf("\"", startIndex);
+        if (endIndex == -1) {
+            return null;
+        }
+        return json.substring(startIndex, endIndex);
+    }
+}

+ 39 - 0
mjava-mankalong/src/test/resource/server.sh

@@ -0,0 +1,39 @@
+#!/bin/bash
+
+appname='mjava-dongfangxinhua'
+
+if [ "$1" == "dev" ]; then
+  java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
+else
+  if [ "$1" == "start" ]; then
+    nohup java -Xms256m -Xmx256m -jar $appname.jar &
+    echo "server prod is starting"
+    tail -f log/info.log
+  else
+    if [ "$1" == "test" ]; then
+      nohup java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=test &
+      echo "server test is starting"
+      tail -f log/info.log
+    else
+      if [ "$1" == "stop" ]; then
+        PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+        if [ -z "$PID" ]; then
+          echo "server is already stopped"
+        else
+          echo kill $PID
+          kill $PID
+        fi
+      else
+        if [ "$1" == "status" ]; then
+          PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+          if [ -z "$PID" ]; then
+            echo "server is stopped"
+          else
+            echo "server is running"
+            echo $PID
+          fi
+        fi
+      fi
+    fi
+  fi
+fi