ソースを参照

Initial commit

zhangkan 3 週間 前
コミット
171f494607

+ 16 - 0
.gitignore

@@ -0,0 +1,16 @@
+.DS_Store
+.idea/
+*.iml
+
+target/
+out/
+build/
+
+*.log
+hs_err_pid*
+replay_pid*
+
+.env
+.env.*
+!.env.example
+application-local.properties

+ 0 - 0
README.md


+ 368 - 0
pom.xml

@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.3.3.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.muzhi.duohui</groupId>
+    <artifactId>springboot</artifactId>
+<!--    <packaging>jar</packaging>-->
+    <version>duohui</version>
+    <name>duohui</name>
+    <description>Demo project for Spring Boot</description>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <fastjson.version>1.2.33</fastjson.version>
+        <gson.version>2.8.2</gson.version>
+        <json.version>20170516</json.version>
+        <poi.version>3.17</poi.version>
+        <jodatime.version>2.10.1</jodatime.version>
+        <swagger.version>2.7.0</swagger.version>
+        <commons-fileupload.version>1.3.1</commons-fileupload.version>
+        <!--        <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>-->
+        <!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本-->
+        <!--        <thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>-->
+        <!-- 设置项目的 Java 版本为 11 或更高 -->
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>sonatype-nexus-staging</id>
+            <name>Sonatype Nexus Staging</name>
+            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.4.0</version>
+        </dependency>
+
+        <!-- httpClient -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.13</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>4.4.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.konghq</groupId>
+            <artifactId>unirest-java</artifactId>
+            <version>2.3.17</version>
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>org.slf4j</groupId>-->
+<!--            <artifactId>slf4j-api</artifactId>-->
+<!--        </dependency>-->
+
+<!--        <dependency>-->
+<!--            <groupId>commons-io</groupId>-->
+<!--            <artifactId>commons-io</artifactId>-->
+<!--        </dependency>-->
+
+        <!--json 组件 -->
+<!--        <dependency>-->
+<!--            <groupId>com.alibaba</groupId>-->
+<!--            <artifactId>fastjson</artifactId>-->
+<!--            <scope>provided</scope>-->
+<!--        </dependency>-->
+
+        <!--        <dependency>-->
+        <!--            <groupId>org.apache.cxf</groupId>-->
+        <!--            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>-->
+        <!--            <version>3.3.1</version>-->
+        <!--        </dependency>-->
+
+        <!--        <dependency>-->
+        <!--            <groupId>org.springframework.boot</groupId>-->
+        <!--            <artifactId>spring-boot-starter-thymeleaf</artifactId>-->
+        <!--&lt;!&ndash;            <version>2.3.3.RELEASE</version>&ndash;&gt;-->
+        <!--        </dependency>-->
+
+        <!--钉钉相关-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
+            <version>2.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dingtalk</artifactId>
+            <version>2.2.34</version>
+        </dependency>
+
+        <!--json相关-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>${json.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+
+        <!--        <dependency>-->
+        <!--            <groupId>net.sf.json-lib</groupId>-->
+        <!--            <artifactId>json-lib</artifactId>-->
+        <!--            <version>2.4</version>-->
+        <!--        </dependency>-->
+
+
+        <!-- JSONObject对象依赖的jar包 -->
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.3</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.ezmorph</groupId>
+            <artifactId>ezmorph</artifactId>
+            <version>1.0.6</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.json-lib</groupId>
+            <artifactId>json-lib</artifactId>
+            <version>2.2.3</version>
+            <classifier>jdk15</classifier><!-- 指定jdk版本 -->
+        </dependency>
+
+
+        <!--xls-->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
+        <!--xlsx-->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
+        <!--文件上传-->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>${commons-fileupload.version}</version>
+        </dependency>
+
+        <!--        <dependency>-->
+        <!--            <groupId>org.springframework.boot</groupId>-->
+        <!--            <artifactId>spring-boot-starter-thymeleaf</artifactId>-->
+        <!--        </dependency>-->
+
+        <!--引入web模块-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <version>2.3.3.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+            <version>1.18.10</version>
+        </dependency>
+
+        <!--MD5加密-->
+        <dependency>
+            <groupId>org.apache.directory.studio</groupId>
+            <artifactId>org.apache.commons.codec</artifactId>
+            <version>1.8</version>
+        </dependency>
+
+        <!--Map缓存方法:可设置Map中的Entry在一段时间后自动过期-->
+        <dependency>
+            <groupId>net.jodah</groupId>
+            <artifactId>expiringmap</artifactId>
+            <version>0.5.8</version>
+        </dependency>
+
+<!--        &lt;!&ndash;mybatis-plus数据库连接&ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>com.baomidou</groupId>-->
+<!--            <artifactId>mybatis-plus-boot-starter</artifactId>-->
+<!--            <version>3.2.0</version>-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash;引入mysql:数据库驱动&ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>mysql</groupId>-->
+<!--            <artifactId>mysql-connector-java</artifactId>-->
+<!--            <scope>runtime</scope>-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash;引入druid数据源&ndash;&gt;-->
+<!--        &lt;!&ndash; https://mvnrepository.com/artifact/com.alibaba/druid &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>com.alibaba</groupId>-->
+<!--            <artifactId>druid</artifactId>-->
+<!--            <version>1.1.9</version>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>com.alibaba</groupId>-->
+<!--            <artifactId>druid-spring-boot-starter</artifactId>-->
+<!--            <version>1.1.9</version>-->
+<!--        </dependency>-->
+
+        <!--引入jpa模块-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+
+        <!--日期时间工具-->
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <version>${jodatime.version}</version>
+        </dependency>
+
+        <!--日期工具-->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>4.6.8</version>
+        </dependency>
+
+        <!--log4j-->
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+        </dependency>
+
+        <!--swagger-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <!--swagger ui-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.junit.vintage</groupId>
+                    <artifactId>junit-vintage-engine</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <fork>true</fork>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>utf8</encoding>
+                </configuration>
+            </plugin>
+
+            <!--打包跳过测试-->
+<!--            <plugin>-->
+<!--                <groupId>org.apache.maven.plugins</groupId>-->
+<!--                <artifactId>maven-surefire-plugin</artifactId>-->
+<!--                <version>2.4.2</version>-->
+<!--                <configuration>-->
+<!--                    <skipTests>true</skipTests>-->
+<!--                </configuration>-->
+<!--            </plugin>-->
+        </plugins>
+
+        <!--映射mapper中对应的xml配置文件,如果没有mapper.xml文件则将下列注释-->
+<!--        <resources>-->
+<!--            <resource>-->
+<!--                <directory>src/main/java</directory>-->
+<!--                <includes>-->
+<!--                    <include>**/*.xml</include>-->
+
+<!--                    <include>**/*.properties</include>-->
+<!--                    <include>**/*.tld</include>-->
+<!--                    <include>**/*.xls</include>-->
+<!--                    <include>**/*.xlsx</include>-->
+<!--                </includes>-->
+<!--                <filtering>false</filtering>-->
+<!--            </resource>-->
+<!--        </resources>-->
+    </build>
+
+</project>

+ 21 - 0
src/main/java/com/muzhi/duohui/DuohuiApplication.java

@@ -0,0 +1,21 @@
+package com.muzhi.duohui;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+
+//@MapperScan("com.muzhi.huaxiao.mapper")
+@EnableAsync//开启异步注解
+@SpringBootApplication(exclude= DataSourceAutoConfiguration.class)//启动时不加载数据库(exclude= DataSourceAutoConfiguration.class)
+@EnableScheduling//开启定时任务
+//@ComponentScan(basePackages = {"com.muzhi"})
+public class DuohuiApplication {
+
+    public static void main(String[] args){
+        SpringApplication.run(DuohuiApplication.class, args);
+    }
+
+}

+ 77 - 0
src/main/java/com/muzhi/duohui/common/R.java

@@ -0,0 +1,77 @@
+package com.muzhi.duohui.common;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author ZhangKan
+ * @Data 11:20
+ */
+
+//统一返回结果类
+@Data
+public class R {
+
+    @ApiModelProperty(value = "是否成功")
+    private Boolean success;
+
+    @ApiModelProperty(value = "返回码")
+    private Integer code;
+
+    @ApiModelProperty(value = "返回消息")
+    private String message;
+
+    @ApiModelProperty(value = "返回数据")
+    private Map<String, Object> data = new HashMap<String, Object>();
+
+    //把构造方法私有
+    private R(){}
+
+    //成功静态方法
+    public static R ok(){
+
+        R r = new R();
+        r.setSuccess(true);
+        r.setCode(ResultCode.SUCCESS);
+        r.setMessage("成功");
+        return r;
+    }
+
+    //失败静态方法
+    public static R error(){
+
+        R r = new R();
+        r.setSuccess(false);
+        r.setCode(ResultCode.ERROR);
+        r.setMessage("失败");
+        return r;
+    }
+
+    public R message(String message){
+        this.setMessage(message);
+        return this;
+    }
+
+    public R code(Integer code){
+        this.setCode(code);
+        return this;
+    }
+
+    public R data(String key, Object value){
+        this.data.put(key, value);
+        return this;
+    }
+
+    public R data(String key, String value){
+        this.data.put(key, value);
+        return this;
+    }
+
+    public R data(Map<String, Object> map){
+        this.setData(map);
+        return this;
+    }
+}

+ 12 - 0
src/main/java/com/muzhi/duohui/common/ResultCode.java

@@ -0,0 +1,12 @@
+package com.muzhi.duohui.common;
+
+/**
+ * @Author ZhangKan
+ * @Data 11:15
+ */
+public interface ResultCode {
+
+    public static Integer SUCCESS = 200;//成功
+
+    public static Integer ERROR = 201;//失败
+}

+ 39 - 0
src/main/java/com/muzhi/duohui/controller/AccessTokenController.java

@@ -0,0 +1,39 @@
+package com.muzhi.duohui.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @Author ZhangKan
+ * @Data 15:03
+ */
+
+@Api(description = "钉钉授权AccessToken")
+@RestController
+@RequestMapping("/dingservice")
+@CrossOrigin//解决跨域问题
+public class AccessTokenController {
+
+    @Autowired
+    private com.muzhi.duohui.service.AccessTokenService AccessTokenService;
+
+    //获取钉钉中的access_token(钉钉应用)
+    @ApiOperation(value = "获取钉钉的access_token")
+    @GetMapping("getAccessToken")
+    public String getAccessToken(){
+
+        String accessToken = AccessTokenService.getAccessToken();
+        return accessToken;
+    }
+
+    //获取钉钉中的access_token(派智TB应用)
+    @ApiOperation(value = "获取钉钉中的access_token")
+    @GetMapping("getAppToken")
+    public String getAppToken(){
+
+        String AppToken = AccessTokenService.getAppToken();
+        return AppToken;
+    }
+}

+ 35 - 0
src/main/java/com/muzhi/duohui/controller/TbController.java

@@ -0,0 +1,35 @@
+package com.muzhi.duohui.controller;
+
+import com.muzhi.duohui.common.R;
+import com.muzhi.duohui.service.TbService;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * @Author ZhangKan
+ * @Data 15:03
+ */
+
+@Api(description = "TB接口")
+@RestController
+@RequestMapping("/tbservice")
+//@CrossOrigin//解决跨域问题
+public class TbController {
+
+    @Autowired
+    private TbService tbService;
+
+    //接收TB推送的数据
+    @PostMapping("callback")
+    public R callback(@RequestBody Map body) throws Exception{
+
+        R r = tbService.callBack(body);
+        return r;
+    }
+}

+ 35 - 0
src/main/java/com/muzhi/duohui/dingtalk/dingtalkWebhook.java

@@ -0,0 +1,35 @@
+package com.muzhi.duohui.dingtalk;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class dingtalkWebhook {
+
+
+    public static void dingtalkWebhook(String webhookUrl, String mapStr){
+
+        OkHttpClient client = new OkHttpClient().newBuilder()
+                .build();
+        MediaType mediaType = MediaType.parse("text/plain");
+        RequestBody body = RequestBody.create(mediaType, mapStr);
+        Request request = new Request.Builder()
+                .url(webhookUrl)
+                .method("POST", body)
+                .build();
+        JSONObject jsonObject = null;
+        try {
+            Response response = client.newCall(request).execute();
+            String bodyStr = response.body().string();
+            jsonObject = JSON.parseObject(bodyStr);
+            System.out.println("返回体body{}:" + jsonObject);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+}

+ 14 - 0
src/main/java/com/muzhi/duohui/service/AccessTokenService.java

@@ -0,0 +1,14 @@
+package com.muzhi.duohui.service;
+
+/**
+ * @Author ZhangKan
+ * @Data 15:34
+ */
+public interface AccessTokenService {
+
+    //获取access_token的方法(钉钉应用)
+    String getAccessToken();
+
+    //获取access_token的方法(夺汇TB应用)
+    String getAppToken();
+}

+ 12 - 0
src/main/java/com/muzhi/duohui/service/TbService.java

@@ -0,0 +1,12 @@
+package com.muzhi.duohui.service;
+
+import com.muzhi.duohui.common.R;
+
+import java.util.Map;
+
+public interface TbService {
+
+    /**TB WebHook*/
+    //接收TB的WebHook推送过来的数据
+    R callBack(Map body) throws Exception;
+}

+ 83 - 0
src/main/java/com/muzhi/duohui/service/impl/AccessTokenServiceImpl.java

@@ -0,0 +1,83 @@
+package com.muzhi.duohui.service.impl;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.request.OapiGettokenRequest;
+import com.dingtalk.api.response.OapiGettokenResponse;
+import com.muzhi.duohui.service.AccessTokenService;
+import com.taobao.api.ApiException;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
+
+
+/**
+ * @Author ZhangKan
+ * @Data 15:39
+ */
+
+@Service
+public class AccessTokenServiceImpl implements AccessTokenService {
+
+    @Value("${dingtalk.app-key}")
+    private String appKey;
+
+    @Value("${dingtalk.app-secret}")
+    private String dingtalkAppSecret;
+
+    public static String DingtalkAccessToken = null;
+
+    //获取dingtalk授权码(钉钉应用)
+    @Override
+    public String getAccessToken() {
+        DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+        OapiGettokenRequest request = new OapiGettokenRequest();
+        request.setAppkey(appKey);
+        request.setAppsecret(dingtalkAppSecret);
+        request.setHttpMethod("GET");
+        try {
+            OapiGettokenResponse response = client.execute(request);
+            DingtalkAccessToken = response.getAccessToken();
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+        return DingtalkAccessToken;
+    }
+
+    public static final Long   EXPIRES_IN = 1 * 3600 * 1000L;
+    public static final String TOKEN_APPID = "_appId";
+
+    @Value("${teambition.app-id}")
+    private String appId;
+
+    @Value("${teambition.app-secret}")
+    private String appSecret;
+    //获取access_token的方法(夺汇TB应用)
+    @Override
+    public String getAppToken() {
+        if (StringUtils.isEmpty(appId) || StringUtils.isEmpty(appSecret)) {
+            return null;
+        }
+
+        Algorithm algorithm = Algorithm.HMAC256(appSecret);
+        long timestamp = System.currentTimeMillis();
+        Date issuedAt = new Date(timestamp);
+        Date expiresAt = new Date(timestamp + EXPIRES_IN);
+
+//        return JWT.create()
+//                .withClaim(TOKEN_APPID, appId)
+//                .withIssuedAt(issuedAt)
+//                .withExpiresAt(expiresAt)
+//                .sign(algorithm);
+
+        String sign = JWT.create()
+                .withClaim(TOKEN_APPID, appId)
+                .withIssuedAt(issuedAt)
+                .withExpiresAt(expiresAt)
+                .sign(algorithm);
+        return sign;
+    }
+}

+ 508 - 0
src/main/java/com/muzhi/duohui/service/impl/TbServiceImpl.java

@@ -0,0 +1,508 @@
+package com.muzhi.duohui.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.dingtalkyida_1_0.models.SearchFormDatasResponse;
+import com.aliyun.tea.TeaException;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.muzhi.duohui.common.R;
+import com.muzhi.duohui.service.AccessTokenService;
+import com.muzhi.duohui.service.TbService;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+@Service
+@Slf4j
+public class TbServiceImpl implements TbService {
+
+    //宜搭接口调用
+    public static com.aliyun.dingtalkyida_1_0.Client createClient() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkyida_1_0.Client(config);
+    }
+
+    @Autowired
+    private AccessTokenService accessTokenService;
+
+    //夺汇TB企业ID(tbOrganizationId)
+    public static String tbOrganizationId = "5e8e8a6ef849edccba9be9e3";
+
+    //通过任务id查询任务详情
+    public JSONArray getRenwuxiangqing(String rwid){
+
+        //获取属于该区域名称的项目集id
+        OkHttpClient client1 = new OkHttpClient().newBuilder()
+                .build();
+        Request request1 = new Request.Builder()
+                .url("https://open.teambition.com/api/v3/task/query?taskId="+ rwid)
+                .method("GET", null)
+                .addHeader("Authorization", "Bearer " + accessTokenService.getAppToken())
+                .addHeader("X-Tenant-Id", tbOrganizationId)
+                .addHeader("X-Tenant-Type", "organization")
+                .build();
+
+        int code1 = 0;
+        JSONArray result1 = null;
+        try {
+            Response response1 = client1.newCall(request1).execute();
+            String bodyStr1 = response1.body().string();
+            JSONObject jsonObject1 = JSON.parseObject(bodyStr1);
+            System.out.println("返回体body:" + jsonObject1);
+            code1 = jsonObject1.getInteger("code");
+
+            result1 = jsonObject1.getJSONArray("result");
+            System.out.println("result===>" + result1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        System.out.println("查询【通过任务id查询所属项目id】接口返回的状态码(200成功,400异常):" + code1);
+
+        //任务类型id
+//        String sfcId = null;
+//        if (!result1.isEmpty() || result1 != null) {
+//            JSONObject jsonObject1 = result1.getJSONObject(0);
+//
+//            //任务类型id
+//            sfcId = jsonObject1.getString("sfcId");
+//            System.out.println("任务类型id:" + sfcId);
+//        }
+
+        return result1;
+    }
+
+    //通过任务类型id搜索项目任务类型
+    public JSONArray getQiyeTaskType(String projectId, String rwlxid){
+
+        //获取属于该区域名称的项目集id
+        OkHttpClient client1 = new OkHttpClient().newBuilder()
+                .build();
+        Request request1 = new Request.Builder()
+                .url("https://open.teambition.com/api/v3/project/"+ projectId +"/scenariofieldconfig/search?sfcIds="+ rwlxid)
+                .method("GET", null)
+                .addHeader("Authorization", "Bearer " + accessTokenService.getAppToken())
+                .addHeader("X-Tenant-Id", tbOrganizationId)
+                .addHeader("X-Tenant-Type", "organization")
+                .build();
+
+        int code1 = 0;
+        JSONArray result1 = null;
+        try {
+            Response response1 = client1.newCall(request1).execute();
+            String bodyStr1 = response1.body().string();
+            JSONObject jsonObject1 = JSON.parseObject(bodyStr1);
+            System.out.println("返回体body:" + jsonObject1);
+            code1 = jsonObject1.getInteger("code");
+
+            result1 = jsonObject1.getJSONArray("result");
+            System.out.println("result===>" + result1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        System.out.println("查询【通过任务类型id搜索项目任务类型】接口返回的状态码(200成功,400异常):" + code1);
+
+        return result1;
+    }
+
+    //根据任务自定义字段id,查询企业「自定义字段」名称
+    public String getTaskCustomfieldName(String taskCustomfieldId){
+
+        OkHttpClient client1 = new OkHttpClient().newBuilder()
+                .build();
+        Request request1 = new Request.Builder()
+                .url("https://open.teambition.com/api/v3/customfield/search?cfIds=" + taskCustomfieldId)
+                .method("GET", null)
+                .addHeader("Authorization", "Bearer " + accessTokenService.getAppToken())
+                .addHeader("X-Tenant-Id", tbOrganizationId)
+                .addHeader("X-Tenant-Type", "organization")
+                .build();
+
+        int code1 = 0;
+        JSONArray result1 = null;
+        try {
+            Response response1 = client1.newCall(request1).execute();
+            String bodyStr1 = response1.body().string();
+            JSONObject jsonObject1 = JSON.parseObject(bodyStr1);
+            System.out.println("返回体body:" + jsonObject1);
+            code1 = jsonObject1.getInteger("code");
+
+            result1 = jsonObject1.getJSONArray("result");
+            System.out.println("result===>" + result1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        System.out.println("查询【根据任务自定义字段id,查询企业「自定义字段」名称】接口返回的状态码(200成功,400异常):" + code1);
+
+        //自定义字段名称
+        String xmztName = null;
+        if (!result1.isEmpty() || result1 != null) {
+            for (int i = 0; i < result1.size(); i++) {
+                JSONObject jsonObject1 = result1.getJSONObject(i);
+                //自定义字段名称
+                xmztName = jsonObject1.getString("name");
+                System.out.println("自定义字段名称:" + xmztName);
+            }
+        }
+
+        return xmztName;
+    }
+
+    //更新项目自定义字段值
+    public JSONObject updateXmCustomField(String operatorId, String xmid, String customfieldId, List listTitle){
+
+        Map mapAll = new HashMap();
+        mapAll.put("customfieldId", customfieldId);
+        mapAll.put("value", listTitle);
+
+        String mapStr = JSON.toJSONString(mapAll);
+        System.out.println("封装更新的字段参数:" + mapStr);
+
+
+        OkHttpClient client = new OkHttpClient().newBuilder()
+                .build();
+        MediaType mediaType = MediaType.parse("application/json");
+        RequestBody body = RequestBody.create(mediaType, mapStr);
+        Request request = new Request.Builder()
+                .url("https://open.teambition.com/api/v3/project/"+ xmid +"/status/customfield/create")
+                .method("POST", body)
+                .addHeader("x-operator-id", operatorId)
+                .addHeader("Authorization", "Bearer " + accessTokenService.getAppToken())
+                .addHeader("X-Tenant-Id", tbOrganizationId)
+                .addHeader("X-Tenant-Type", "organization")
+                .addHeader("Content-Type", "application/json")
+                .build();
+
+        JSONObject jsonObject1 = new JSONObject();
+        try {
+            Response response1 = client.newCall(request).execute();
+            String bodyStr1 = response1.body().string();
+            jsonObject1 = JSON.parseObject(bodyStr1);
+            System.out.println("返回体body:" + jsonObject1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return jsonObject1;
+    }
+
+    //根据项目id,查询项目概览自定义字段列表中「自定义字段」id
+    public String getXiangmuZidingyiziduanid(String xmid, String zidingyiziduanName){
+
+        OkHttpClient client1 = new OkHttpClient().newBuilder()
+                .build();
+        Request request1 = new Request.Builder()
+                .url("https://open.teambition.com/api/v3/project/"+ xmid +"/status/customfield/list")
+                .method("GET", null)
+                .addHeader("Authorization", "Bearer " + accessTokenService.getAppToken())
+                .addHeader("X-Tenant-Id", tbOrganizationId)
+                .addHeader("X-Tenant-Type", "organization")
+                .build();
+
+        int code1 = 0;
+        JSONArray result1 = null;
+        try {
+            Response response1 = client1.newCall(request1).execute();
+            String bodyStr1 = response1.body().string();
+            JSONObject jsonObject1 = JSON.parseObject(bodyStr1);
+            System.out.println("返回体body:" + jsonObject1);
+            code1 = jsonObject1.getInteger("code");
+
+            result1 = jsonObject1.getJSONArray("result");
+            System.out.println("result===>" + result1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        System.out.println("查询【根据项目id,查询项目概览自定义字段列表中「自定义字段」id】接口返回的状态码(200成功,400异常):" + code1);
+
+        //自定义字段id
+        String xmzdyzdId = null;
+        if (!result1.isEmpty() || result1 != null) {
+            for (int i = 0; i < result1.size(); i++) {
+                JSONObject jsonObject1 = result1.getJSONObject(i);
+                //自定义字段名称
+                String xmztName = jsonObject1.getString("name");
+                System.out.println("自定义字段名称:" + xmztName);
+
+                if (xmztName.equals(zidingyiziduanName)){
+                    //自定义字段id
+                    xmzdyzdId = jsonObject1.getString("cfId");
+                    System.out.println("自定义字段id:" + xmzdyzdId);
+                }
+            }
+        }
+
+        return xmzdyzdId;
+    }
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * 根据Excel文档梳理的字段名称与字段类型映射字典
+     */
+    private static final Map<String, String> FIELD_NAME_TYPE_MAPPING = new HashMap<>();
+    static {
+        FIELD_NAME_TYPE_MAPPING.put("覆盖国家", "多选");
+        FIELD_NAME_TYPE_MAPPING.put("是否白标", "单选");
+        FIELD_NAME_TYPE_MAPPING.put("渠道能力", "多选");
+        FIELD_NAME_TYPE_MAPPING.put("应用站点", "多选");
+        FIELD_NAME_TYPE_MAPPING.put("FBD", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("FBD渠道协作人", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("产品经理", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("研发", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("合规", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("客资", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("风控", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("运营", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("技术支持", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("财务", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("法务", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("税务", "成员");
+        FIELD_NAME_TYPE_MAPPING.put("组别", "单选");
+        FIELD_NAME_TYPE_MAPPING.put("渠道类型", "单选");
+        FIELD_NAME_TYPE_MAPPING.put("国家和能力", "层级选择");
+        FIELD_NAME_TYPE_MAPPING.put("商务首次沟通日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("NDA完成日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("FBD预审完成日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("商务合同签署完成日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("立项上会日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("PRD评审完成日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("技术方案评审完成日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("预计提测日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("预计发布日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("实际提测日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("实际发布日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("白名单对客日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("全量对客日期", "日期");
+        FIELD_NAME_TYPE_MAPPING.put("立项文件夹", "钉钉文档");
+        FIELD_NAME_TYPE_MAPPING.put("优先级", "单选");
+        FIELD_NAME_TYPE_MAPPING.put("PRD", "钉钉文档");
+        FIELD_NAME_TYPE_MAPPING.put("技术方案", "钉钉文档");
+        FIELD_NAME_TYPE_MAPPING.put("业务价值", "数字");
+        FIELD_NAME_TYPE_MAPPING.put("产研复杂度", "数字");
+    }
+
+    /**
+     * 任务类型与项目概览字段类型映射字典
+     */
+    private static final Map<String, String> FIELD_USER_TYPE_MAPPING = new HashMap<>();
+    static {
+        FIELD_USER_TYPE_MAPPING.put("渠道商务里程碑", "FBD");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-产品评估", "产品经理");
+        FIELD_USER_TYPE_MAPPING.put("技术开发发布里程碑", "研发");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-合规评估", "合规");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-客资评估", "客资");
+        FIELD_USER_TYPE_MAPPING.put("渠道管理-风控验证", "风控");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-运营评估", "运营");
+        FIELD_USER_TYPE_MAPPING.put("渠道管理-连通性测试", "技术支持");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-财务评估", "财务");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-法务评估", "法务");
+        FIELD_USER_TYPE_MAPPING.put("立项评估-税务评估(白标必须)", "税务");
+    }
+    //获取对应类型的方法
+    public static String getTypeByFieldName(String fieldName) {
+        // 使用 .get() 方法获取值
+        return FIELD_USER_TYPE_MAPPING.get(fieldName);
+    }
+
+    //接收TB的WebHook推送过来的数据
+    @Async
+    @Override
+    public R callBack(Map body) throws Exception{
+
+        String s = JSON.toJSONString(body);
+        System.out.println("TB推送过来的数据:" + s);
+
+        //解析TB推送过来的数据
+        JSONObject jsonObject = JSON.parseObject(s);
+        String event = jsonObject.getString("event");
+        System.out.println("事件名称「推送类型」:" + event);
+        String timestamp = jsonObject.getString("timestamp");
+        System.out.println("事件触发时间「毫秒级时间戳」:" + timestamp);
+
+//        休眠10秒
+//        try {
+//            Thread.sleep(10000);
+//        }catch (InterruptedException e){
+//            e.printStackTrace();
+//        }
+
+        if (event.equals("v3.task.customfield.update")) {//======任务自定义字段更新======
+            log.info("【任务自定义字段更新】,开始执行===》");
+            JSONObject data = jsonObject.getJSONObject("data");
+            System.out.println("任务信息data:" + data);
+
+            //项目id
+//            String xmid = data.getString("projectId");
+//            System.out.println("项目id:" + xmid);
+            //任务id
+            String taskId = data.getString("taskId");
+            System.out.println("任务id:" + taskId);
+            //操作者id
+            String operatorId = data.getString("creatorId");
+            System.out.println("操作者id:" + operatorId);
+            //任务自定义字段id
+            String customfieldId = data.getString("customfieldId");
+            System.out.println("任务自定义字段id:" + customfieldId);
+            //当前字段旧内容
+            JSONArray customfieldOldValue = data.getJSONArray("customfieldOldValue");
+            System.out.println("当前字段旧内容[]:" + customfieldOldValue);
+            //当前字段新内容
+            JSONArray customfieldValue = data.getJSONArray("customfieldValue");
+            System.out.println("当前字段新内容[]:" + customfieldValue);
+
+            /*根据任务id查询任务所属的项目id*/
+            JSONArray renwuxiangqing = getRenwuxiangqing(taskId);
+            //项目id
+            String projectId = null;
+            if (!renwuxiangqing.isEmpty() || renwuxiangqing != null) {
+                JSONObject jsonObject1 = renwuxiangqing.getJSONObject(0);
+                //项目id
+                projectId = jsonObject1.getString("projectId");
+                System.out.println("项目id:" + projectId);
+            }
+            if (projectId == null){
+                log.error("根据任务id查询所属项目id为空");
+                return R.error().message("根据任务id查询所属项目id为空");
+            }
+
+            /*根据任务自定义字段id,查询企业「自定义字段」名称*/
+            String taskName = getTaskCustomfieldName(customfieldId);
+            System.out.println("任务中当前更新的字段名称:" + taskName);
+            if (!FIELD_NAME_TYPE_MAPPING.containsKey(taskName)) {
+                log.error("非文档映射内的字段,忽略");
+                return R.error().message("非文档映射内的字段,忽略"); // 非文档映射内的字段,忽略
+            }
+
+            /*根据项目id,查询项目概览自定义字段列表中「自定义字段」id*/
+            String xmzdyzdid = getXiangmuZidingyiziduanid(projectId, taskName);
+            if (xmzdyzdid != null){
+                log.info("【根据项目id,查询项目概览自定义字段列表中「自定义字段」id】不为空,开始执行后续业务===》");
+                /*更新项目概览自定义字段*/
+                JSONObject jsonObject2 = updateXmCustomField(operatorId, projectId, xmzdyzdid, customfieldValue);
+                int code = jsonObject2.getInteger("code");
+                System.out.println("【更新项目自定义字段值】接口返回的状态码(200成功,400异常):" + code);
+                if (code == 200){
+                    log.info("【更新项目自定义字段值】成功!");
+                    return R.ok().message("更新项目自定义字段值成功");
+                }else {
+                    String errorMessage = jsonObject2.getString("errorMessage");
+                    System.out.println("【更新项目自定义字段值】接口返回的异常错误信息:" + errorMessage);
+
+                    log.error("【更新项目自定义字段值】失败!");
+                    return R.error().message("更新项目自定义字段值失败,异常错误信息【" + errorMessage + "】");
+                }
+            }else{
+                log.error("【根据项目id,查询项目概览自定义字段列表中「自定义字段」id】为空,结束执行后续业务!");
+                return R.error().message("根据项目id,查询项目概览自定义字段列表中「自定义字段」id为空,结束执行后续业务!");
+            }
+        }else if (event.equals("v3.task.executor.update")){//======任务执行者更新======
+            log.info("【任务执行者更新】,开始执行===》");
+            JSONObject data = jsonObject.getJSONObject("data");
+            System.out.println("任务信息data:" + data);
+
+            //任务id
+            String taskId = data.getString("taskId");
+            System.out.println("任务id:" + taskId);
+            //操作者id
+            String operatorId = data.getString("creatorId");
+            System.out.println("操作者id:" + operatorId);
+            //更新后的执行者id
+            String executorId = data.getString("executorId") != null ? data.getString("executorId") : "";
+            System.out.println("更新后的执行者id:" + executorId);
+            /*根据任务id查询任务所属的项目id*/
+            JSONArray renwuxiangqing = getRenwuxiangqing(taskId);
+            //项目id
+            String projectId = null;
+            if (!renwuxiangqing.isEmpty() || renwuxiangqing != null) {
+                JSONObject jsonObject1 = renwuxiangqing.getJSONObject(0);
+                //项目id
+                projectId = jsonObject1.getString("projectId");
+                System.out.println("项目id:" + projectId);
+            }
+            if (projectId == null){
+                log.error("根据任务id查询所属项目id为空");
+                return R.error().message("根据任务id查询所属项目id为空");
+            }
+
+            /*根据任务id查询任务类型*/
+            JSONArray renwuxiangqingArray = getRenwuxiangqing(taskId);
+            //任务类型id
+            String renwuleixingid = null;
+            if (!renwuxiangqingArray.isEmpty() || renwuxiangqingArray != null) {
+                JSONObject jsonObject1 = renwuxiangqingArray.getJSONObject(0);
+                //当前任务类型id
+                renwuleixingid = jsonObject1.getString("sfcId");
+                System.out.println("当前任务类型id:" + renwuleixingid);
+                /*通过任务类型id搜索项目任务类型*/
+                JSONArray qiyeTaskType = getQiyeTaskType(projectId, renwuleixingid);
+                //任务类型名称
+                String sfcName = null;
+                if (!qiyeTaskType.isEmpty() || qiyeTaskType != null) {
+                    JSONObject jsonObject3 = qiyeTaskType.getJSONObject(0);
+                    //任务类型名称
+                    sfcName = jsonObject3.getString("name");
+                    System.out.println("任务类型名称:" + sfcName);
+                    if (!FIELD_USER_TYPE_MAPPING.containsKey(sfcName)) {
+                        log.error("非文档映射内的任务类型,忽略");
+                        return R.error().message("非文档映射内的任务类型,忽略"); // 非文档映射内的字段,忽略
+                    }else {
+                        String typeByFieldName = getTypeByFieldName(sfcName);
+                        log.info("当前任务类型匹配的项目概览成员字段名称:" + typeByFieldName);
+
+                        /*根据项目id,查询项目概览自定义字段列表中「自定义字段」id*/
+                        String xmzdyzdid = getXiangmuZidingyiziduanid(projectId, typeByFieldName);
+                        if (xmzdyzdid != null){
+                            log.info("【根据项目id,查询项目概览自定义字段列表中「自定义字段」id】不为空,开始执行后续业务===》");
+                            /*更新项目概览自定义字段*/
+                            Map mapTitle = new HashMap();
+                            mapTitle.put("id", executorId);
+                            String title = null;
+                            if (!executorId.equals("")){
+                                title = "系统同步";
+                            }
+                            mapTitle.put("title", title);//TB成员字段传TBuserId,title默认空即可,也可匹配到TB中的人员进行写入成员字段
+                            List listTitle = new ArrayList();
+                            listTitle.add(mapTitle);
+                            JSONObject jsonObject2 = updateXmCustomField(operatorId, projectId, xmzdyzdid, listTitle);
+                            int code = jsonObject2.getInteger("code");
+                            System.out.println("【更新项目自定义字段值】接口返回的状态码(200成功,400异常):" + code);
+                            if (code == 200){
+                                log.info("【更新项目自定义字段值】成功!");
+                                return R.ok().message("更新项目自定义字段值成功");
+                            }else {
+                                String errorMessage = jsonObject2.getString("errorMessage");
+                                System.out.println("【更新项目自定义字段值】接口返回的异常错误信息:" + errorMessage);
+
+                                log.error("【更新项目自定义字段值】失败!");
+                                return R.error().message("更新项目自定义字段值失败,异常错误信息【" + errorMessage + "】");
+                            }
+                        }else{
+                            log.error("【根据项目id,查询项目概览自定义字段列表中「自定义字段」id】为空,结束执行后续业务!");
+                            return R.error().message("根据项目id,查询项目概览自定义字段列表中「自定义字段」id为空,结束执行后续业务!");
+                        }
+                    }
+                }else {
+                    log.error("通过任务类型id搜索企业任务类型名称为空!");
+                    return R.error().message("通过任务类型id搜索企业任务类型名称为空!");
+                }
+            }else {
+                log.error("根据任务id查询任务类型为空!");
+                return R.error().message("根据任务id查询任务类型为空!");
+            }
+        }else {
+            log.error("当前事件不属于任务自定义字段/任务执行者更新,结束执行后续业务!");
+            return R.error().message("当前事件不属于任务自定义字段/任务执行者更新,结束执行后续业务!");
+        }
+    }
+}

+ 61 - 0
src/main/resources/application.properties

@@ -0,0 +1,61 @@
+server.port=8122
+server.servlet.context-path=/api/duohui
+
+server.tomcat.uri-encoding=UTF-8
+
+dingtalk.app-key=${DINGTALK_APP_KEY:}
+dingtalk.app-secret=${DINGTALK_APP_SECRET:}
+teambition.app-id=${TEAMBITION_APP_ID:}
+teambition.app-secret=${TEAMBITION_APP_SECRET:}
+
+#?????????
+ribbon:
+    ReadTimeoutMillis: 5000
+    ConnectTimeoutMillis: 5000
+
+## 服务名
+#spring.application.name=simaner-yd
+## 环境设置:dev、test、prod(开发环境、测试环境、生产环境)
+#spring.profiles.active=dev
+
+# mysql数据库连接
+# 本地测试数据库
+#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+#spring.datasource.url=jdbc:mysql://localhost:3306/dingtalk?serverTimezone=GMT%2B8
+#spring.datasource.username=root
+#spring.datasource.password=${DB_PASSWORD}
+
+#定时同步
+
+#配置日志,当前为默认的控制台输出,也可以用log4j
+#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
+
+#控制台显示sql
+#spring.jpa.show-sql=true
+#更新或者创建数据表结构
+#spring.jpa.hibernate.ddl-auto=update
+
+#返回json的全局时间格式
+spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+spring.jackson.time-zone=GMT+8
+#配置mapper xml文件的路径
+#mybatis-plus.mapper-locations=classpath:com/muzhi/lz/mapper/xml/*.xml
+
+#mybatis-plus.config-location=classpath:mybatis/mybatis-config.xml
+
+#禁用缓存
+spring.thymeleaf.cache=false
+#spring.thymeleaf.mode= LEGACYHTML5
+#spring.resources.chain.strategy.content.enabled=true
+#spring.resources.chain.strategy.content.paths=/**
+#spring.thymeleaf.check-template = true
+#spring.thymeleaf.servlet.content-type=text/html
+#spring.thymeleaf.enabled = true
+#spring.thymeleaf.encoding = UTF-8
+#spring.thymeleaf.prefix = classpath:/static/
+#spring.thymeleaf.suffix = .html
+
+#定义日期提交的格式(日期的格式化):SpingMVC将页面提交的值需要转换为指定类型;默认的是yyyy/MM/dd
+#spring.mvc.date-format=yyyy-MM-dd
+
+spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/templates/

+ 225 - 0
src/test/java/com/muzhi/duohui/APITest/Test1.java

@@ -0,0 +1,225 @@
+package com.muzhi.duohui.APITest;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.dingtalkyida_1_0.models.SearchFormDatasResponse;
+import com.aliyun.dingtalkyida_2_0.models.CreateOrUpdateFormDataResponse;
+import com.aliyun.dingtalkyida_2_0.models.GetFormDataByIDResponse;
+import com.aliyun.tea.TeaException;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.muzhi.duohui.service.AccessTokenService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.*;
+
+@SpringBootTest
+@Slf4j
+public class Test1 {
+
+    @Autowired
+    private AccessTokenService accessTokenService;
+
+    public static com.aliyun.dingtalkworkflow_1_0.Client createClient() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkworkflow_1_0.Client(config);
+    }
+
+    public static com.aliyun.dingtalkyida_2_0.Client createClient2() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkyida_2_0.Client(config);
+    }
+
+    //宜搭接口调用
+    public static com.aliyun.dingtalkyida_1_0.Client createClient3() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkyida_1_0.Client(config);
+    }
+
+    @Test
+    public void test1(){
+        JSONObject jsonObject2 = null;
+        try {
+            com.aliyun.dingtalkyida_2_0.Client client = createClient2();
+            com.aliyun.dingtalkyida_2_0.models.CreateOrUpdateFormDataHeaders createOrUpdateFormDataHeaders = new com.aliyun.dingtalkyida_2_0.models.CreateOrUpdateFormDataHeaders();
+            createOrUpdateFormDataHeaders.xAcsDingtalkAccessToken = accessTokenService.getAccessToken();
+            com.aliyun.dingtalkyida_2_0.models.CreateOrUpdateFormDataRequest createOrUpdateFormDataRequest = new com.aliyun.dingtalkyida_2_0.models.CreateOrUpdateFormDataRequest()
+                    .setSystemToken(System.getenv("DINGTALK_SYSTEM_TOKEN"))
+                    .setFormUuid("FORM-BD31E2C07C7448DD931F686A5D881E96DQV8")
+                    .setUserId("yida_pub_account")
+                    .setSearchCondition("[{\"componentName\":\"TextField\",\"type\":\"TEXT\",\"value\":\"BC2000029\",\"key\":\"textField_maw7b9k0\",\"operator\":\"eq\"}]")
+                    .setAppType("APP_FJSLK9BJ20K1NL3G2PUW")
+                    .setFormDataJson("{\"selectField_lqesy4t1\":\"D\",\"textField_maw7b9k0\":\"BC2000029\",\"textField_lqesy4sy\":\"KETTLER Alu-Rad GmbH\",\"textField_mh8j17hy\":\"袁铷玥\"}");
+
+            CreateOrUpdateFormDataResponse orUpdateFormDataWithOptions = client.createOrUpdateFormDataWithOptions(createOrUpdateFormDataRequest, createOrUpdateFormDataHeaders, new RuntimeOptions());
+            String s = JSON.toJSONString(orUpdateFormDataWithOptions.getBody());
+            jsonObject2 = JSON.parseObject(s);
+            System.out.println("【创建或更新】表单object对象:" + jsonObject2);
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+        }
+    }
+
+    @Test
+    public void test2(){
+        try {
+            com.aliyun.dingtalkyida_2_0.Client client = createClient2();
+            com.aliyun.dingtalkyida_2_0.models.GetFormDataByIDHeaders getFormDataByIDHeaders = new com.aliyun.dingtalkyida_2_0.models.GetFormDataByIDHeaders();
+            getFormDataByIDHeaders.xAcsDingtalkAccessToken = accessTokenService.getAccessToken();
+            com.aliyun.dingtalkyida_2_0.models.GetFormDataByIDRequest getFormDataByIDRequest = new com.aliyun.dingtalkyida_2_0.models.GetFormDataByIDRequest()
+                    .setSystemToken(System.getenv("DINGTALK_SYSTEM_TOKEN"))
+                    .setUserId("yida_pub_account")
+                    .setAppType("APP_FJSLK9BJ20K1NL3G2PUW");
+
+            GetFormDataByIDResponse formDataByIDWithOptions = client.getFormDataByIDWithOptions("FINST-R8E66381FS30I83TKR2W4DO14O8V35TY6QBHM5NH", getFormDataByIDRequest, getFormDataByIDHeaders, new RuntimeOptions());
+            String s = JSON.toJSONString(formDataByIDWithOptions.getBody());
+            JSONObject jsonObject = JSON.parseObject(s);
+            System.out.println("【查询】表单object对象:" + jsonObject);
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+
+        }
+    }
+
+    @Test
+    public void test3(){
+        try {
+            com.aliyun.dingtalkyida_2_0.Client client = createClient2();
+            com.aliyun.dingtalkyida_2_0.models.UpdateSubTableHeaders updateSubTableHeaders = new com.aliyun.dingtalkyida_2_0.models.UpdateSubTableHeaders();
+            updateSubTableHeaders.xAcsDingtalkAccessToken = accessTokenService.getAccessToken();
+            com.aliyun.dingtalkyida_2_0.models.UpdateSubTableRequest updateSubTableRequest = new com.aliyun.dingtalkyida_2_0.models.UpdateSubTableRequest()
+                    .setSystemToken(System.getenv("DINGTALK_SYSTEM_TOKEN"))
+                    .setFormInstanceId("FINST-R8E66381FS30I83TKR2W4DO14O8V35TY6QBHM5NH")
+                    .setUserId("yida_pub_account")
+                    .setTableFieldIds("tableField_lqesy4t4")
+                    .setUpdateFormDataJson("{     \"tableField_lqesy4t4\": [         {             \"textField_makozait\": \"0519-68198299\",             \"textField_lqesy4t7\": \"\",             \"textField_lqesy4t6\": \"\"         }     ] }")
+                    .setAppType("APP_FJSLK9BJ20K1NL3G2PUW");
+
+            client.updateSubTableWithOptions(updateSubTableRequest, updateSubTableHeaders, new com.aliyun.teautil.models.RuntimeOptions());
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+
+        }
+    }
+
+
+    @Test
+    public void test4(){
+
+        JSONObject jsonObject = null;
+
+        int size = 100;
+        int page = 1;
+
+        //TODO 指定筛选信息
+        Map mapAll = new HashMap();
+        //TB项目id
+        mapAll.put("textField_lqxtykce", "6912e527d299b1cc63ab2960");
+        String mapAllStr = JSON.toJSONString(mapAll);
+        System.out.println("封装查询的字段参数:" + mapAllStr);
+
+        //LEV项目档案的实例id
+        String slid_lev = null;
+        do {
+
+            try {
+                com.aliyun.dingtalkyida_1_0.Client client = createClient3();
+                com.aliyun.dingtalkyida_1_0.models.SearchFormDatasHeaders searchFormDatasHeaders = new com.aliyun.dingtalkyida_1_0.models.SearchFormDatasHeaders();
+                searchFormDatasHeaders.xAcsDingtalkAccessToken = accessTokenService.getAccessToken();
+                com.aliyun.dingtalkyida_1_0.models.SearchFormDatasRequest searchFormDatasRequest = new com.aliyun.dingtalkyida_1_0.models.SearchFormDatasRequest()
+                        .setSystemToken(System.getenv("DINGTALK_SEARCH_SYSTEM_TOKEN"))
+
+                        .setSearchFieldJson(mapAllStr)
+
+                        .setCurrentPage(page)
+                        .setPageSize(size)
+                        .setFormUuid("FORM-2CC97D2F8D7D4F7C925538CC5758755DOA4W")
+                        .setUserId("yida_pub_account")
+                        .setAppType("APP_H2HQQ5I9E0HHGHAY7KSL");
+
+                SearchFormDatasResponse searchFormDatasResponse = client.searchFormDatasWithOptions(searchFormDatasRequest, searchFormDatasHeaders, new RuntimeOptions());
+//                System.out.println(JSON.toJSONString(searchFormDatasResponse.getBody()));
+                String s = JSON.toJSONString(searchFormDatasResponse.getBody());
+                jsonObject = JSON.parseObject(s);
+//                System.out.println("宜搭数据高级条件查询【IPD项目档案】接口object对象:" + jsonObject);
+            } catch (TeaException err) {
+                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                    // err 中含有 code 和 message 属性,可帮助开发定位问题
+                }
+
+            } catch (Exception _err) {
+                TeaException err = new TeaException(_err.getMessage(), _err);
+                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                    // err 中含有 code 和 message 属性,可帮助开发定位问题
+                }
+
+            }
+
+            JSONArray data = jsonObject.getJSONArray("data");
+//            System.out.println("返回的宜搭data:" + data);
+
+            if (data.isEmpty()) {
+                System.out.println("查询【IPD项目档案】返回数据为空!");
+            } else {
+                for (int i = 0; i < data.size(); i++) {
+                    JSONObject formData = data.getJSONObject(i).getJSONObject("formData");
+                    Map map = new HashMap<>();
+
+                    //实例ID
+                    String shiliID = data.getJSONObject(i).getString("formInstanceId");
+                    System.out.println("实例ID===>" + shiliID);
+
+                    //LEV项目档案的实例id
+                    slid_lev = null;
+                    try {
+                        slid_lev = formData.getString("textField_lrj7vnxf") != null ? formData.getString("textField_lrj7vnxf") : null;
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }
+                    System.out.println("LEV项目档案的实例id:" + slid_lev);
+                }
+            }
+
+            if (jsonObject.getFloat("totalCount") / 100 > jsonObject.getInteger("currentPage")){
+                page = page + 1;
+                System.out.println("下一次待查询分页:" + page);
+            }
+
+        }while (jsonObject.getFloat("totalCount") / 100 > jsonObject.getInteger("currentPage"));
+
+        System.out.println("根据TB项目id查询【IPD项目档案】匹配到的LEV项目档案数据实例id:" + slid_lev);
+    }
+
+}

+ 59 - 0
src/test/java/com/muzhi/duohui/APITest/Test2.java

@@ -0,0 +1,59 @@
+package com.muzhi.duohui.APITest;
+
+import com.muzhi.duohui.service.AccessTokenService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+@Slf4j
+public class Test2 {
+
+    @Autowired
+    private AccessTokenService accessTokenService;
+
+    public static com.aliyun.dingtalkworkflow_1_0.Client createClient() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkworkflow_1_0.Client(config);
+    }
+
+    public static com.aliyun.dingtalkyida_2_0.Client createClient2() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkyida_2_0.Client(config);
+    }
+
+    //宜搭接口调用
+    public static com.aliyun.dingtalkyida_1_0.Client createClient3() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkyida_1_0.Client(config);
+    }
+
+    @Test
+    public void test1(){
+
+    }
+
+    @Test
+    public void test2(){
+
+    }
+
+    @Test
+    public void test3(){
+
+    }
+
+
+    @Test
+    public void test4(){
+
+    }
+
+}

+ 13 - 0
src/test/java/com/muzhi/duohui/TestApplicationTests.java

@@ -0,0 +1,13 @@
+package com.muzhi.duohui;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TestApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}