koul 1 tahun lalu
induk
melakukan
381e5a71e6

+ 10 - 1
pom.xml

@@ -111,7 +111,16 @@
 			<groupId>org.apache.httpcomponents</groupId>
 			<artifactId>httpmime</artifactId>
 		</dependency>
-
+		<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>dingtalk</artifactId>
+			<version>1.2.15</version>
+		</dependency>
+		<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>alibaba-dingtalk-service-sdk</artifactId>
+			<version>2.0.0</version>
+		</dependency>
 		<dependency>
 			<groupId>org.oracle</groupId>
 			<artifactId>oracle</artifactId>

+ 39 - 0
src/main/java/com/uas/eis/config/AsyncConfig.java

@@ -0,0 +1,39 @@
+package com.uas.eis.config;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @Author: zhouy
+ * @Date: 2020/5/22 13:43
+ */
+@Configuration
+@EnableAsync  // 启用异步任务
+public class AsyncConfig {
+    // 声明一个线程池(并指定线程池的名字)
+    @Bean("taskExecutor")
+    public Executor asyncExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        //核心线程数10:线程池创建时候初始化的线程数
+        executor.setCorePoolSize(2);
+        //最大线程数20:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
+        executor.setMaxPoolSize(20);
+        //缓冲队列500:用来缓冲执行任务的队列
+        executor.setQueueCapacity(1000);
+        //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
+        executor.setKeepAliveSeconds(60);
+        //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
+        executor.setThreadNamePrefix("DailyAsync-");
+        //所有任务处理完毕开始关闭线程池
+        executor.setWaitForTasksToCompleteOnShutdown(true);
+        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
+        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.initialize();
+        return executor;
+    }
+}

+ 30 - 0
src/main/java/com/uas/eis/core/config/DataCache.java

@@ -0,0 +1,30 @@
+package com.uas.eis.core.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+ 
+public class DataCache {
+    private final Map<String, Object> cache = new HashMap<>();
+    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+ 
+    public DataCache() {
+        // 启动定时任务,每2小时清空缓存
+        scheduler.scheduleAtFixedRate(this::clearCache, 2, 2, TimeUnit.HOURS);
+    }
+ 
+    public void addToCache(String key, Object value) {
+        cache.put(key, value);
+    }
+ 
+    public Object getFromCache(String key) {
+        return cache.get(key);
+    }
+ 
+    private void clearCache() {
+        cache.clear();
+        System.out.println("Cache cleared at: " + System.currentTimeMillis());
+    }
+}

+ 395 - 0
src/main/java/com/uas/eis/core/config/DingCallbackCrypto.java

@@ -0,0 +1,395 @@
+package com.uas.eis.core.config;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.Arrays;
+import java.util.HashMap;
+import  java.util.Map ;
+import java.util.Random;
+import  java.security.Security ;
+import java.lang.reflect.Field;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+/**
+ * DingTalk open platform encryption and decryption method
+ * Download JCE Unrestricted Permission Policy File from ORACLE Official Website
+ */
+
+public class DingCallbackCrypto {
+    private static final Charset CHARSET = Charset.forName("utf-8");
+    private static final Base64 base64 = new Base64();
+    private byte[] aesKey;
+    private  String  token ;
+    private String corpId;
+    /**
+     * ask getPaddingBytes key fixed length
+     **/
+    private static final Integer AES_ENCODE_KEY_LENGTH = 43;
+    /**
+     * Encrypted random string byte length
+     **/
+    private static final Integer RANDOM_LENGTH = 16;
+
+    /**
+     * Constructor
+     *
+     * @param token On the DingTalk open platform, the token set by the developer
+     * @param encodingAesKey The EncodingAESKey set by the developer on the DingTalk open platform
+     * @param corpId Enterprise self-built application-event subscription, use appKey
+     * Enterprise self-built application - register callback address, use corpId
+     * Third-party enterprise applications, use suiteKey
+     *
+     * @throws DingTalkEncryptException failed to execute, please check the exception's error code and specific error message
+     */
+    public DingCallbackCrypto(String token, String encodingAesKey, String corpId) throws DingTalkEncryptException {
+        if (null == encodingAesKey || encodingAesKey.length() != AES_ENCODE_KEY_LENGTH) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.AES_KEY_ILLEGAL);
+        }
+        this.token = token;
+        this.corpId = corpId;
+        aesKey = Base64.decodeBase64(encodingAesKey + "=");
+    }
+
+    public Map<String, String> getEncryptedMap(String plaintext) throws DingTalkEncryptException {
+        return getEncryptedMap(plaintext, System.currentTimeMillis(), Utils.getRandomStr(16));
+    }
+
+    /**
+     * Encrypt the message body synchronized with the DingTalk open platform and return the encrypted Map
+     *
+     * @param plaintext The message body plaintext passed
+     * @param timeStamp timestamp
+     * @param nonce random string
+     * @return
+     * @throws DingTalkEncryptException
+     */
+    public Map<String, String> getEncryptedMap(String plaintext, Long timeStamp, String nonce)
+            throws DingTalkEncryptException {
+        if (null == plaintext) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL);
+        }
+        if (null == timeStamp) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_TIMESTAMP_ILLEGAL);
+        }
+        if (null == nonce) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_NONCE_ILLEGAL);
+        }
+        // encrypt
+        String encrypt = encrypt(Utils.getRandomStr(RANDOM_LENGTH), plaintext);
+        String signature = getSignature(token, String.valueOf(timeStamp), nonce, encrypt);
+        Map<String, String> resultMap = new HashMap<String, String>();
+        resultMap.put("msg_signature", signature);
+        resultMap.put("encrypt", encrypt);
+        resultMap.put("timeStamp", String.valueOf(timeStamp));
+        resultMap.put("nonce", nonce);
+        return resultMap;
+    }
+
+    /**
+     * ciphertext decryption
+     *
+     * @param msgSignature signature string
+     * @param timeStamp timestamp
+     * @param nonce random string
+     * @param encryptMsg ciphertext
+     * @return decrypted original text
+     * @throws DingTalkEncryptException
+     */
+    public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg)
+            throws DingTalkEncryptException {
+        //check signature
+        String signature = getSignature(token, timeStamp, nonce, encryptMsg);
+        if (!signature.equals(msgSignature)) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
+        }
+        // decrypt
+        String result = decrypt(encryptMsg);
+        return result;
+    }
+
+    /*
+     * Encrypt plaintext.
+     * @param text The plaintext to be encrypted
+     * @return encrypted base64 encoded string
+     */
+    private String encrypt(String random, String plaintext) throws DingTalkEncryptException {
+        try {
+            byte[] randomBytes = random.getBytes(CHARSET);
+            byte[] plainTextBytes = plaintext.getBytes(CHARSET);
+            byte[] lengthByte = Utils.int2Bytes(plainTextBytes.length);
+            byte[] corpidBytes = corpId.getBytes(CHARSET);
+            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+            byteStream.write(randomBytes);
+            byteStream.write(lengthByte);
+            byteStream.write(plainTextBytes);
+            byteStream.write(corpidBytes);
+            byte[] padBytes = PKCS7Padding.getPaddingBytes(byteStream.size());
+            byteStream.write(padBytes);
+            byte[] unencrypted = byteStream.toByteArray();
+            byteStream.close();
+            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+            SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+            IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
+            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+            byte[] encrypted = cipher.doFinal(unencrypted);
+            String result = base64.encodeToString(encrypted);
+            return result;
+        } catch ( Exception  e ) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR);
+        }
+    }
+
+    /*
+     * Decrypt the ciphertext.
+     * @param text The ciphertext to decrypt
+     * @return decrypted plaintext
+     */
+    private String decrypt(String text) throws DingTalkEncryptException {
+        byte [] originalArr ;
+        try {
+            // Set the decryption mode to CBC mode of AES
+            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+            SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
+            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
+            // Decode the ciphertext using BASE64
+            byte[] encrypted = Base64.decodeBase64(text);
+            // decrypt
+            originalArr = cipher.doFinal(encrypted);
+        } catch ( Exception  e ) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
+        }
+
+        String plainText;
+        String fromCorpid;
+        try {
+            // remove the complement character
+            byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
+            // Separate 16-bit random string, network byte order and corpId
+            byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
+            int plainTextLegth = Utils.bytes2int(networkOrder);
+            plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
+            fromCorpid = new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);
+        } catch ( Exception  e ) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);
+        }
+
+        // When the corpids are not the same
+        if (!fromCorpid.equals(corpId)) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);
+        }
+        return plainText;
+    }
+
+    /**
+     * digital signature
+     *
+     * @param token     isv token
+     * @param timestamp timestamp
+     * @param nonce random string
+     * @param encrypt encrypted text
+     * @return
+     * @throws DingTalkEncryptException
+     */
+    public String getSignature(String token, String timestamp, String nonce, String encrypt)
+            throws DingTalkEncryptException {
+        try {
+            String[] array = new String[] {token, timestamp, nonce, encrypt};
+            Arrays.sort(array);
+//            System.out.println(JSON.toJSONString(array));
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < 4; i++) {
+                sb.append(array[i]);
+            }
+            String str = sb.toString();
+//            System.out.println(str);
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            md.update(str.getBytes());
+            byte[] digest = md.digest();
+
+            StringBuffer hexstr = new StringBuffer();
+            String shaHex = "";
+            for (int i = 0; i < digest.length; i++) {
+                shaHex = Integer.toHexString(digest[i] & 0xFF);
+                if (shaHex.length() < 2) {
+                    hexstr.append(0);
+                }
+                hexstr.append(shaHex);
+            }
+            return hexstr.toString();
+        } catch ( Exception  e ) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
+        }
+    }
+
+    public static class Utils {
+        public  Utils () {
+        }
+
+        public static String getRandomStr(int count) {
+            String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+            Random random = new Random();
+            StringBuffer sb = new StringBuffer();
+
+            for (int i = 0; i < count; ++i) {
+                int number = random.nextInt(base.length());
+                sb.append(base.charAt(number));
+            }
+
+            return sb.toString();
+        }
+
+        public static byte[] int2Bytes(int count) {
+            byte[] byteArr = new byte[] {(byte)(count >> 24 & 255), (byte)(count >> 16 & 255), (byte)(count >> 8 & 255),
+                    (byte)(count & 255)};
+            return byteArr;
+        }
+
+        public static int bytes2int(byte[] byteArr) {
+            int count = 0;
+
+            for (int i = 0; i < 4; ++i) {
+                count <<= 8;
+                count |= byteArr[i] & 255;
+            }
+
+            return count;
+        }
+    }
+
+    public static class PKCS7Padding {
+        private static final Charset CHARSET = Charset.forName("utf-8");
+        private static final int BLOCK_SIZE = 32;
+
+        public PKCS7Padding() {
+        }
+
+        public static byte[] getPaddingBytes(int count) {
+            int amountToPad = 32 - count % 32;
+            if (amountToPad == 0) {
+                amountToPad = 32;
+            }
+
+            char padChr = chr(amountToPad);
+            String tmp = new String();
+
+            for (int index = 0; index < amountToPad; ++index) {
+                tmp = tmp + padChr;
+            }
+
+            return tmp.getBytes(CHARSET);
+        }
+
+        public static byte[] removePaddingBytes(byte[] decrypted) {
+            int pad = decrypted[decrypted.length - 1];
+            if (pad < 1 || pad > 32) {
+                pad = 0;
+            }
+
+            return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
+        }
+
+        private  static  char  chr ( int  a ) {
+            byte target = (byte)(a & 255);
+            return (char)target;
+        }
+    }
+
+    public static class DingTalkEncryptException extends Exception {
+        public static final int SUCCESS = 0;
+        public static final int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
+        public static final int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
+        public static final int ENCRYPTION_NONCE_ILLEGAL = 900003;
+        public static final int AES_KEY_ILLEGAL = 900004;
+        public static final int SIGNATURE_NOT_MATCH = 900005;
+        public static final int COMPUTE_SIGNATURE_ERROR = 900006;
+        public static final int COMPUTE_ENCRYPT_TEXT_ERROR = 900007;
+        public static final int COMPUTE_DECRYPT_TEXT_ERROR = 900008;
+        public static final int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009;
+        public static final int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010;
+        private static Map<Integer, String> msgMap = new HashMap();
+        private  Integer  code ;
+
+        static {
+            msgMap .put ( 0 , " success" ) ;
+            msgMap.put ( 900001 , " Illegal encrypted plaintext" ) ;
+            msgMap.put ( 900002 , " Illegal encryption timestamp parameter" ) ;
+            msgMap.put ( 900003 , " The encrypted random string parameter is illegal" );
+            msgMap.put ( 900005 , "Signature mismatch " ) ;
+            msgMap.put ( 900006 , " Signature calculation failed" ) ;
+            msgMap .put ( 900004 , " Illegal aes key" );
+            msgMap.put ( 900007 , " Error computing encrypted text" ) ;
+            msgMap.put ( 900008 , " Error computing decrypted text" ) ;
+            msgMap.put ( 900009 , " Calculation of decrypted text length does not match" );
+            msgMap.put ( 900010 , "Compute decrypted literal corpid does not match" );
+        }
+
+        public  Integer  getCode () {
+            return this.code;
+        }
+
+        public DingTalkEncryptException(Integer exceptionCode) {
+            super((String)msgMap.get(exceptionCode));
+            this.code = exceptionCode;
+        }
+    }
+    static {
+        try {
+            Security.setProperty("crypto.policy", "limited");
+            RemoveCryptographyRestrictions();
+        } catch (Exception var1) {
+        }
+
+    }
+    private static void RemoveCryptographyRestrictions() throws Exception {
+        Class<?> jceSecurity = getClazz("javax.crypto.JceSecurity");
+        Class<?> cryptoPermissions = getClazz("javax.crypto.CryptoPermissions");
+        Class<?> cryptoAllPermission = getClazz("javax.crypto.CryptoAllPermission");
+        if (jceSecurity != null) {
+            setFinalStaticValue(jceSecurity, "isRestricted", false);
+            PermissionCollection defaultPolicy = (PermissionCollection)getFieldValue(jceSecurity, "defaultPolicy", (Object)null, PermissionCollection.class);
+            if (cryptoPermissions != null) {
+                Map<?, ?> map = (Map)getFieldValue(cryptoPermissions, "perms", defaultPolicy, Map.class);
+                map.clear();
+            }
+
+            if (cryptoAllPermission != null) {
+                Permission permission = (Permission)getFieldValue(cryptoAllPermission, "INSTANCE", (Object)null, Permission.class);
+                defaultPolicy.add(permission);
+            }
+        }
+
+    }
+    private static Class<?> getClazz(String className) {
+        Class clazz = null;
+
+        try {
+            clazz = Class.forName(className);
+        } catch (Exception var3) {
+        }
+
+        return  clazz ;
+    }
+    private static void setFinalStaticValue(Class<?> srcClazz, String fieldName, Object newValue) throws Exception {
+        Field field = srcClazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        Field modifiersField = Field.class.getDeclaredField("modifiers");
+        modifiersField.setAccessible(true);
+        modifiersField.setInt(field, field.getModifiers() & -17);
+        field.set((Object)null, newValue);
+    }
+    private static <T> T getFieldValue(Class<?> srcClazz, String fieldName, Object owner, Class<T> dstClazz) throws Exception {
+        Field field = srcClazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        return dstClazz.cast(field.get(owner));
+    }
+}
+

+ 61 - 0
src/main/java/com/uas/eis/core/support/SpringDynamicCronTask.java

@@ -0,0 +1,61 @@
+package com.uas.eis.core.support;
+
+
+import com.uas.eis.task.ScheduleTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+
+@Configuration
+@EnableScheduling
+@Component
+public class SpringDynamicCronTask implements SchedulingConfigurer {
+
+	private final Logger logger = LoggerFactory.getLogger(this.getClass());
+	@Autowired
+	private Environment env;
+	@Autowired
+	private ScheduleTask scheduleTask;
+	@Override
+	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+		String activeProFiles = env.getActiveProfiles()[0];
+		if("prod".equals(activeProFiles)) {
+			logger.info("运行环境:%s;注册TASK:%s");
+			taskRegistrar.addCronTask(() -> {
+				//业务逻辑
+				try {
+					Method method = scheduleTask.getClass().getMethod(env.getProperty("Task.getVacationMethod"));
+					method.invoke(scheduleTask);
+				}catch (Exception e){
+					e.printStackTrace();
+				}
+			}, env.getProperty("Task.getVacationCron"));
+            taskRegistrar.addCronTask(() -> {
+                //业务逻辑
+                try {
+                    Method method = scheduleTask.getClass().getMethod(env.getProperty("Task.getCCSQMethod"));
+                    method.invoke(scheduleTask);
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }, env.getProperty("Task.getCCSQCron"));
+			taskRegistrar.addCronTask(() -> {
+				//业务逻辑
+				try {
+					Method method = scheduleTask.getClass().getMethod(env.getProperty("Task.getExtraWorkMethod"));
+					method.invoke(scheduleTask);
+				}catch (Exception e){
+					e.printStackTrace();
+				}
+			}, env.getProperty("Task.getExtraWorkCron"));
+		}
+	}
+}

+ 45 - 0
src/main/java/com/uas/eis/service/Impl/ScheduleTaskServiceImpl.java

@@ -0,0 +1,45 @@
+package com.uas.eis.service.Impl;
+
+import com.uas.eis.dao.BaseDao;
+import com.uas.eis.service.ScheduleTaskService;
+import com.uas.eis.utils.OaUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+
+@Service
+public class ScheduleTaskServiceImpl implements ScheduleTaskService {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+
+
+    @Autowired
+    private BaseDao baseDao;
+    @Autowired
+    private OaUtils oaUtils;
+
+    @Override
+    public void getVacation() {
+        try {
+            String aeecssToken = oaUtils.getAeecssToken();
+            System.err.println(aeecssToken);
+            Map<String, String> processInsList = oaUtils.getProcessInsList("dcdf1a24b74b3303845761d131c9cd76");
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void getCCSQ() {
+
+    }
+
+    @Override
+    public void getExtraWork() {
+
+    }
+}

+ 11 - 0
src/main/java/com/uas/eis/service/ScheduleTaskService.java

@@ -0,0 +1,11 @@
+package com.uas.eis.service;
+
+public interface ScheduleTaskService {
+
+    void getVacation();
+
+    void getCCSQ();
+
+    void getExtraWork();
+
+}

+ 52 - 0
src/main/java/com/uas/eis/task/ScheduleTask.java

@@ -0,0 +1,52 @@
+package com.uas.eis.task;
+
+import com.uas.eis.service.ScheduleTaskService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+@Component("scheduleTask")
+public class ScheduleTask {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private ScheduleTaskService scheduleTaskService;
+
+
+    /**
+     * 获取请假单
+     */
+    public void getVacation() {
+        logger.info("获取请假单开始");
+        Date date = new Date();
+        scheduleTaskService.getVacation();
+        logger.info("获取请假单结束:用时" + ((System.currentTimeMillis() - date.getTime()) / 1000));
+
+    }
+
+    /**
+     * 获取出差申请
+     */
+    public void getCCSQ() {
+        logger.info("获取出差申请开始");
+        Date date = new Date();
+        scheduleTaskService.getCCSQ();
+        logger.info("获取出差申请结束:用时" + ((System.currentTimeMillis() - date.getTime()) / 1000));
+
+    }
+
+    /**
+     * 获取加班申请
+     */
+    public void getExtraWork() {
+        logger.info("获取加班申请开始");
+        Date date = new Date();
+        scheduleTaskService.getExtraWork();
+        logger.info("获取加班申请结束:用时" + ((System.currentTimeMillis() - date.getTime()) / 1000));
+
+    }
+
+}

+ 78 - 0
src/main/java/com/uas/eis/utils/ApprovalResult.java

@@ -0,0 +1,78 @@
+package com.uas.eis.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.uas.eis.core.config.DingCallbackCrypto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import com.alibaba.fastjson.JSON;
+
+import java.util.Map;
+
+@RestController
+@RequestMapping("approval")
+public class ApprovalResult {
+
+    @Value("${dingTalk.appKey}")
+    private String appKey;
+    @Value("${dingTalk.callToken}")
+    private String callToken;
+    @Value("${dingTalk.callAesKey}")
+    private String callAesKey;
+
+    @Autowired
+    private OaUtils oaUtils;
+
+    @PostMapping
+    public Map<String, String> approval(@RequestParam(value = "msg_signature", required = false) String msg_signature,
+                                        @RequestParam(value = "timestamp", required = false) String timeStamp,
+                                        @RequestParam(value = "nonce", required = false) String nonce,
+                                        @RequestBody(required = false) JSONObject json){
+        try {
+            // 1. 从http请求中获取加解密参数
+
+            // 2. 使用加解密类型
+            // Constant.OWNER_KEY 说明:
+            // 1、开发者后台配置的订阅事件为应用级事件推送,此时OWNER_KEY为应用的APP_KEY。
+            // 2、调用订阅事件接口订阅的事件为企业级事件推送,
+            //      此时OWNER_KEY为:企业的appkey(企业内部应用)或SUITE_KEY(三方应用)
+            DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(callToken, callAesKey, appKey);
+            String encryptMsg = json.getString("encrypt");
+            String decryptMsg = callbackCrypto.getDecryptMsg(msg_signature, timeStamp, nonce, encryptMsg);
+
+            // 3. 反序列化回调事件json数据
+            JSONObject eventJson = JSON.parseObject(decryptMsg);
+            String eventType = eventJson.getString("EventType");
+
+            // 4. 根据EventType分类处理
+            if ("check_url".equals(eventType)) {
+                // 测试回调url的正确性
+                System.out.println("测试回调url的正确性");
+            } else if ("bpms_instance_change".equals(eventType)) {
+                // 处理审批事件 TODO
+                String processInstanceId = eventJson.get("processInstanceId").toString();
+                String aeecssToken = oaUtils.getAeecssToken();
+                Map<String, String> processInsDetail = oaUtils.getProcessInsDetail(processInstanceId, aeecssToken);
+                System.out.println("审批事件----------------->响应结果为----------------->");
+                System.out.println(aeecssToken);
+                System.out.println(processInsDetail);
+                System.out.println("审批事件结束----------------------------------------》");
+            } else {
+                // 添加其他已注册的
+                System.out.println("发生了:" + eventType + "事件");
+            }
+
+            // 5. 返回success的加密数据
+            Map<String, String> successMap = callbackCrypto.getEncryptedMap("success");
+            return successMap;
+
+        } catch (DingCallbackCrypto.DingTalkEncryptException | JsonProcessingException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
+

+ 145 - 0
src/main/java/com/uas/eis/utils/OaUtils.java

@@ -0,0 +1,145 @@
+package com.uas.eis.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiGettokenRequest;
+import com.dingtalk.api.request.OapiProcessinstanceCreateRequest;
+import com.dingtalk.api.request.OapiProcessinstanceGetRequest;
+import com.dingtalk.api.response.OapiGettokenResponse;
+import com.dingtalk.api.response.OapiProcessinstanceCreateResponse;
+import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.taobao.api.ApiException;
+import com.uas.eis.core.config.DataCache;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 钉钉OA审批工具类
+ */
+@Component
+public class OaUtils {
+
+    @Value("${dingTalk.appKey}")
+    private String appKey;
+    @Value("${dingTalk.appSecret}")
+    private String appSecret;
+
+    @Value("${dingTalk.api}")
+    private String url;
+
+    @Value("${dingTalk.processCode}")
+    private String processCode;
+
+    @Value("${dingTalk.originatorUserId}")
+    private String originatorUserId;
+
+    private ObjectMapper om=new ObjectMapper();
+    private static String cacheKey="token";
+    private static final String SEARCH_LEAVE_URL = "https://oapi.dingtalk.com/topapi/process/instance/list?access_token=%s";
+
+    /**
+     * 获取accessToken  有效期 2小时  频繁访问将限流 建议缓存
+     * @return
+     * @throws JsonProcessingException
+     */
+    public String getAeecssToken(){
+        DataCache cache = new DataCache();
+        try {
+            String accessToken = StringUtil.nvl(cache.getFromCache(cacheKey), "");
+            if ("".equals(accessToken)) {
+                DingTalkClient client = new DefaultDingTalkClient(url + "/gettoken");
+                OapiGettokenRequest req = new OapiGettokenRequest();
+                req.setHttpMethod("GET");
+                req.setAppkey(appKey);
+                req.setAppsecret(appSecret);
+                OapiGettokenResponse rsp = client.execute(req);
+                String str = rsp.getBody();
+                HashMap hashMap = om.readValue(str, HashMap.class);
+                accessToken = hashMap.get("access_token").toString();
+                cache.addToCache(cacheKey, accessToken);
+            }
+            return accessToken;
+        } catch (Exception e) {
+            cache.addToCache(cacheKey,null);
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取审批列表
+     * @return
+     * @throws ApiException
+     */
+    public Map<String,String> getProcessInsList(String acceToken) throws Exception {
+        Map<String,String> resultMap=new HashMap<>(2);
+        DingTalkClient client = new DefaultDingTalkClient(url+"/topapi/process/instance/list");
+        OapiProcessinstanceGetRequest req = new OapiProcessinstanceGetRequest();
+        req.setHttpMethod("GET");
+        OapiProcessinstanceGetResponse rsp = client.execute(req, acceToken);
+        String body = rsp.getBody();
+        HashMap map = om.readValue(body, HashMap.class);
+        HashMap pie =(HashMap) map.get("process_instance");
+        resultMap.put("status",pie.get("status").toString());
+        resultMap.put("result",pie.get("result").toString());
+        return resultMap;
+    }
+
+    /**
+     * 获取审批详情
+     * @return
+     * @throws ApiException
+     */
+    public Map<String,String> getProcessInsDetail(String insTanceId, String acceToken) throws Exception {
+        Map<String,String> resultMap=new HashMap<>(2);
+        DingTalkClient client = new DefaultDingTalkClient(url+"topapi/processinstance/get");
+        OapiProcessinstanceGetRequest req = new OapiProcessinstanceGetRequest();
+        req.setProcessInstanceId(insTanceId);
+        OapiProcessinstanceGetResponse rsp = client.execute(req, acceToken);
+        String body = rsp.getBody();
+        HashMap map = om.readValue(body, HashMap.class);
+        HashMap pie =(HashMap) map.get("process_instance");
+        resultMap.put("status",pie.get("status").toString());
+        resultMap.put("result",pie.get("result").toString());
+        return resultMap;
+    }
+
+    /**
+     * 发起审批
+     * @param acceToken
+     * @return
+     * @throws ApiException
+     */
+    public Map<String,String> createApproval(String acceToken) throws ApiException {
+        Map<String,String> result=new HashMap<>(2);
+        DingTalkClient client = new DefaultDingTalkClient(url+ "topapi/processinstance/create");
+        OapiProcessinstanceCreateRequest req = new OapiProcessinstanceCreateRequest();
+        req.setProcessCode(processCode);
+        req.setOriginatorUserId(originatorUserId);
+        // 若发起人属于跟部门 传 -1
+        req.setDeptId(-1L);
+
+        //单行输入框
+        List<OapiProcessinstanceCreateRequest.FormComponentValueVo> formComponentValueVoList = new ArrayList<OapiProcessinstanceCreateRequest.FormComponentValueVo>();
+        OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
+        formComponentValueVoList.add(formComponentValueVo);
+        formComponentValueVo.setName("备注");
+        formComponentValueVo.setValue("代码创建审批测试");
+
+        req.setFormComponentValues(formComponentValueVoList);
+        OapiProcessinstanceCreateResponse rsp = client.execute(req, acceToken);
+        String str = JSON.toJSONString(rsp);
+        JSONObject eventJson = JSON.parseObject(str);
+        result.put("errcode",eventJson.get("errcode").toString());
+        result.put("processInstanceId",eventJson.get("processInstanceId").toString());
+        return result;
+    }
+}
+

+ 33 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,33 @@
+spring:
+    datasource:
+        type: org.apache.tomcat.jdbc.pool.DataSource
+        driverClassName: oracle.jdbc.OracleDriver
+        username: MOYING
+        password: select!#%*(
+        url: jdbc:oracle:thin:@10.1.81.208:11696:orcl
+server:
+    tomcat:
+        uri_encoding: UTF-8
+    context-path:
+        /EIS
+
+Task:
+    getVacationMethod: syncProducts
+    getVacationCron: 0 0/10 * * * ?
+    getCCSQMethod: syncMakeBases
+    getCCSQCron: 0 2/10 * * * ?
+    getExtraWorkMethod: syncMakeBases
+    getExtraWorkCron: 0 4/10 * * * ?
+
+action:
+    api_action: /EIS/api,/EIS/mes,/EIS/erp
+    public_actions: /EIS/logout,/EIS/hello1
+
+dingTalk:
+    api: https://oapi.dingtalk.com
+    appKey: dingxfuwm5g76h4q5a4q
+    appSecret: vGizhqKZOqcKb4-iJmZR6_LPUaK1OafMe4GuZ-LX6pSdXr6x15y6PgLdBGSYcq3d
+    processCode: 3
+    originatorUserId: 4
+    callToken: 5
+    callAesKey: 6

+ 33 - 0
src/main/resources/application-prod.yml

@@ -0,0 +1,33 @@
+spring:
+    datasource:
+        type: org.apache.tomcat.jdbc.pool.DataSource
+        driverClassName: oracle.jdbc.OracleDriver
+        username: MOYING
+        password: select!#%*(
+        url: jdbc:oracle:thin:@10.1.81.208:11696:orcl
+server:
+    tomcat:
+        uri_encoding: UTF-8
+    context-path:
+        /EIS
+
+Task:
+    getVacationMethod: syncProducts
+    getVacationCron: 0 0/10 * * * ?
+    getCCSQMethod: syncMakeBases
+    getCCSQCron: 0 2/10 * * * ?
+    getExtraWorkMethod: syncMakeBases
+    getExtraWorkCron: 0 4/10 * * * ?
+
+action:
+    api_action: /EIS/api,/EIS/mes,/EIS/erp
+    public_actions: /EIS/logout,/EIS/hello1
+
+dingTalk:
+    api: https://oapi.dingtalk.com
+    appKey: 1
+    appSecret: 2
+    processCode: 3
+    originatorUserId: 4
+    callToken: 5
+    callAesKey: 6

+ 2 - 15
src/main/resources/application.yml

@@ -1,10 +1,6 @@
 spring:
-    datasource:
-        type: org.apache.tomcat.jdbc.pool.DataSource
-        driverClassName: oracle.jdbc.OracleDriver
-        username: UAS_DEV
-        password: select!#%*(
-        url: jdbc:oracle:thin:@192.168.253.6:1521:orcl
+    profiles:
+        active: dev
     http:
         encoding:
             force: true
@@ -12,12 +8,3 @@ spring:
             enabled: true
     message:
         encoding: UTF-8
-server:
-    tomcat:
-        uri_encoding: UTF-8
-    context-path:
-        /EIS
-
-action:
-    api_action: /EIS/api
-    public_actions: /EIS/logout,/EIS/hello1

+ 1 - 0
src/main/resources/token.properties

@@ -1,2 +1,3 @@
 SECURITY_KEY=435aMe9L5itTrckY35kfcOQvPkBGZtGo
 KEEP=86400000
+

+ 8 - 1
src/test/java/com/uas/eis/UasEisApplicationTests.java

@@ -1,7 +1,10 @@
 package com.uas.eis;
 
+import com.uas.eis.service.Impl.ScheduleTaskServiceImpl;
+import com.uas.eis.service.ScheduleTaskService;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
@@ -9,8 +12,12 @@ import org.springframework.test.context.junit4.SpringRunner;
 @SpringBootTest
 public class UasEisApplicationTests {
 
+	@Autowired
+	private ScheduleTaskService scheduleTaskService;
+
 	@Test
-	public void contextLoads() {
+	public void getVacation() {
+		scheduleTaskService.getVacation();
 	}
 
 }