Drew 6 лет назад
Сommit
d0d2df8a6d
100 измененных файлов с 5245 добавлено и 0 удалено
  1. 33 0
      .gitignore
  2. 114 0
      .mvn/wrapper/MavenWrapperDownloader.java
  3. BIN
      .mvn/wrapper/maven-wrapper.jar
  4. 1 0
      .mvn/wrapper/maven-wrapper.properties
  5. 7 0
      build.sh
  6. 8 0
      install-jar.sh
  7. BIN
      lib/client-sdk.api-1.0.2.jar
  8. BIN
      lib/client-sdk.common-1.0.0-SNAPSHOT.jar
  9. BIN
      lib/client-sdk.core-1.0.0-SNAPSHOT.jar
  10. BIN
      lib/client-sdk.spring-1.0.0-SNAPSHOT.jar
  11. BIN
      lib/lippi-oapi-encrpt.jar
  12. BIN
      lib/taobao-sdk-java-auto_1479188381469-20191011-source.jar
  13. BIN
      lib/taobao-sdk-java-auto_1479188381469-20191011.jar
  14. BIN
      libs/com/dingtalk/client-sdk.api/1.0.2/client-sdk.api-1.0.2.jar
  15. 9 0
      libs/com/dingtalk/client-sdk.api/1.0.2/client-sdk.api-1.0.2.pom
  16. 12 0
      libs/com/dingtalk/client-sdk.api/maven-metadata-local.xml
  17. BIN
      libs/com/dingtalk/client-sdk.common/1.0.0/client-sdk.common-1.0.0.jar
  18. 9 0
      libs/com/dingtalk/client-sdk.common/1.0.0/client-sdk.common-1.0.0.pom
  19. 12 0
      libs/com/dingtalk/client-sdk.common/maven-metadata-local.xml
  20. BIN
      libs/com/dingtalk/client-sdk.core/1.0.0/client-sdk.core-1.0.0.jar
  21. 9 0
      libs/com/dingtalk/client-sdk.core/1.0.0/client-sdk.core-1.0.0.pom
  22. 12 0
      libs/com/dingtalk/client-sdk.core/maven-metadata-local.xml
  23. BIN
      libs/com/dingtalk/client-sdk.spring/1.0.0/client-sdk.spring-1.0.0.jar
  24. 9 0
      libs/com/dingtalk/client-sdk.spring/1.0.0/client-sdk.spring-1.0.0.pom
  25. 12 0
      libs/com/dingtalk/client-sdk.spring/maven-metadata-local.xml
  26. BIN
      libs/com/dingtalk/lippi-oapi-encrpt/1.0.0/lippi-oapi-encrpt-1.0.0.jar
  27. 9 0
      libs/com/dingtalk/lippi-oapi-encrpt/1.0.0/lippi-oapi-encrpt-1.0.0.pom
  28. BIN
      libs/com/dingtalk/lippi-oapi-encrpt/1.0.3/lippi-oapi-encrpt-1.0.3.jar
  29. 9 0
      libs/com/dingtalk/lippi-oapi-encrpt/1.0.3/lippi-oapi-encrpt-1.0.3.pom
  30. 13 0
      libs/com/dingtalk/lippi-oapi-encrpt/maven-metadata-local.xml
  31. BIN
      libs/com/dingtalk/taobao-sdk-java-auto/1479188381469-20191011/taobao-sdk-java-auto-1479188381469-20191011.jar
  32. 9 0
      libs/com/dingtalk/taobao-sdk-java-auto/1479188381469-20191011/taobao-sdk-java-auto-1479188381469-20191011.pom
  33. 12 0
      libs/com/dingtalk/taobao-sdk-java-auto/maven-metadata-local.xml
  34. 286 0
      mvnw
  35. 161 0
      mvnw.cmd
  36. 287 0
      pom.xml
  37. 287 0
      src/main/java/com/izouma/dingtalk/Demo.java
  38. 85 0
      src/main/java/com/izouma/dingtalk/DemoTest.java
  39. 65 0
      src/main/java/com/izouma/dingtalk/Env.java
  40. 14 0
      src/main/java/com/izouma/dingtalk/OApiException.java
  41. 180 0
      src/main/java/com/izouma/dingtalk/auth/AuthHelper.java
  42. 63 0
      src/main/java/com/izouma/dingtalk/department/DepartmentHelper.java
  43. 80 0
      src/main/java/com/izouma/dingtalk/eventchange/eventChangeHelper.java
  44. 53 0
      src/main/java/com/izouma/dingtalk/media/MediaHelper.java
  45. 16 0
      src/main/java/com/izouma/dingtalk/message/ConversationMessageDelivery.java
  46. 17 0
      src/main/java/com/izouma/dingtalk/message/ImageMessage.java
  47. 15 0
      src/main/java/com/izouma/dingtalk/message/LightAppMessageDelivery.java
  48. 22 0
      src/main/java/com/izouma/dingtalk/message/LinkMessage.java
  49. 6 0
      src/main/java/com/izouma/dingtalk/message/Message.java
  50. 15 0
      src/main/java/com/izouma/dingtalk/message/MessageDelivery.java
  51. 43 0
      src/main/java/com/izouma/dingtalk/message/MessageHelper.java
  52. 69 0
      src/main/java/com/izouma/dingtalk/message/OAMessage.java
  53. 17 0
      src/main/java/com/izouma/dingtalk/message/TextMessage.java
  54. 43 0
      src/main/java/com/izouma/dingtalk/user/User.java
  55. 143 0
      src/main/java/com/izouma/dingtalk/user/UserHelper.java
  56. 135 0
      src/main/java/com/izouma/dingtalk/utils/FileUtils.java
  57. 251 0
      src/main/java/com/izouma/dingtalk/utils/HttpHelper.java
  58. 53 0
      src/main/java/com/izouma/dingtalk/utils/aes/DingTalkEncryptException.java
  59. 211 0
      src/main/java/com/izouma/dingtalk/utils/aes/DingTalkEncryptor.java
  60. 52 0
      src/main/java/com/izouma/dingtalk/utils/aes/DingTalkJsApiSingnature.java
  61. 50 0
      src/main/java/com/izouma/dingtalk/utils/aes/PKCS7Padding.java
  62. 53 0
      src/main/java/com/izouma/dingtalk/utils/aes/Utils.java
  63. 17 0
      src/main/java/com/izouma/ticketExchange/TicketExchangeApplication.java
  64. 12 0
      src/main/java/com/izouma/ticketExchange/annotations/Searchable.java
  65. 17 0
      src/main/java/com/izouma/ticketExchange/config/Constants.java
  66. 148 0
      src/main/java/com/izouma/ticketExchange/config/DateConfig.java
  67. 20 0
      src/main/java/com/izouma/ticketExchange/config/ErrorPageConfig.java
  68. 36 0
      src/main/java/com/izouma/ticketExchange/config/LocalDateTimeSerializerConfig.java
  69. 44 0
      src/main/java/com/izouma/ticketExchange/config/RedisConfig.java
  70. 24 0
      src/main/java/com/izouma/ticketExchange/config/SpringSecurityAuditorAware.java
  71. 75 0
      src/main/java/com/izouma/ticketExchange/config/WebMvcConfig.java
  72. 74 0
      src/main/java/com/izouma/ticketExchange/config/WxMpConfiguration.java
  73. 13 0
      src/main/java/com/izouma/ticketExchange/config/WxMpProperties.java
  74. 47 0
      src/main/java/com/izouma/ticketExchange/config/WxPayConfiguration.java
  75. 97 0
      src/main/java/com/izouma/ticketExchange/config/WxPayProperties.java
  76. 32 0
      src/main/java/com/izouma/ticketExchange/converter/LongArrayConverter.java
  77. 25 0
      src/main/java/com/izouma/ticketExchange/converter/StringArrayConverter.java
  78. 24 0
      src/main/java/com/izouma/ticketExchange/converter/StringToMapConverter.java
  79. 81 0
      src/main/java/com/izouma/ticketExchange/domain/BaseEntity.java
  80. 79 0
      src/main/java/com/izouma/ticketExchange/domain/BedInfo.java
  81. 40 0
      src/main/java/com/izouma/ticketExchange/domain/BuildingInfo.java
  82. 95 0
      src/main/java/com/izouma/ticketExchange/domain/CheckinInfo.java
  83. 77 0
      src/main/java/com/izouma/ticketExchange/domain/Department.java
  84. 50 0
      src/main/java/com/izouma/ticketExchange/domain/DepositRecord.java
  85. 35 0
      src/main/java/com/izouma/ticketExchange/domain/FeeType.java
  86. 43 0
      src/main/java/com/izouma/ticketExchange/domain/FloorInfo.java
  87. 35 0
      src/main/java/com/izouma/ticketExchange/domain/Menu.java
  88. 57 0
      src/main/java/com/izouma/ticketExchange/domain/PropertyCompany.java
  89. 46 0
      src/main/java/com/izouma/ticketExchange/domain/RechargeRecord.java
  90. 51 0
      src/main/java/com/izouma/ticketExchange/domain/RoomFee.java
  91. 120 0
      src/main/java/com/izouma/ticketExchange/domain/RoomInfo.java
  92. 73 0
      src/main/java/com/izouma/ticketExchange/domain/RoomTypeInfo.java
  93. 32 0
      src/main/java/com/izouma/ticketExchange/domain/SmsRecord.java
  94. 80 0
      src/main/java/com/izouma/ticketExchange/domain/StoreInfo.java
  95. 29 0
      src/main/java/com/izouma/ticketExchange/domain/Tenant.java
  96. 112 0
      src/main/java/com/izouma/ticketExchange/domain/User.java
  97. 55 0
      src/main/java/com/izouma/ticketExchange/domain/client/DepositRefundApply.java
  98. 56 0
      src/main/java/com/izouma/ticketExchange/domain/gen/TestGenCode.java
  99. 38 0
      src/main/java/com/izouma/ticketExchange/domain/sale/CollectionAccount.java
  100. 185 0
      src/main/java/com/izouma/ticketExchange/domain/sale/Contract.java

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**
+!**/src/test/**
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+
+### VS Code ###
+.vscode/
+
+.DS_Store

+ 114 - 0
.mvn/wrapper/MavenWrapperDownloader.java

@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+    /**
+     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+     */
+    private static final String DEFAULT_DOWNLOAD_URL =
+            "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+    /**
+     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+     * use instead of the default one.
+     */
+    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+            ".mvn/wrapper/maven-wrapper.properties";
+
+    /**
+     * Path where the maven-wrapper.jar will be saved to.
+     */
+    private static final String MAVEN_WRAPPER_JAR_PATH =
+            ".mvn/wrapper/maven-wrapper.jar";
+
+    /**
+     * Name of the property which should be used to override the default download url for the wrapper.
+     */
+    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+    public static void main(String args[]) {
+        System.out.println("- Downloader started");
+        File baseDirectory = new File(args[0]);
+        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+        // If the maven-wrapper.properties exists, read it and check if it contains a custom
+        // wrapperUrl parameter.
+        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+        String url = DEFAULT_DOWNLOAD_URL;
+        if (mavenWrapperPropertyFile.exists()) {
+            FileInputStream mavenWrapperPropertyFileInputStream = null;
+            try {
+                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+                Properties mavenWrapperProperties = new Properties();
+                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+            } catch (IOException e) {
+                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+            } finally {
+                try {
+                    if (mavenWrapperPropertyFileInputStream != null) {
+                        mavenWrapperPropertyFileInputStream.close();
+                    }
+                } catch (IOException e) {
+                    // Ignore ...
+                }
+            }
+        }
+        System.out.println("- Downloading from: : " + url);
+
+        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+        if (!outputFile.getParentFile().exists()) {
+            if (!outputFile.getParentFile().mkdirs()) {
+                System.out.println(
+                        "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+            }
+        }
+        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+        try {
+            downloadFileFromURL(url, outputFile);
+            System.out.println("Done");
+            System.exit(0);
+        } catch (Throwable e) {
+            System.out.println("- Error downloading");
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+        URL website = new URL(urlString);
+        ReadableByteChannel rbc;
+        rbc = Channels.newChannel(website.openStream());
+        FileOutputStream fos = new FileOutputStream(destination);
+        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+        fos.close();
+        rbc.close();
+    }
+
+}

BIN
.mvn/wrapper/maven-wrapper.jar


+ 1 - 0
.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip

+ 7 - 0
build.sh

@@ -0,0 +1,7 @@
+git checkout
+git pull
+#(cd src/main/vue && npm run build)
+mvn clean package
+systemctl stop zmj
+cp target/zhumj-0.0.1-SNAPSHOT.jar /var/www/zmj/zhumj-0.0.1-SNAPSHOT.jar
+systemctl start zmj

+ 8 - 0
install-jar.sh

@@ -0,0 +1,8 @@
+
+mvn org.apache.maven.plugins:maven-install-plugin:2.5.1:install-file \
+-DgroupId=com.dingtalk \
+-DartifactId=client-sdk.api \
+-Dpackaging=jar \
+-Dversion=1.0.2 \
+-Dfile=lib/client-sdk.api-1.0.2.jar \
+-DlocalRepositoryPath=libs

BIN
lib/client-sdk.api-1.0.2.jar


BIN
lib/client-sdk.common-1.0.0-SNAPSHOT.jar


BIN
lib/client-sdk.core-1.0.0-SNAPSHOT.jar


BIN
lib/client-sdk.spring-1.0.0-SNAPSHOT.jar


BIN
lib/lippi-oapi-encrpt.jar


BIN
lib/taobao-sdk-java-auto_1479188381469-20191011-source.jar


BIN
lib/taobao-sdk-java-auto_1479188381469-20191011.jar


BIN
libs/com/dingtalk/client-sdk.api/1.0.2/client-sdk.api-1.0.2.jar


+ 9 - 0
libs/com/dingtalk/client-sdk.api/1.0.2/client-sdk.api-1.0.2.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.api</artifactId>
+  <version>1.0.2</version>
+  <description>POM was created from install:install-file</description>
+</project>

+ 12 - 0
libs/com/dingtalk/client-sdk.api/maven-metadata-local.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.api</artifactId>
+  <versioning>
+    <release>1.0.2</release>
+    <versions>
+      <version>1.0.2</version>
+    </versions>
+    <lastUpdated>20191021025219</lastUpdated>
+  </versioning>
+</metadata>

BIN
libs/com/dingtalk/client-sdk.common/1.0.0/client-sdk.common-1.0.0.jar


+ 9 - 0
libs/com/dingtalk/client-sdk.common/1.0.0/client-sdk.common-1.0.0.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.common</artifactId>
+  <version>1.0.0</version>
+  <description>POM was created from install:install-file</description>
+</project>

+ 12 - 0
libs/com/dingtalk/client-sdk.common/maven-metadata-local.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.common</artifactId>
+  <versioning>
+    <release>1.0.0</release>
+    <versions>
+      <version>1.0.0</version>
+    </versions>
+    <lastUpdated>20191021025350</lastUpdated>
+  </versioning>
+</metadata>

BIN
libs/com/dingtalk/client-sdk.core/1.0.0/client-sdk.core-1.0.0.jar


+ 9 - 0
libs/com/dingtalk/client-sdk.core/1.0.0/client-sdk.core-1.0.0.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.core</artifactId>
+  <version>1.0.0</version>
+  <description>POM was created from install:install-file</description>
+</project>

+ 12 - 0
libs/com/dingtalk/client-sdk.core/maven-metadata-local.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.core</artifactId>
+  <versioning>
+    <release>1.0.0</release>
+    <versions>
+      <version>1.0.0</version>
+    </versions>
+    <lastUpdated>20191021025637</lastUpdated>
+  </versioning>
+</metadata>

BIN
libs/com/dingtalk/client-sdk.spring/1.0.0/client-sdk.spring-1.0.0.jar


+ 9 - 0
libs/com/dingtalk/client-sdk.spring/1.0.0/client-sdk.spring-1.0.0.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.spring</artifactId>
+  <version>1.0.0</version>
+  <description>POM was created from install:install-file</description>
+</project>

+ 12 - 0
libs/com/dingtalk/client-sdk.spring/maven-metadata-local.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>client-sdk.spring</artifactId>
+  <versioning>
+    <release>1.0.0</release>
+    <versions>
+      <version>1.0.0</version>
+    </versions>
+    <lastUpdated>20191021025638</lastUpdated>
+  </versioning>
+</metadata>

BIN
libs/com/dingtalk/lippi-oapi-encrpt/1.0.0/lippi-oapi-encrpt-1.0.0.jar


+ 9 - 0
libs/com/dingtalk/lippi-oapi-encrpt/1.0.0/lippi-oapi-encrpt-1.0.0.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>lippi-oapi-encrpt</artifactId>
+  <version>1.0.0</version>
+  <description>POM was created from install:install-file</description>
+</project>

BIN
libs/com/dingtalk/lippi-oapi-encrpt/1.0.3/lippi-oapi-encrpt-1.0.3.jar


+ 9 - 0
libs/com/dingtalk/lippi-oapi-encrpt/1.0.3/lippi-oapi-encrpt-1.0.3.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>lippi-oapi-encrpt</artifactId>
+  <version>1.0.3</version>
+  <description>POM was created from install:install-file</description>
+</project>

+ 13 - 0
libs/com/dingtalk/lippi-oapi-encrpt/maven-metadata-local.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>lippi-oapi-encrpt</artifactId>
+  <versioning>
+    <release>1.0.3</release>
+    <versions>
+      <version>1.0.0</version>
+      <version>1.0.3</version>
+    </versions>
+    <lastUpdated>20191021030128</lastUpdated>
+  </versioning>
+</metadata>

BIN
libs/com/dingtalk/taobao-sdk-java-auto/1479188381469-20191011/taobao-sdk-java-auto-1479188381469-20191011.jar


+ 9 - 0
libs/com/dingtalk/taobao-sdk-java-auto/1479188381469-20191011/taobao-sdk-java-auto-1479188381469-20191011.pom

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>taobao-sdk-java-auto</artifactId>
+  <version>1479188381469-20191011</version>
+  <description>POM was created from install:install-file</description>
+</project>

+ 12 - 0
libs/com/dingtalk/taobao-sdk-java-auto/maven-metadata-local.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>com.dingtalk</groupId>
+  <artifactId>taobao-sdk-java-auto</artifactId>
+  <versioning>
+    <release>1479188381469-20191011</release>
+    <versions>
+      <version>1479188381469-20191011</version>
+    </versions>
+    <lastUpdated>20191021025642</lastUpdated>
+  </versioning>
+</metadata>

+ 286 - 0
mvnw

@@ -0,0 +1,286 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+  # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $jarUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+
+    if command -v wget > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+        fi
+        wget "$jarUrl" -O "$wrapperJarPath"
+    elif command -v curl > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+        fi
+        curl -o "$wrapperJarPath" "$jarUrl"
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        if [ -e "$javaClass" ]; then
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaClass")
+            fi
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 161 - 0
mvnw.cmd

@@ -0,0 +1,161 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
+	IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    echo Found %WRAPPER_JAR%
+) else (
+    echo Couldn't find %WRAPPER_JAR%, downloading it ...
+	echo Downloading from: %DOWNLOAD_URL%
+    powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
+    echo Finished downloading %WRAPPER_JAR%
+)
+@REM End of extension
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%

+ 287 - 0
pom.xml

@@ -0,0 +1,287 @@
+<?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 https://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.1.8.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.izouma</groupId>
+    <artifactId>ticketExchange</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>ticketExchange</name>
+    <description>换票</description>
+
+    <repositories>
+        <repository>
+            <id>nexus-aliyun</id>
+            <url>https://maven.aliyun.com/repository/central</url>
+        </repository>
+        <repository>
+            <id>Local repository</id>
+            <url>file://${basedir}/libs</url>
+        </repository>
+    </repositories>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <skipTests>true</skipTests>
+        <poi.verion>3.17</poi.verion>
+        <javawx.version>3.5.0</javawx.version>
+        <aliyun.oss.version>2.8.3</aliyun.oss.version>
+        <aliyun.core.version>4.1.0</aliyun.core.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-envers</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-text</artifactId>
+            <version>1.3</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>annotations</artifactId>
+            <version>3.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-mp</artifactId>
+            <version>${javawx.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-pay</artifactId>
+            <version>${javawx.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-open</artifactId>
+            <version>${javawx.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>${aliyun.oss.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>${aliyun.core.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.kevinsawicki</groupId>
+            <artifactId>http-request</artifactId>
+            <version>6.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>${poi.verion}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>${poi.verion}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <version>3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>2.0.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.11</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity</artifactId>
+            <version>1.7</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-tools</artifactId>
+            <version>2.0</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.belerweb/pinyin4j -->
+        <dependency>
+            <groupId>com.belerweb</groupId>
+            <artifactId>pinyin4j</artifactId>
+            <version>2.5.1</version>
+        </dependency>
+        <!-- swagger -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.9.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-freemarker</artifactId>
+        </dependency>
+
+        <!-- 钉钉 -->
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>lippi-oapi-encrpt</artifactId>
+            <version>1.0.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>client-sdk.api</artifactId>
+            <version>1.0.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>client-sdk.common</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>client-sdk.core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>client-sdk.spring</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>taobao-sdk-java-auto</artifactId>
+            <version>1479188381469-20191011</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.37</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ning</groupId>
+            <artifactId>async-http-client</artifactId>
+            <version>1.9.32</version>
+        </dependency>
+        <!-- 钉钉 -->
+
+    </dependencies>
+
+</project>

+ 287 - 0
src/main/java/com/izouma/dingtalk/Demo.java

@@ -0,0 +1,287 @@
+package com.izouma.dingtalk;
+
+import com.izouma.dingtalk.auth.AuthHelper;
+import com.izouma.dingtalk.department.DepartmentHelper;
+import com.izouma.dingtalk.media.MediaHelper;
+import com.izouma.dingtalk.message.LightAppMessageDelivery;
+import com.izouma.dingtalk.message.MessageHelper;
+import com.izouma.dingtalk.user.UserHelper;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.open.client.api.model.corp.*;
+import com.dingtalk.open.client.api.model.corp.MessageBody.OABody.Body;
+import com.dingtalk.open.client.api.model.corp.MessageBody.OABody.Body.Form;
+import com.dingtalk.open.client.api.model.corp.MessageBody.OABody.Body.Rich;
+import com.dingtalk.open.client.api.model.corp.MessageBody.OABody.Head;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 本地测试方法钉钉API
+ */
+public class Demo {
+
+    public static String TO_USER = "";
+    public static String TO_PARTY = "";
+    public static String AGENT_ID = "";
+
+    public static void main(String[] args) throws Exception {
+
+        try {
+
+            List<Department> departments = new ArrayList<Department>();
+            departments = DepartmentHelper.listDepartments(AuthHelper.getAccessToken(), "1");
+            JSONObject usersJSON = new JSONObject();
+
+            System.out.println("depart num:" + departments.size());
+            for (int i = 0; i < departments.size(); i++) {
+                JSONObject userDepJSON = new JSONObject();
+                System.out.println("dep:" + departments.get(i).toString());
+
+                long offset = 0;
+                int size = 5;
+                CorpUserList corpUserList = new CorpUserList();
+                while (true) {
+                    corpUserList = UserHelper.getDepartmentUser(AuthHelper.getAccessToken(), Long.valueOf(departments.get(i).getId())
+                            , offset, size, null);
+                    System.out.println(JSON.toJSONString(corpUserList));
+                    if (Boolean.TRUE.equals(corpUserList.isHasMore())) {
+                        offset += size;
+                    } else {
+                        break;
+                    }
+                }
+                if (corpUserList.getUserlist().size() == 0) {
+                    continue;
+                }
+                for (int j = 0; j < corpUserList.getUserlist().size(); j++) {
+                    String user = JSON.toJSONString(corpUserList.getUserlist().get(j));
+                    userDepJSON.put(j + "", JSONObject.parseObject(user, CorpUserDetail.class));
+
+                }
+
+
+                usersJSON.put(departments.get(i).getName(), userDepJSON);
+                System.out.println("user:" + usersJSON.toString());
+            }
+
+            System.out.println("depart:" + usersJSON.toJSONString());
+
+
+            // 获取access token
+            String accessToken = AuthHelper.getAccessToken();
+            log("成功获取access token: ", accessToken);
+
+            // 获取jsapi ticket
+            String ticket = AuthHelper.getJsapiTicket(accessToken);
+            log("成功获取jsapi ticket: ", ticket);
+
+            // 获取签名
+            String nonceStr = "nonceStr";
+            long timeStamp = System.currentTimeMillis();
+            String url = "http://www.dingtalk.com";
+            String signature = AuthHelper.sign(ticket, nonceStr, timeStamp, url);
+            log("成功签名: ", signature);
+
+            // 创建部门
+            String name = "TestDept.34";
+            String parentId = "1";
+            String order = "1";
+            boolean createDeptGroup = true;
+            long departmentId = Long.parseLong(DepartmentHelper.createDepartment(accessToken, name, parentId, order, createDeptGroup));
+            log("成功创建部门", name, " 部门id=", departmentId);
+
+            // 获取部门列表
+            List<Department> list = DepartmentHelper.listDepartments(accessToken, parentId);
+            log("成功获取部门列表", list);
+
+            // 更新部门
+            name = "hahahaha";
+            boolean autoAddUser = true;
+            String deptManagerUseridList = null;
+            boolean deptHiding = false;
+            String deptPerimits = "aa|qq";
+            DepartmentHelper.updateDepartment(accessToken, departmentId, name, parentId, order, createDeptGroup,
+                    autoAddUser, deptManagerUseridList, deptHiding, deptPerimits, null,
+                    null, null, null, null);
+
+
+            log("成功更新部门", " 部门id=", departmentId);
+
+            CorpUserDetail userDetail = new CorpUserDetail();
+            userDetail.setUserid("id_yuhuan");
+            userDetail.setName("name_yuhuan");
+            userDetail.setEmail("yuhuan@abc.com");
+            userDetail.setMobile("18612124567");
+            userDetail.setDepartment(new ArrayList());
+            userDetail.getDepartment().add(departmentId);
+
+
+            UserHelper.createUser(accessToken, userDetail);
+            log("成功创建成员", "成员信息=", userDetail);
+
+            // 上传图片
+            File file = new File("/Users/ian/Downloads/lALOAVYgbc0DIM0Bwg_450_800.png");
+            UploadResult uploadResult = MediaHelper.upload(accessToken, MediaHelper.TYPE_IMAGE, file);
+            log("成功上传图片", uploadResult);
+
+            // 下载图片
+            String fileDir = "/Users/ian/Desktop/";
+            MediaHelper.download(accessToken, uploadResult.getMedia_id(), fileDir);
+            log("成功下载图片");
+
+
+            MessageBody.TextBody textBody = new MessageBody.TextBody();
+            textBody.setContent("TextMessage");
+
+            MessageBody.ImageBody imageBody = new MessageBody.ImageBody();
+            imageBody.setMedia_id(uploadResult.getMedia_id());
+
+            MessageBody.LinkBody linkBody = new MessageBody.LinkBody();
+            linkBody.setMessageUrl("http://www.baidu.com");
+            linkBody.setPicUrl("@lALOACZwe2Rk");
+            linkBody.setTitle("Link Message");
+            linkBody.setText("This is a link message");
+
+            // 创建oa消息
+            MessageBody.OABody oaBody = new MessageBody.OABody();
+            oaBody.setMessage_url("message_url");
+            Head head = new Head();
+            head.setText("head.text");
+            head.setBgcolor("FFBBBBBB");
+            oaBody.setHead(head);
+
+            Body body = new Body();
+            body.setAuthor("author");
+            body.setContent("content");
+            body.setFile_count("file_count");
+            body.setImage("@image");
+            body.setTitle("body.title");
+            Rich rich = new Rich();
+            rich.setNum("num");
+            rich.setUnit("unit");
+            body.setRich(rich);
+            List<Form> formList = new ArrayList<Form>();
+            Form form = new Form();
+            form.setKey("key");
+            form.setValue("value");
+            formList.add(form);
+            body.setForm(formList);
+            oaBody.setBody(body);
+
+            // 发送微应用消息
+            String toUsers = TO_USER;
+            String toParties = TO_PARTY;
+            String agentId = AGENT_ID;
+            LightAppMessageDelivery lightAppMessageDelivery = new LightAppMessageDelivery(toUsers, toParties, agentId);
+
+            lightAppMessageDelivery.withMessage(MessageType.TEXT, textBody);
+            MessageHelper.send(accessToken, lightAppMessageDelivery);
+            log("成功发送 微应用文本消息");
+            lightAppMessageDelivery.withMessage(MessageType.IMAGE, imageBody);
+            MessageHelper.send(accessToken, lightAppMessageDelivery);
+            log("成功发送 微应用图片消息");
+            lightAppMessageDelivery.withMessage(MessageType.LINK, linkBody);
+            MessageHelper.send(accessToken, lightAppMessageDelivery);
+            log("成功发送 微应用link消息");
+            lightAppMessageDelivery.withMessage(MessageType.OA, oaBody);
+            MessageHelper.send(accessToken, lightAppMessageDelivery);
+            log("成功发送 微应用oa消息");
+
+            // 发送会话消息
+//			String sender = Vars.SENDER;
+//			String cid = Vars.CID;//cid需要通过jsapi获取,具体详情请查看开放平台文档--->客户端文档--->会话
+
+//			ConversationMessageDelivery conversationMessageDelivery = new ConversationMessageDelivery(sender, cid,
+//					agentId);
+//
+//			conversationMessageDelivery.withMessage(MessageType.TEXT, textBody);
+//			MessageHelper.send(accessToken, conversationMessageDelivery);
+//			log("成功发送 会话文本消息");
+//			conversationMessageDelivery.withMessage(MessageType.IMAGE, imageBody);
+//			MessageHelper.send(accessToken, conversationMessageDelivery);
+//			log("成功发送 会话图片消息");
+//			conversationMessageDelivery.withMessage(MessageType.LINK, linkBody);
+//			MessageHelper.send(accessToken, conversationMessageDelivery);
+//			log("成功发送 会话link消息");
+
+            // 更新成员
+            userDetail.setMobile("11177776666");
+            UserHelper.updateUser(accessToken, userDetail);
+            log("成功更新成员", "成员信息=", userDetail);
+
+            // 获取成员
+            CorpUserDetail userDetail11 = UserHelper.getUser(accessToken, userDetail.getUserid());
+            log("成功获取成员", "成员userid=", userDetail11.getUserid());
+
+            // 获取部门成员
+            CorpUserList userList = UserHelper.getDepartmentUser(accessToken, departmentId, null, null, null);
+            log("成功获取部门成员", "部门成员user=", userList.getUserlist());
+
+            // 获取部门成员(详情)
+            CorpUserDetailList userList2 = UserHelper.getUserDetails(accessToken, departmentId, null, null, null);
+            log("成功获取部门成员详情", "部门成员详情user=", userList2.getUserlist());
+
+            // 批量删除成员
+//			User user2 = new User("id_yuhuan2", "name_yuhuan2");
+//			user2.email = "yuhua2n@abc.com";
+//			user2.mobile = "18611111111";
+//			user2.department = new ArrayList();
+//			user2.department.add(departmentId);
+//			UserHelper.createUser(accessToken, user2);
+
+            CorpUserDetail userDetail2 = new CorpUserDetail();
+            userDetail2.setUserid("id_yuhuan2");
+            userDetail2.setName("name_yuhuan2");
+            userDetail2.setEmail("yuhua2n@abc.com");
+            userDetail2.setMobile("18612124926");
+            userDetail2.setDepartment(new ArrayList());
+            userDetail2.getDepartment().add(departmentId);
+            UserHelper.createUser(accessToken, userDetail2);
+
+
+            List<String> useridlist = new ArrayList();
+            useridlist.add(userDetail.getUserid());
+            useridlist.add(userDetail2.getUserid());
+            UserHelper.batchDeleteUser(accessToken, useridlist);
+            log("成功批量删除成员", "成员列表useridlist=", useridlist);
+
+            // 删除成员
+//			User user3 = new User("id_yuhuan3", "name_yuhuan3");
+//			user3.email = "yuhua2n@abc.com";
+//			user3.mobile = "18611111111";
+//			user3.department = new ArrayList();
+//			user3.department.add(departmentId);
+            CorpUserDetail userDetail3 = new CorpUserDetail();
+            userDetail3.setUserid("id_yuhuan3");
+            userDetail3.setName("name_yuhuan3");
+            userDetail3.setMobile("13146654734");
+            userDetail3.setDepartment(new ArrayList());
+            userDetail3.getDepartment().add(departmentId);
+
+
+            UserHelper.createUser(accessToken, userDetail3);
+            UserHelper.deleteUser(accessToken, userDetail3.getUserid());
+            log("成功删除成员", "成员userid=", userDetail3.getUserid());
+
+            // 删除部门
+            DepartmentHelper.deleteDepartment(accessToken, departmentId);
+            log("成功删除部门", " 部门id=", departmentId);
+
+        } catch (OApiException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static void log(Object... msgs) {
+        StringBuilder sb = new StringBuilder();
+        for (Object o : msgs) {
+            if (o != null) {
+                sb.append(o.toString());
+            }
+        }
+        System.out.println(sb.toString());
+    }
+}

+ 85 - 0
src/main/java/com/izouma/dingtalk/DemoTest.java

@@ -0,0 +1,85 @@
+package com.izouma.dingtalk;
+
+import com.izouma.dingtalk.auth.AuthHelper;
+import com.izouma.dingtalk.department.DepartmentHelper;
+import com.izouma.dingtalk.user.UserHelper;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.open.client.api.model.corp.CorpUserDetail;
+import com.dingtalk.open.client.api.model.corp.CorpUserDetailList;
+import com.dingtalk.open.client.api.model.corp.CorpUserList;
+import com.dingtalk.open.client.api.model.corp.Department;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 本地测试方法钉钉API
+ */
+public class DemoTest {
+
+    public static void main(String[] args) throws Exception {
+
+        try {
+
+            List<Department> departments = new ArrayList<Department>();
+            departments = DepartmentHelper.listDepartments(AuthHelper.getAccessToken(), "1");
+            JSONObject usersJSON = new JSONObject();
+
+            System.out.println("depart num:" + departments.size());
+            for (int i = 0; i < departments.size(); i++) {
+
+                // 获取部门成员(详情)
+                CorpUserDetailList userList2 = UserHelper.getUserDetails(AuthHelper.getAccessToken(), Long.valueOf(departments.get(i).getId()), null, null, null);
+                log("成功获取部门成员详情", "部门成员详情user=", userList2.getUserlist());
+
+                JSONObject userDepJSON = new JSONObject();
+                System.out.println("dep:" + departments.get(i).toString());
+
+                long offset = 0;
+                int size = 5;
+                CorpUserList corpUserList = new CorpUserList();
+                while (true) {
+                    corpUserList = UserHelper.getDepartmentUser(AuthHelper.getAccessToken(), Long.valueOf(departments.get(i).getId())
+                            , offset, size, null);
+                    System.out.println(JSON.toJSONString(corpUserList));
+                    if (Boolean.TRUE.equals(corpUserList.isHasMore())) {
+                        offset += size;
+                    } else {
+                        break;
+                    }
+                }
+                if (corpUserList.getUserlist().size() == 0) {
+                    continue;
+                }
+                for (int j = 0; j < corpUserList.getUserlist().size(); j++) {
+                    String user = JSON.toJSONString(corpUserList.getUserlist().get(j));
+                    userDepJSON.put(j + "", JSONObject.parseObject(user, CorpUserDetail.class));
+
+                }
+
+
+                usersJSON.put(departments.get(i).getName(), userDepJSON);
+                System.out.println("user:" + usersJSON.toString());
+
+
+
+            }
+
+            System.out.println("depart:" + usersJSON.toJSONString());
+
+        } catch (OApiException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static void log(Object... msgs) {
+        StringBuilder sb = new StringBuilder();
+        for (Object o : msgs) {
+            if (o != null) {
+                sb.append(o.toString());
+            }
+        }
+        System.out.println(sb.toString());
+    }
+}

+ 65 - 0
src/main/java/com/izouma/dingtalk/Env.java

@@ -0,0 +1,65 @@
+package com.izouma.dingtalk;
+
+
+/**
+ * 企业应用接入时的常量定义
+ */
+public class Env {
+
+    /**
+     * 企业corpid
+     */
+    public static final String CORP_ID = "dingbf02317035a2ce7a35c2f4657eb6378f";
+
+    /**
+     * 应用agentId
+     */
+    public static final String AGENT_ID = "303430214";
+
+    /**
+     * 应用的appkey
+     */
+    public static final String APP_KEY = "dinguq6noxhfizkqnsaf";
+
+    /**
+     * 应用的appsecret
+     */
+    public static final String APP_SECRET = "Eb9TYf5qJlMiRiwmD0jCoxJIBjRxdpG2y87wa6mPveRc8gPGUGaSjG3HJApLM_Fo";
+
+    /**
+     * 回调host
+     */
+    public static final String CALLBACK_URL_HOST = "";
+
+    /**
+     * 加解密需要用到的token,企业可以随机填写。如 "123456"
+     */
+	public static final String TOKEN = "123456";
+
+    /**
+     * 数据加密密钥。用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成
+     */
+	public static final String ENCODING_AES_KEY = "abcdefghijabcdefghijabcdefghijabcdefghij123";
+
+    /**
+     * DING API地址
+     */
+    public static final String OAPI_HOST = "https://oapi.dingtalk.com";
+
+    /**
+     * 删除企业回调接口url
+     */
+    public static final String DELETE_CALLBACK = "https://oapi.dingtalk.com/call_back/delete_call_back";
+
+    /**
+     * 注册企业回调接口url
+     */
+    public static final String REGISTER_CALLBACK = "https://oapi.dingtalk.com/call_back/register_call_back";
+
+    /**
+     * 企业应用后台地址,用户管理后台免登使用
+     */
+    public static final String OA_BACKGROUND_URL = "";
+
+    public static final String SSO_Secret = "";
+}

+ 14 - 0
src/main/java/com/izouma/dingtalk/OApiException.java

@@ -0,0 +1,14 @@
+package com.izouma.dingtalk;
+
+public class OApiException extends Exception {
+
+    public static final int ERR_RESULT_RESOLUTION = -2;
+
+    public OApiException(String field) {
+        this(ERR_RESULT_RESOLUTION, "Cannot resolve field " + field + " from oapi resonpse");
+    }
+
+	public OApiException(int errCode, String errMsg) {
+		super("error code: " + errCode + ", error message: " + errMsg);
+	}
+}

+ 180 - 0
src/main/java/com/izouma/dingtalk/auth/AuthHelper.java

@@ -0,0 +1,180 @@
+package com.izouma.dingtalk.auth;
+
+import com.izouma.dingtalk.Env;
+import com.izouma.dingtalk.OApiException;
+import com.izouma.dingtalk.utils.FileUtils;
+import com.izouma.dingtalk.utils.HttpHelper;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.oapi.lib.aes.DingTalkJsApiSingnature;
+import com.dingtalk.open.client.ServiceFactory;
+import com.dingtalk.open.client.api.model.corp.JsapiTicket;
+import com.dingtalk.open.client.api.service.corp.CorpConnectionService;
+import com.dingtalk.open.client.api.service.corp.JsapiService;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * AccessToken和jsticket的获取封装
+ */
+public class AuthHelper {
+
+    /**
+     * 调整到1小时50分钟
+     */
+    public static final long cacheTime = 1000 * 60 * 55 * 2;
+
+    /**
+     * 在此方法中,为了避免频繁获取access_token,
+     * 在距离上一次获取access_token时间在两个小时之内的情况,
+     * 将直接从持久化存储中读取access_token
+     *
+     * 因为access_token和jsapi_ticket的过期时间都是7200秒
+     * 所以在获取access_token的同时也去获取了jsapi_ticket
+     * 注:jsapi_ticket是在前端页面JSAPI做权限验证配置的时候需要使用的
+     * 具体信息请查看开发者文档--权限验证配置
+     */
+    public static String getAccessToken() throws OApiException {
+        long curTime = System.currentTimeMillis();
+        JSONObject accessTokenValue = (JSONObject) FileUtils.getValue("accesstoken", Env.APP_KEY);
+        String accToken = "";
+        JSONObject jsontemp = new JSONObject();
+        if (accessTokenValue == null || curTime - accessTokenValue.getLong("begin_time") >= cacheTime) {
+            try {
+                ServiceFactory serviceFactory = ServiceFactory.getInstance();
+                CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class);
+                accToken = corpConnectionService.getCorpToken(Env.APP_KEY, Env.APP_SECRET);
+                // save accessToken
+                JSONObject jsonAccess = new JSONObject();
+                jsontemp.clear();
+                jsontemp.put("access_token", accToken);
+                jsontemp.put("begin_time", curTime);
+                jsonAccess.put(Env.APP_KEY, jsontemp);
+                //真实项目中最好保存到数据库中
+                FileUtils.write2File(jsonAccess, "accesstoken");
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        } else {
+            return accessTokenValue.getString("access_token");
+        }
+        return accToken;
+    }
+
+    /**
+     * 获取JSTicket, 用于js的签名计算
+     * 正常的情况下,jsapi_ticket的有效期为7200秒,所以开发者需要在某个地方设计一个定时器,定期去更新jsapi_ticket
+     */
+    public static String getJsapiTicket(String accessToken) throws OApiException {
+        JSONObject jsTicketValue = (JSONObject) FileUtils.getValue("jsticket", Env.APP_KEY);
+        long curTime = System.currentTimeMillis();
+        String jsTicket = "";
+
+        if (jsTicketValue == null || curTime -
+                jsTicketValue.getLong("begin_time") >= cacheTime) {
+            ServiceFactory serviceFactory;
+            try {
+                serviceFactory = ServiceFactory.getInstance();
+                JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);
+
+                JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi");
+                jsTicket = JsapiTicket.getTicket();
+
+                JSONObject jsonTicket = new JSONObject();
+                JSONObject jsontemp = new JSONObject();
+                jsontemp.clear();
+                jsontemp.put("ticket", jsTicket);
+                jsontemp.put("begin_time", curTime);
+                jsonTicket.put(Env.APP_KEY, jsontemp);
+                FileUtils.write2File(jsonTicket, "jsticket");
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return jsTicket;
+        } else {
+            return jsTicketValue.getString("ticket");
+        }
+    }
+
+    public static String sign(String ticket, String nonceStr, long timeStamp, String url) throws OApiException {
+        try {
+            return DingTalkJsApiSingnature.getJsApiSingnature(url, nonceStr, timeStamp, ticket);
+        } catch (Exception ex) {
+            throw new OApiException(0, ex.getMessage());
+        }
+    }
+
+    /**
+     * 计算当前请求的jsapi的签名数据<br/>
+     * <p>
+     * 如果签名数据是通过ajax异步请求的话,签名计算中的url必须是给用户展示页面的url
+     *
+     * @param request
+     * @return
+     */
+    public static String getConfig(HttpServletRequest request) {
+        String urlString = request.getRequestURL().toString();
+        String queryString = request.getQueryString();
+
+        String queryStringEncode = null;
+        String url;
+        if (queryString != null) {
+            queryStringEncode = URLDecoder.decode(queryString);
+            url = urlString + "?" + queryStringEncode;
+        } else {
+            url = urlString;
+        }
+        /**
+         * 确认url与配置的应用首页地址一致
+         */
+        System.out.println(url);
+
+        /**
+         * 随机字符串
+         */
+        String nonceStr = "abcdefg";
+        long timeStamp = System.currentTimeMillis() / 1000;
+        String signedUrl = url;
+        String accessToken = null;
+        String ticket = null;
+        String signature = null;
+
+        try {
+            accessToken = AuthHelper.getAccessToken();
+
+            ticket = AuthHelper.getJsapiTicket(accessToken);
+            signature = AuthHelper.sign(ticket, nonceStr, timeStamp, signedUrl);
+
+        } catch (OApiException e) {
+            e.printStackTrace();
+        }
+
+        Map<String, Object> configValue = new HashMap<>();
+        configValue.put("jsticket", ticket);
+        configValue.put("signature", signature);
+        configValue.put("nonceStr", nonceStr);
+        configValue.put("timeStamp", timeStamp);
+        configValue.put("corpId", Env.CORP_ID);
+        configValue.put("agentId", Env.AGENT_ID);
+
+        String config = JSON.toJSONString(configValue);
+        return config;
+    }
+
+    public static String getSsoToken() throws OApiException {
+        String url = "https://oapi.dingtalk.com/sso/gettoken?corpid=" + Env.CORP_ID + "&corpsecret=" + Env.SSO_Secret;
+        JSONObject response = HttpHelper.httpGet(url);
+        String ssoToken;
+        if (response.containsKey("access_token")) {
+            ssoToken = response.getString("access_token");
+        } else {
+            throw new OApiException("Sso_token");
+        }
+        return ssoToken;
+
+    }
+}

+ 63 - 0
src/main/java/com/izouma/dingtalk/department/DepartmentHelper.java

@@ -0,0 +1,63 @@
+package com.izouma.dingtalk.department;
+
+import com.dingtalk.open.client.ServiceFactory;
+import com.dingtalk.open.client.api.model.corp.Department;
+import com.dingtalk.open.client.api.model.corp.DepartmentDetail;
+import com.dingtalk.open.client.api.service.corp.CorpDepartmentService;
+import com.dingtalk.open.client.common.SdkInitException;
+import com.dingtalk.open.client.common.ServiceException;
+import com.dingtalk.open.client.common.ServiceNotExistException;
+
+import java.util.List;
+
+/**
+ * 部门相关API
+ *
+ * https://open-doc.dingtalk.com/docs/doc.htm?treeId=371&articleId=106817&docType=1
+ */
+public class DepartmentHelper {
+
+    /**
+     *  创建部门
+     */
+    public static String createDepartment(String accessToken, String name,
+                                          String parentId, String order, boolean createDeptGroup) throws Exception {
+
+        CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
+        return corpDepartmentService.deptCreate(accessToken, name, parentId, order, createDeptGroup);
+    }
+
+    /**
+     * 获取部门列表
+     */
+    public static List<Department> listDepartments(String accessToken, String parentDeptId)
+            throws ServiceNotExistException, SdkInitException, ServiceException {
+        CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
+        List<Department> deptList = corpDepartmentService.getDeptList(accessToken, parentDeptId);
+        return deptList;
+    }
+
+
+    /**
+     * 删除部门
+     */
+    public static void deleteDepartment(String accessToken, Long id) throws Exception {
+        CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
+        corpDepartmentService.deptDelete(accessToken, id);
+    }
+
+    /**
+     * 更新部门
+     */
+    public static void updateDepartment(String accessToken, long id, String name,
+                                        String parentId, String order, Boolean createDeptGroup,
+                                        boolean autoAddUser, String deptManagerUseridList, boolean deptHiding, String deptPerimits,
+                                        String userPerimits, Boolean outerDept, String outerPermitDepts,
+                                        String outerPermitUsers, String orgDeptOwner) throws Exception {
+        CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
+        corpDepartmentService.deptUpdate(accessToken, id, name, parentId, order, createDeptGroup,
+                autoAddUser, deptManagerUseridList, deptHiding, deptPerimits, userPerimits,
+                outerDept, outerPermitDepts, outerPermitUsers, orgDeptOwner);
+
+    }
+}

+ 80 - 0
src/main/java/com/izouma/dingtalk/eventchange/eventChangeHelper.java

@@ -0,0 +1,80 @@
+package com.izouma.dingtalk.eventchange;
+
+import com.izouma.dingtalk.Env;
+import com.izouma.dingtalk.OApiException;
+import com.izouma.dingtalk.utils.HttpHelper;
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.List;
+
+/**
+ * 通讯录回调相关事件
+ * <p>
+ * https://open-doc.dingtalk.com/docs/doc.htm?treeId=371&articleId=104975&docType=1
+ */
+public class eventChangeHelper {
+
+    /**
+     * 注册事件回调接口
+     */
+    public static String registerEventChange(String accessToken, List<String> callBackTag, String token, String aesKey, String url) throws OApiException {
+        String signUpUrl = Env.OAPI_HOST + "/call_back/register_call_back?" +
+                "access_token=" + accessToken;
+        JSONObject args = new JSONObject();
+        args.put("call_back_tag", callBackTag);
+        args.put("token", token);
+        args.put("aes_key", aesKey);
+        args.put("url", url);
+
+        JSONObject response = HttpHelper.httpPost(signUpUrl, args);
+        if (response.containsKey("errcode")) {
+            return response.getString("errcode");
+        } else {
+            return null;
+        }
+    }
+
+    //查询事件回调接口
+    public static String getEventChange(String accessToken) throws OApiException {
+        String url = Env.OAPI_HOST + "/call_back/get_call_back?" +
+                "access_token=" + accessToken;
+        JSONObject response = HttpHelper.httpGet(url);
+        return response.toString();
+    }
+
+    //更新事件回调接口
+    public static String updateEventChange(String accessToken, List<String> callBackTag, String token, String aesKey, String url) throws OApiException {
+        String signUpUrl = Env.OAPI_HOST + "/call_back/update_call_back?" +
+                "access_token=" + accessToken;
+        JSONObject args = new JSONObject();
+        args.put("call_back_tag", callBackTag);
+        args.put("token", token);
+        args.put("aes_key", aesKey);
+        args.put("url", url);
+
+        JSONObject response = HttpHelper.httpPost(signUpUrl, args);
+        if (response.containsKey("errcode")) {
+            return response.getString("errcode");
+        } else {
+            return null;
+        }
+    }
+
+    //删除事件回调接口
+    public static String deleteEventChange(String accessToken) throws OApiException {
+        String url = Env.OAPI_HOST + "/call_back/delete_call_back?" +
+                "access_token=" + accessToken;
+        JSONObject response = HttpHelper.httpGet(url);
+        return response.toString();
+    }
+
+
+    public static String getFailedResult(String accessToken) throws OApiException {
+        String url = Env.OAPI_HOST + "/call_back/get_call_back_failed_result?" +
+                "access_token=" + accessToken;
+        JSONObject response = HttpHelper.httpGet(url);
+        return response.toString();
+    }
+
+
+}

+ 53 - 0
src/main/java/com/izouma/dingtalk/media/MediaHelper.java

@@ -0,0 +1,53 @@
+package com.izouma.dingtalk.media;
+
+import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.open.client.ServiceFactory;
+import com.dingtalk.open.client.api.model.corp.UploadResult;
+import com.dingtalk.open.client.api.service.corp.MediaService;
+import com.izouma.dingtalk.Env;
+import com.izouma.dingtalk.utils.HttpHelper;
+
+import java.io.File;
+
+/**
+ * 管理多媒体文件
+ * https://open-doc.dingtalk.com/docs/doc.htm?source=search&treeId=373&articleId=104971&docType=1
+ */
+public class MediaHelper {
+
+    /**
+     * 资源文件类型
+     */
+    public static final String TYPE_IMAGE = "image";
+    public static final String TYPE_VOICE = "voice";
+    public static final String TYPE_VIDEO = "video";
+    public static final String TYPE_FILE = "file";
+
+
+    public static class MediaUploadResult {
+        public String type;
+        public String media_id;
+        public String created_at;
+    }
+
+    /**
+     * 上传多媒体文件
+     * <p>
+     */
+    public static UploadResult upload(String accessToken, String type, File file) throws Exception {
+
+        MediaService mediaService = ServiceFactory.getInstance().getOpenService(MediaService.class);
+        UploadResult uploadResult = mediaService.uploadMediaFile(accessToken, type, file);
+        return uploadResult;
+    }
+
+    /**
+     * 下载多媒体文件,目前sdk没有封装此接口,需要通过HTTP访问
+     */
+    public static void download(String accessToken, String mediaId, String fileDir) throws Exception {
+        String url = Env.OAPI_HOST + "/media/downloadFile?" +
+                "access_token=" + accessToken + "&media_id=" + mediaId;
+        JSONObject response = HttpHelper.downloadMedia(url, fileDir);
+        System.out.println(response);
+    }
+}

+ 16 - 0
src/main/java/com/izouma/dingtalk/message/ConversationMessageDelivery.java

@@ -0,0 +1,16 @@
+package com.izouma.dingtalk.message;
+
+public class ConversationMessageDelivery extends MessageDelivery {
+
+	public String sender;
+	public String cid;
+	public String agentid;
+	
+	public ConversationMessageDelivery(String sender, String cid, 
+			String agentId) {
+		this.sender = sender;
+		this.cid = cid;
+		this.agentid = agentId;
+	}
+		
+}

+ 17 - 0
src/main/java/com/izouma/dingtalk/message/ImageMessage.java

@@ -0,0 +1,17 @@
+package com.izouma.dingtalk.message;
+
+
+public class ImageMessage extends Message {
+	
+	public String media_id;
+	
+	public ImageMessage(String mediaId) {
+		super();
+		media_id = mediaId;
+	}
+	
+	@Override
+	public String type() {
+		return "image";
+	}
+}

+ 15 - 0
src/main/java/com/izouma/dingtalk/message/LightAppMessageDelivery.java

@@ -0,0 +1,15 @@
+package com.izouma.dingtalk.message;
+
+public class LightAppMessageDelivery extends MessageDelivery {
+
+	public String touser;
+	public String toparty;
+	public String agentid;
+	
+	public LightAppMessageDelivery(String toUsers, String toParties, String agentId) {
+		this.touser = toUsers;
+		this.toparty = toParties;
+		this.agentid = agentId;
+	}
+	
+}

+ 22 - 0
src/main/java/com/izouma/dingtalk/message/LinkMessage.java

@@ -0,0 +1,22 @@
+package com.izouma.dingtalk.message;
+
+public class LinkMessage extends Message {
+	
+	public String messageUrl;
+    public String picUrl;
+    public String title;
+    public String text;
+	
+	public LinkMessage(String messageUrl, String picUrl, String title, String text) {
+		super();
+		this.messageUrl = messageUrl;
+		this.picUrl = picUrl;
+		this.title = title;
+		this.text = text;
+	}
+	
+	@Override
+	public String type() {
+		return "link";
+	}
+}

+ 6 - 0
src/main/java/com/izouma/dingtalk/message/Message.java

@@ -0,0 +1,6 @@
+package com.izouma.dingtalk.message;
+
+
+public abstract class Message {
+	public abstract String type();
+}

+ 15 - 0
src/main/java/com/izouma/dingtalk/message/MessageDelivery.java

@@ -0,0 +1,15 @@
+package com.izouma.dingtalk.message;
+
+import com.dingtalk.open.client.api.model.corp.MessageBody;
+
+public class MessageDelivery {
+	
+	public String msgType;
+	public MessageBody message;
+	
+	public MessageDelivery withMessage(String msgType, MessageBody msg) {
+		this.msgType = msgType;
+		this.message = msg;
+		return this;
+	}
+}

+ 43 - 0
src/main/java/com/izouma/dingtalk/message/MessageHelper.java

@@ -0,0 +1,43 @@
+package com.izouma.dingtalk.message;
+
+import com.dingtalk.open.client.ServiceFactory;
+import com.dingtalk.open.client.api.model.corp.MessageSendResult;
+import com.dingtalk.open.client.api.service.corp.MessageService;
+
+/**
+ * 发送消息
+ */
+public class MessageHelper {
+
+    public static class Receipt {
+        String invaliduser;
+        String invalidparty;
+    }
+
+    /**
+     * 发送普通消息
+     *
+     * @param accessToken
+     * @param delivery
+     * @return
+     * @throws Exception
+     */
+    public static Receipt send(String accessToken, LightAppMessageDelivery delivery)
+            throws Exception {
+        MessageService messageService = ServiceFactory.getInstance().getOpenService(MessageService.class);
+        MessageSendResult reulst = messageService.sendToCorpConversation(accessToken, delivery.touser,
+                delivery.toparty, delivery.agentid, delivery.msgType, delivery.message);
+        Receipt receipt = new Receipt();
+        receipt.invaliduser = reulst.getInvaliduser();
+        receipt.invalidparty = reulst.getInvalidparty();
+        return receipt;
+    }
+
+
+    public static String send(String accessToken, ConversationMessageDelivery delivery)
+            throws Exception {
+        MessageService messageService = ServiceFactory.getInstance().getOpenService(MessageService.class);
+        return messageService.sendToNormalConversation(accessToken, delivery.sender,
+                delivery.cid, delivery.msgType, delivery.message);
+    }
+}

+ 69 - 0
src/main/java/com/izouma/dingtalk/message/OAMessage.java

@@ -0,0 +1,69 @@
+package com.izouma.dingtalk.message;
+
+import java.util.List;
+
+/** 
+  { 
+    "message_url": "http://dingtalk.com", 
+    "head": {
+        "bgcolor": "FFCC0000"
+    }, 
+    "body": {
+        "title": "标题", 
+        "form": [
+            {
+                "key": "姓名", 
+                "value": "张三"
+            }, 
+            {
+                "key": "年龄", 
+                "value": "30"
+            }
+        ], 
+        "rich": {
+            "num": "15.6", 
+            "unit": "元"
+        }, 
+        "content": "大段文本", 
+        "image": "@lADOAAGXIszazQKA", 
+        "file_count": "3", 
+        "author": "李四"
+    }
+ */
+public class OAMessage extends Message {
+	
+	public String message_url;
+	public Head head;
+	public Body body;
+	
+
+	@Override
+	public String type() {
+		return "oa";
+	}
+	
+	//content
+	public static class Head {
+		public String bgcolor;
+	}
+	
+	public static class Body {
+		public String title;
+		public List<Form> form;
+		public Rich rich;
+		public String content;
+		public String image;
+		public String file_found;
+		public String author;
+		
+		public static class Form {
+			public String key;
+			public String value;
+		}
+		
+		public static class Rich {
+			public String num;
+			public String unit;
+		}
+	}
+}

+ 17 - 0
src/main/java/com/izouma/dingtalk/message/TextMessage.java

@@ -0,0 +1,17 @@
+package com.izouma.dingtalk.message;
+
+
+public class TextMessage extends Message {
+	
+	public String content;	
+	
+	public TextMessage(String content) {
+		super();
+		this.content = content;
+	}
+	
+	@Override
+	public String type() {
+		return "text";
+	}
+}

+ 43 - 0
src/main/java/com/izouma/dingtalk/user/User.java

@@ -0,0 +1,43 @@
+package com.izouma.dingtalk.user;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.List;
+
+public class User {
+	public String userid;
+	public String name;
+	public boolean active;
+	public String avatar;
+	public List<Long> department;
+	public String position;
+	public String mobile;
+	public String tel;
+	public String workPlace;
+	public String remark;
+	public String email;
+	public String jobnumber;
+	public JSONObject extattr;
+	public boolean isAdmin;
+	public boolean isBoss;
+	public String dingId;
+
+
+	
+	public User() {
+	}
+	
+	public User(String userid, String name) {
+		this.userid = userid;
+		this.name = name;
+	}
+	
+	@Override
+	public String toString() {
+		List<User> users;
+		return "User[userid:" + userid + ", name:" + name + ", active:" + active + ", "
+				+ "avatar:" + avatar + ", department:" + department +
+				", position:" + position + ", mobile:" + mobile + ", email:" + email + 
+				", extattr:" + extattr;
+	}
+}

+ 143 - 0
src/main/java/com/izouma/dingtalk/user/UserHelper.java

@@ -0,0 +1,143 @@
+package com.izouma.dingtalk.user;
+
+import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.open.client.ServiceFactory;
+import com.dingtalk.open.client.api.model.corp.CorpUserBaseInfo;
+import com.dingtalk.open.client.api.model.corp.CorpUserDetail;
+import com.dingtalk.open.client.api.model.corp.CorpUserDetailList;
+import com.dingtalk.open.client.api.model.corp.CorpUserList;
+import com.dingtalk.open.client.api.service.corp.CorpUserService;
+import com.izouma.dingtalk.Env;
+import com.izouma.dingtalk.OApiException;
+import com.izouma.dingtalk.utils.FileUtils;
+import com.izouma.dingtalk.utils.HttpHelper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 通讯录成员相关的接口调用
+ */
+public class UserHelper {
+
+
+    /**
+     * 根据免登授权码查询免登用户userId
+     *
+     * @param accessToken
+     * @param code
+     * @return
+     * @throws Exception
+     */
+    public static CorpUserBaseInfo getUserInfo(String accessToken, String code) throws Exception {
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        return corpUserService.getUserinfo(accessToken, code);
+    }
+
+    /**
+     * 创建企业成员
+     * <p>
+     * https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=106816&docType=1#s1
+     */
+    public static String createUser(String accessToken, CorpUserDetail userDetail) throws Exception {
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        JSONObject js = (JSONObject) JSONObject.parse(userDetail.getOrderInDepts());
+        Map<Long, Long> orderInDepts = FileUtils.toHashMap(js);
+
+        String userId = corpUserService.createCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts,
+                userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(),
+                userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(),
+                userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr());
+
+        // 员工唯一标识ID
+        return userId;
+    }
+
+
+    /**
+     * 更新成员
+     * <p>
+     * https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=106816&docType=1#s2
+     */
+    public static void updateUser(String accessToken, CorpUserDetail userDetail) throws Exception {
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        JSONObject js = (JSONObject) JSONObject.parse(userDetail.getOrderInDepts());
+        Map<Long, Long> orderInDepts = FileUtils.toHashMap(js);
+
+        corpUserService.updateCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts,
+                userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(),
+                userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(),
+                userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr());
+    }
+
+
+    /**
+     * 删除成员
+     */
+    public static void deleteUser(String accessToken, String userid) throws Exception {
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        corpUserService.deleteCorpUser(accessToken, userid);
+    }
+
+
+    //获取成员
+    public static CorpUserDetail getUser(String accessToken, String userid) throws Exception {
+
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        return corpUserService.getCorpUser(accessToken, userid);
+    }
+
+    //批量删除成员
+    public static void batchDeleteUser(String accessToken, List<String> useridlist)
+            throws Exception {
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        corpUserService.batchdeleteCorpUserListByUserids(accessToken, useridlist);
+
+    }
+
+
+    //获取部门成员
+    public static CorpUserList getDepartmentUser(
+            String accessToken,
+            long departmentId,
+            Long offset,
+            Integer size,
+            String order)
+            throws Exception {
+
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        return corpUserService.getCorpUserSimpleList(accessToken, departmentId,
+                offset, size, order);
+    }
+
+
+    //获取部门成员(详情)
+    public static CorpUserDetailList getUserDetails(
+            String accessToken,
+            long departmentId,
+            Long offset,
+            Integer size,
+            String order)
+            throws Exception {
+
+        CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
+        return corpUserService.getCorpUserList(accessToken, departmentId,
+                offset, size, order);
+    }
+
+
+    /**
+     * 管理后台免登时通过CODE换取微应用管理员的身份信息
+     *
+     * @param ssoToken
+     * @param code
+     * @return
+     * @throws OApiException
+     */
+    public static JSONObject getAgentUserInfo(String ssoToken, String code) throws OApiException {
+        String url = Env.OAPI_HOST + "/sso/getuserinfo?" + "access_token=" + ssoToken + "&code=" + code;
+        JSONObject response = HttpHelper.httpGet(url);
+        return response;
+    }
+
+}

+ 135 - 0
src/main/java/com/izouma/dingtalk/utils/FileUtils.java

@@ -0,0 +1,135 @@
+package com.izouma.dingtalk.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.http.util.TextUtils;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 模拟accessToken和jsTicket的数据持久化<br/>
+ * <p>
+ * 正式项目最好是写入到Mysql
+ */
+public class FileUtils {
+
+    public static final String FILEPATH = "Permanent_Data";
+
+    // json写入文件
+    public synchronized static void write2File(Object json, String fileName) {
+        BufferedWriter writer = null;
+        File filePath = new File(FILEPATH);
+        JSONObject eJSON = null;
+
+        if (!filePath.exists() && !filePath.isDirectory()) {
+            filePath.mkdirs();
+        }
+
+        File file = new File(FILEPATH + File.separator + fileName + ".xml");
+        System.out.println("path:" + file.getPath() + " abs path:" + file.getAbsolutePath());
+        if (!file.exists()) {
+            try {
+                file.createNewFile();
+            } catch (Exception e) {
+                System.out.println("createNewFile,出现异常:");
+                e.printStackTrace();
+            }
+        } else {
+            eJSON = (JSONObject) read2JSON(fileName);
+        }
+
+        try {
+            writer = new BufferedWriter(new FileWriter(file));
+
+            if (eJSON == null) {
+                writer.write(json.toString());
+            } else {
+                Object[] array = ((JSONObject) json).keySet().toArray();
+                for (int i = 0; i < array.length; i++) {
+                    eJSON.put(array[i].toString(), ((JSONObject) json).get(array[i].toString()));
+                }
+
+                writer.write(eJSON.toString());
+            }
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (writer != null) {
+                    writer.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+    // 读文件到json
+    public static JSONObject read2JSON(String fileName) {
+        File file = new File(FILEPATH + File.separator + fileName + ".xml");
+        if (!file.exists()) {
+            return null;
+        }
+
+        BufferedReader reader = null;
+        String laststr = "";
+        try {
+            reader = new BufferedReader(new FileReader(file));
+            String tempString = null;
+            while ((tempString = reader.readLine()) != null) {
+                laststr += tempString;
+            }
+            reader.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return (JSONObject) JSON.parse(laststr);
+    }
+
+    // 通过key值获取文件中的value
+    public static Object getValue(String fileName, String key) {
+        JSONObject eJSON = null;
+        eJSON = (JSONObject) read2JSON(fileName);
+        if (null != eJSON && eJSON.containsKey(key)) {
+            @SuppressWarnings("unchecked")
+            Map<String, Object> values = JSON.parseObject(eJSON.toString(), Map.class);
+            return values.get(key);
+        } else {
+            return null;
+        }
+    }
+
+    public static HashMap<Long, Long> toHashMap(JSONObject js) {
+        if (js == null) {
+            return null;
+        }
+        HashMap<Long, Long> data = new HashMap<Long, Long>();
+        // 将json字符串转换成jsonObject
+        Set<String> set = js.keySet();
+        // 遍历jsonObject数据,添加到Map对象
+        Iterator<String> it = set.iterator();
+        while (it.hasNext()) {
+            String key = String.valueOf(it.next());
+            Long keyLong = Long.valueOf(key);
+
+            String value = js.getString(key);
+            Long valueLong;
+            if (TextUtils.isEmpty(value)) {
+                valueLong = js.getLong(key);
+            } else {
+                valueLong = Long.valueOf(value);
+            }
+            data.put(keyLong, valueLong);
+        }
+        return data;
+    }
+
+
+}

+ 251 - 0
src/main/java/com/izouma/dingtalk/utils/HttpHelper.java

@@ -0,0 +1,251 @@
+package com.izouma.dingtalk.utils;
+
+import com.izouma.dingtalk.OApiException;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.io.FileUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.client.RedirectLocations;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * HTTP请求封装,建议直接使用sdk的API
+ */
+public class HttpHelper {
+
+	public static JSONObject httpGet(String url) throws OApiException{
+        HttpGet httpGet = new HttpGet(url);
+        CloseableHttpResponse response = null;
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        RequestConfig requestConfig = RequestConfig.custom().
+        		setSocketTimeout(2000).setConnectTimeout(2000).build();
+        httpGet.setConfig(requestConfig);
+
+        try {
+            response = httpClient.execute(httpGet, new BasicHttpContext());
+
+            if (response.getStatusLine().getStatusCode() != 200) {
+
+                System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+                                   + ", url=" + url);
+                return null;
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                String resultStr = EntityUtils.toString(entity, "utf-8");
+
+                JSONObject result = JSON.parseObject(resultStr);
+                if (result.getInteger("errcode") == 0) {
+                    return result;
+                } else {
+                    System.out.println("request url=" + url + ",return value=");
+                    System.out.println(resultStr);
+                    int errCode = result.getInteger("errcode");
+                    String errMsg = result.getString("errmsg");
+                    throw new OApiException(errCode, errMsg);
+                }
+            }
+        } catch (IOException e) {
+            System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            if (response != null) try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return null;
+    }
+	
+	
+	public static JSONObject httpPost(String url, Object data) throws OApiException {
+        HttpPost httpPost = new HttpPost(url);
+        CloseableHttpResponse response = null;
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        RequestConfig requestConfig = RequestConfig.custom().
+        		setSocketTimeout(2000).setConnectTimeout(2000).build();
+        httpPost.setConfig(requestConfig);
+        httpPost.addHeader("Content-Type", "application/json");
+
+        try {
+        	StringEntity requestEntity = new StringEntity(JSON.toJSONString(data), "utf-8");
+            httpPost.setEntity(requestEntity);
+            
+            response = httpClient.execute(httpPost, new BasicHttpContext());
+
+            if (response.getStatusLine().getStatusCode() != 200) {
+
+                System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+                                   + ", url=" + url);
+                return null;
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                String resultStr = EntityUtils.toString(entity, "utf-8");
+
+                JSONObject result = JSON.parseObject(resultStr);
+                if (result.getInteger("errcode") == 0) {
+                	result.remove("errcode");
+                	result.remove("errmsg");
+                    return result;
+                } else {
+                    System.out.println("request url=" + url + ",return value=");
+                    System.out.println(resultStr);
+                    int errCode = result.getInteger("errcode");
+                    String errMsg = result.getString("errmsg");
+                    throw new OApiException(errCode, errMsg);
+                }
+            }
+        } catch (IOException e) {
+            System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            if (response != null) try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return null;
+    }
+	
+	
+	public static JSONObject uploadMedia(String url, File file) throws OApiException {
+        HttpPost httpPost = new HttpPost(url);
+        CloseableHttpResponse response = null;
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
+        httpPost.setConfig(requestConfig);
+
+        HttpEntity requestEntity = MultipartEntityBuilder.create().addPart("media",
+        		new FileBody(file, ContentType.APPLICATION_OCTET_STREAM, file.getName())).build();
+        httpPost.setEntity(requestEntity);
+
+        try {
+            response = httpClient.execute(httpPost, new BasicHttpContext());
+
+            if (response.getStatusLine().getStatusCode() != 200) {
+
+                System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+                                   + ", url=" + url);
+                return null;
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                String resultStr = EntityUtils.toString(entity, "utf-8");
+
+                JSONObject result = JSON.parseObject(resultStr);
+                if (result.getInteger("errcode") == 0) {
+                    // 成功
+                	result.remove("errcode");
+                	result.remove("errmsg");
+                    return result;
+                } else {
+                    System.out.println("request url=" + url + ",return value=");
+                    System.out.println(resultStr);
+                    int errCode = result.getInteger("errcode");
+                    String errMsg = result.getString("errmsg");
+                    throw new OApiException(errCode, errMsg);
+                }
+            }
+        } catch (IOException e) {
+            System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            if (response != null) try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return null;
+    }
+	
+	
+	public static JSONObject downloadMedia(String url, String fileDir) throws OApiException {
+        HttpGet httpGet = new HttpGet(url);
+        CloseableHttpResponse response = null;
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
+        httpGet.setConfig(requestConfig);
+
+        try {
+            HttpContext localContext = new BasicHttpContext();
+
+            response = httpClient.execute(httpGet, localContext);
+
+            RedirectLocations locations = (RedirectLocations) localContext.getAttribute(HttpClientContext.REDIRECT_LOCATIONS);
+            if (locations != null) {
+                URI downloadUrl = locations.getAll().get(0);
+                String filename = downloadUrl.toURL().getFile();
+                System.out.println("downloadUrl=" + downloadUrl);
+                File downloadFile = new File(fileDir + File.separator + filename);
+                FileUtils.writeByteArrayToFile(downloadFile, EntityUtils.toByteArray(response.getEntity()));
+                JSONObject obj = new JSONObject();
+                obj.put("downloadFilePath", downloadFile.getAbsolutePath());
+                obj.put("httpcode", response.getStatusLine().getStatusCode());
+                
+               
+                
+                return obj;
+            } else {
+                if (response.getStatusLine().getStatusCode() != 200) {
+
+                    System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+                                       + ", url=" + url);
+                    return null;
+                }
+                HttpEntity entity = response.getEntity();
+                if (entity != null) {
+                    String resultStr = EntityUtils.toString(entity, "utf-8");
+
+                    JSONObject result = JSON.parseObject(resultStr);
+                    if (result.getInteger("errcode") == 0) {
+                        // 成功
+                    	result.remove("errcode");
+                    	result.remove("errmsg");
+                        return result;
+                    } else {
+                        System.out.println("request url=" + url + ",return value=");
+                        System.out.println(resultStr);
+                        int errCode = result.getInteger("errcode");
+                        String errMsg = result.getString("errmsg");
+                        throw new OApiException(errCode, errMsg);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            if (response != null) try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return null;
+    }
+}

+ 53 - 0
src/main/java/com/izouma/dingtalk/utils/aes/DingTalkEncryptException.java

@@ -0,0 +1,53 @@
+package com.izouma.dingtalk.utils.aes;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 钉钉开放平台加解密异常类
+ */
+public class DingTalkEncryptException extends Exception {
+    /**成功**/
+    public static final int SUCCESS = 0;
+    /**加密明文文本非法**/
+    public final static int  ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
+    /**加密时间戳参数非法**/
+    public final static int  ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
+    /**加密随机字符串参数非法**/
+    public final static int  ENCRYPTION_NONCE_ILLEGAL = 900003;
+    /**不合法的aeskey**/
+    public final static int AES_KEY_ILLEGAL = 900004;
+    /**签名不匹配**/
+    public final static int SIGNATURE_NOT_MATCH = 900005;
+    /**计算签名错误**/
+    public final static int COMPUTE_SIGNATURE_ERROR = 900006;
+    /**计算加密文字错误**/
+    public final static int COMPUTE_ENCRYPT_TEXT_ERROR  = 900007;
+    /**计算解密文字错误**/
+    public final static int COMPUTE_DECRYPT_TEXT_ERROR  = 900008;
+    /**计算解密文字长度不匹配**/
+    public final static int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR  = 900009;
+    /**计算解密文字corpid不匹配**/
+    public final static int COMPUTE_DECRYPT_TEXT_CORPID_ERROR  = 900010;
+
+    private static Map<Integer,String> msgMap = new HashMap<Integer,String>();
+    static{
+        msgMap.put(SUCCESS,"成功");
+        msgMap.put(ENCRYPTION_PLAINTEXT_ILLEGAL,"加密明文文本非法");
+        msgMap.put(ENCRYPTION_TIMESTAMP_ILLEGAL,"加密时间戳参数非法");
+        msgMap.put(ENCRYPTION_NONCE_ILLEGAL,"加密随机字符串参数非法");
+        msgMap.put(SIGNATURE_NOT_MATCH,"签名不匹配");
+        msgMap.put(COMPUTE_SIGNATURE_ERROR,"签名计算失败");
+        msgMap.put(AES_KEY_ILLEGAL,"不合法的aes key");
+        msgMap.put(COMPUTE_ENCRYPT_TEXT_ERROR,"计算加密文字错误");
+        msgMap.put(COMPUTE_DECRYPT_TEXT_ERROR,"计算解密文字错误");
+        msgMap.put(COMPUTE_DECRYPT_TEXT_LENGTH_ERROR,"计算解密文字长度不匹配");
+        msgMap.put(COMPUTE_DECRYPT_TEXT_CORPID_ERROR,"计算解密文字corpid或者suiteKey不匹配");
+    }
+
+    public Integer  code;
+    public DingTalkEncryptException(Integer exceptionCode){
+        super(msgMap.get(exceptionCode));
+        this.code = exceptionCode;
+    }
+}

+ 211 - 0
src/main/java/com/izouma/dingtalk/utils/aes/DingTalkEncryptor.java

@@ -0,0 +1,211 @@
+package com.izouma.dingtalk.utils.aes;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 钉钉开放平台加解密方法
+ * 在ORACLE官方网站下载JCE无限制权限策略文件
+ *     JDK6的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
+ *     JDK7的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
+ */
+public class DingTalkEncryptor {
+
+    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固定长度**/
+    private static final Integer AES_ENCODE_KEY_LENGTH = 43;
+    /**加密随机字符串字节长度**/
+    private static final Integer RANDOM_LENGTH = 16;
+
+    /**
+     * 构造函数
+     * @param token             钉钉开放平台上,开发者设置的token
+     * @param encodingAesKey  钉钉开放台上,开发者设置的EncodingAESKey
+     * @param corpId           ISV进行配置的时候应该传对应套件的SUITE_KEY,普通企业是Corpid
+     * @throws DingTalkEncryptException 执行失败,请查看该异常的错误码和具体的错误信息
+     */
+    public DingTalkEncryptor(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 + "=");
+    }
+
+    /**
+     * 将和钉钉开放平台同步的消息体加密,返回加密Map
+     * @param plaintext     传递的消息体明文
+     * @param timeStamp      时间戳
+     * @param nonce           随机字符串
+     * @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);
+        }
+        // 加密
+        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;
+    }
+
+    /**
+     * 密文解密
+     * @param msgSignature     签名串
+     * @param timeStamp        时间戳
+     * @param nonce             随机串
+     * @param encryptMsg       密文
+     * @return                  解密后的原文
+     * @throws DingTalkEncryptException
+     */
+    public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg)throws DingTalkEncryptException {
+        //校验签名
+        String signature = getSignature(token, timeStamp, nonce, encryptMsg);
+        if (!signature.equals(msgSignature)) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
+        }
+        // 解密
+        String result = decrypt(encryptMsg);
+        return result;
+    }
+
+
+    /*
+     * 对明文加密.
+     * @param text 需要加密的明文
+     * @return 加密后base64编码的字符串
+     */
+    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);
+        }
+    }
+
+    /*
+     * 对密文进行解密.
+     * @param text 需要解密的密文
+     * @return 解密得到的明文
+     */
+    private String decrypt(String text) throws DingTalkEncryptException {
+        byte[] originalArr;
+        try {
+            // 设置解密模式为AES的CBC模式
+            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);
+            // 使用BASE64对密文进行解码
+            byte[] encrypted = Base64.decodeBase64(text);
+            // 解密
+            originalArr = cipher.doFinal(encrypted);
+        } catch (Exception e) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
+        }
+
+        String plainText;
+        String fromCorpid;
+        try {
+            // 去除补位字符
+            byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
+            // 分离16位随机字符串,网络字节序和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);
+        }
+
+        // corpid不相同的情况
+        if (!fromCorpid.equals(corpId)) {
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);
+        }
+        return plainText;
+    }
+
+    /**
+     * 数字签名
+     * @param token         isv token
+     * @param timestamp     时间戳
+     * @param nonce          随机串
+     * @param encrypt       加密文本
+     * @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);
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < 4; i++) {
+                sb.append(array[i]);
+            }
+            String str = sb.toString();
+            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);
+        }
+    }
+
+}

+ 52 - 0
src/main/java/com/izouma/dingtalk/utils/aes/DingTalkJsApiSingnature.java

@@ -0,0 +1,52 @@
+package com.izouma.dingtalk.utils.aes;
+
+import java.security.MessageDigest;
+import java.util.Formatter;
+
+/**
+ * 钉钉jsapi签名工具类
+ */
+public class DingTalkJsApiSingnature {
+    /**
+     * 获取jsapi签名
+     * @param url
+     * @param nonce
+     * @param timeStamp
+     * @param jsTicket
+     * @return
+     * @throws DingTalkEncryptException
+     */
+    public static String getJsApiSingnature(String url,String nonce,Long timeStamp,String jsTicket) throws DingTalkEncryptException{
+        String plainTex = "jsapi_ticket=" + jsTicket +"&noncestr=" + nonce +"&timestamp=" + timeStamp + "&url=" + url;
+        System.out.println(plainTex);
+        String signature = "";
+        try{
+            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
+            crypt.reset();
+            crypt.update(plainTex.getBytes("UTF-8"));
+            signature = byteToHex(crypt.digest());
+            return signature;
+        }catch (Exception e){
+            throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
+        }
+    }
+
+    private static String byteToHex(final byte[] hash) {
+        Formatter formatter = new Formatter();
+        for (byte b : hash){
+            formatter.format("%02x", b);
+        }
+        String result = formatter.toString();
+        formatter.close();
+        return result;
+    }
+
+
+    public static void main(String args[]) throws Exception{
+        String url="http://10.62.53.138:3000/jsapi";
+        String nonce="abcdefgh";
+        Long timeStamp = 1437027269927L;
+        String tikcet="zHoQdGJuH0ZDebwo7sLqLzHGUueLmkWCC4RycYgkuvDu3eoROgN5qhwnQLgfzwEXtuR9SDzh6BdhyVngzAjrxV";
+        System.err.println(getJsApiSingnature(url,nonce,timeStamp,tikcet));
+    }
+}

+ 50 - 0
src/main/java/com/izouma/dingtalk/utils/aes/PKCS7Padding.java

@@ -0,0 +1,50 @@
+package com.izouma.dingtalk.utils.aes;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+/*
+ * PKCS7算法的加密填充
+ */
+
+public class PKCS7Padding {
+    private final static Charset CHARSET    = Charset.forName("utf-8");
+    private final static int     BLOCK_SIZE = 32;
+
+    /**
+     * 填充mode字节
+     * @param count
+     * @return
+     */
+    public static byte[] getPaddingBytes(int count) {
+        int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
+        if (amountToPad == 0) {
+            amountToPad = BLOCK_SIZE;
+        }
+        char padChr = chr(amountToPad);
+        String tmp = new String();
+        for (int index = 0; index < amountToPad; index++) {
+            tmp += padChr;
+        }
+        return tmp.getBytes(CHARSET);
+    }
+
+    /**
+     * 移除mode填充字节
+     * @param decrypted
+     * @return
+     */
+    public static byte[] removePaddingBytes(byte[] decrypted) {
+        int pad = (int) decrypted[decrypted.length - 1];
+        if (pad < 1 || pad > BLOCK_SIZE) {
+            pad = 0;
+        }
+        return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
+    }
+
+    private static char chr(int a) {
+        byte target = (byte) (a & 0xFF);
+        return (char) target;
+    }
+
+}

+ 53 - 0
src/main/java/com/izouma/dingtalk/utils/aes/Utils.java

@@ -0,0 +1,53 @@
+package com.izouma.dingtalk.utils.aes;
+
+import java.util.Random;
+
+/**
+ * 加解密工具类
+ */
+public class Utils {
+    
+    /**
+     * 获取随机字符串
+     *
+     * @return
+     */
+    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();
+    }
+
+
+    /*
+     * int转byte数组,高位在前
+     */
+    public static byte[] int2Bytes(int count) {
+        byte[] byteArr = new byte[4];
+        byteArr[3] = (byte) (count & 0xFF);
+        byteArr[2] = (byte) (count >> 8 & 0xFF);
+        byteArr[1] = (byte) (count >> 16 & 0xFF);
+        byteArr[0] = (byte) (count >> 24 & 0xFF);
+        return byteArr;
+    }
+
+    /**
+     * 高位在前bytes数组转int
+     *
+     * @param byteArr
+     * @return
+     */
+    public static int bytes2int(byte[] byteArr) {
+        int count = 0;
+        for (int i = 0; i < 4; i++) {
+            count <<= 8;
+            count |= byteArr[i] & 0xff;
+        }
+        return count;
+    }
+}

+ 17 - 0
src/main/java/com/izouma/ticketExchange/TicketExchangeApplication.java

@@ -0,0 +1,17 @@
+package com.izouma.ticketExchange;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@SpringBootApplication
+@EnableJpaAuditing
+@EnableSwagger2
+public class TicketExchangeApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TicketExchangeApplication.class, args);
+    }
+
+}

+ 12 - 0
src/main/java/com/izouma/ticketExchange/annotations/Searchable.java

@@ -0,0 +1,12 @@
+package com.izouma.ticketExchange.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Searchable {
+    boolean value() default true;
+}

+ 17 - 0
src/main/java/com/izouma/ticketExchange/config/Constants.java

@@ -0,0 +1,17 @@
+package com.izouma.ticketExchange.config;
+
+public interface Constants {
+
+    public interface Regex {
+        String PHONE    = "^1[3-9]\\d{9}$";
+        String USERNAME = "^[_.@A-Za-z0-9-]*$";
+        String CHINESE  = "^[\\u4e00-\\u9fa5]+$";
+        String ID_NO    = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0-2]\\d)|3[0-1])\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0-2]\\d)|3[0-1])\\d{3}[0-9xX]$";
+    }
+
+    String DEFAULT_AVATAR = "https://zhumj.oss-cn-hangzhou.aliyuncs.com/image/user.jpg";
+
+    String SMS_SIGN_NAME = "走马信息";
+
+    String SMS_TEMPLATE_CODE_GENERIC = "SMS_175485688";
+}

+ 148 - 0
src/main/java/com/izouma/ticketExchange/config/DateConfig.java

@@ -0,0 +1,148 @@
+package com.izouma.ticketExchange.config;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+@Configuration
+public class DateConfig {
+
+    /**
+     * 默认日期时间格式
+     */
+    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    /**
+     * 默认日期格式
+     */
+    public static final String DEFAULT_DATE_FORMAT      = "yyyy-MM-dd";
+    /**
+     * 默认时间格式
+     */
+    public static final String DEFAULT_TIME_FORMAT      = "HH:mm:ss";
+
+    /**
+     * LocalDate转换器,用于转换RequestParam和PathVariable参数
+     */
+    @Bean
+    public Converter<String, LocalDate> localDateConverter() {
+        return new Converter<String, LocalDate>() {
+            @Override
+            public LocalDate convert(String source) {
+                return LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
+            }
+        };
+    }
+
+    /**
+     * LocalDateTime转换器,用于转换RequestParam和PathVariable参数
+     */
+    @Bean
+    public Converter<String, LocalDateTime> localDateTimeConverter() {
+        return new Converter<String, LocalDateTime>() {
+            @Override
+            public LocalDateTime convert(String source) {
+                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT));
+            }
+        };
+    }
+
+    /**
+     * LocalTime转换器,用于转换RequestParam和PathVariable参数
+     */
+    @Bean
+    public Converter<String, LocalTime> localTimeConverter() {
+        return new Converter<String, LocalTime>() {
+            @Override
+            public LocalTime convert(String source) {
+                return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT));
+            }
+        };
+    }
+
+    /**
+     * Date转换器,用于转换RequestParam和PathVariable参数
+     */
+    @Bean
+    public Converter<String, Date> dateConverter() {
+        return new Converter<String, Date>() {
+            @Override
+            public Date convert(String source) {
+                SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
+                try {
+                    return format.parse(source);
+                } catch (ParseException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+    }
+
+
+    /**
+     * Json序列化和反序列化转换器,用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json
+     */
+    @Bean
+    public ObjectMapper objectMapper() {
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
+
+        //LocalDateTime系列序列化和反序列化模块,继承自jsr310,我们在这里修改了日期格式
+        JavaTimeModule javaTimeModule = new JavaTimeModule();
+        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
+        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
+        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
+        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
+        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
+        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
+
+
+        //Date序列化和反序列化
+        javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
+            @Override
+            public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+                SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
+                String formattedDate = formatter.format(date);
+                jsonGenerator.writeString(formattedDate);
+            }
+        });
+        javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
+            @Override
+            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+                SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
+                String date = jsonParser.getText();
+                try {
+                    return format.parse(date);
+                } catch (ParseException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        objectMapper.registerModule(javaTimeModule);
+        return objectMapper;
+    }
+
+
+}
+

+ 20 - 0
src/main/java/com/izouma/ticketExchange/config/ErrorPageConfig.java

@@ -0,0 +1,20 @@
+package com.izouma.ticketExchange.config;
+
+import org.springframework.boot.web.server.ConfigurableWebServerFactory;
+import org.springframework.boot.web.server.ErrorPage;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+
+@Configuration
+public class ErrorPageConfig {
+    @Bean
+    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
+
+        return (factory -> {
+            ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/static/admin/index.html");
+            factory.addErrorPages(errorPage404);
+        });
+    }
+}

+ 36 - 0
src/main/java/com/izouma/ticketExchange/config/LocalDateTimeSerializerConfig.java

@@ -0,0 +1,36 @@
+package com.izouma.ticketExchange.config;
+
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Configuration
+public class LocalDateTimeSerializerConfig {
+    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
+    private String pattern;
+
+    @Bean
+    public LocalDateTimeSerializer localDateTimeDeserializer() {
+        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+    }
+
+    @Bean
+    public LocalDateSerializer localDateSerializer() {
+        return new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+    }
+
+    @Bean
+    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
+        return builder -> {
+            builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
+            builder.serializerByType(LocalDate.class, localDateSerializer());
+        };
+    }
+}

+ 44 - 0
src/main/java/com/izouma/ticketExchange/config/RedisConfig.java

@@ -0,0 +1,44 @@
+package com.izouma.ticketExchange.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+@AutoConfigureAfter(RedisAutoConfiguration.class)
+@EnableRedisRepositories
+public class RedisConfig {
+
+    @Bean
+    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(redisConnectionFactory);
+
+        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
+        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        serializer.setObjectMapper(mapper);
+
+        template.setValueSerializer(serializer);
+        //使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(serializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+
+}

+ 24 - 0
src/main/java/com/izouma/ticketExchange/config/SpringSecurityAuditorAware.java

@@ -0,0 +1,24 @@
+package com.izouma.ticketExchange.config;
+
+import com.izouma.ticketExchange.domain.User;
+import com.izouma.ticketExchange.utils.SecurityUtils;
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Nonnull;
+import java.util.Optional;
+
+@Component
+public class SpringSecurityAuditorAware implements AuditorAware<String> {
+
+    @Override
+    @Nonnull
+    public Optional<String> getCurrentAuditor() {
+        String auditor = "system";
+        User user = SecurityUtils.getAuthenticatedUser();
+        if (user != null) {
+            auditor = user.getNickname() + "(" + user.getId() + ")";
+        }
+        return Optional.of(auditor);
+    }
+}

+ 75 - 0
src/main/java/com/izouma/ticketExchange/config/WebMvcConfig.java

@@ -0,0 +1,75 @@
+package com.izouma.ticketExchange.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+    @Value("${storage.local_path}")
+    private String localPath;
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        // registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+        // registry.addResourceHandler("webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
+        registry.addResourceHandler("/admin/**").addResourceLocations("classpath:/static/admin/");
+        registry.addResourceHandler("/files/**").addResourceLocations("file:" + localPath);
+    }
+
+    @Bean
+    public Docket createApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(new ApiInfoBuilder()
+                                 .title("筑梦居接口文档")
+                                 .version("1.0.0")
+                                 .termsOfServiceUrl("#")
+                                 .description("筑梦居接口文档")
+                                 .build())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.izouma.zhumj.web"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    // @Bean
+    // public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {
+    //     MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
+    //     //设置日期格式
+    //     ObjectMapper objectMapper = new ObjectMapper();
+    //     objectMapper.setDateFormat(CustomDateFormat.instance);
+    //     objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+    //     mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
+    //     //设置中文编码格式
+    //     List<MediaType> list = new ArrayList<>();
+    //     list.add(MediaType.APPLICATION_JSON_UTF8);
+    //     mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
+    //     return mappingJackson2HttpMessageConverter;
+    // }
+
+//    @Override
+//    public void addFormatters(FormatterRegistry registry) {
+//        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
+//        registrar.setUseIsoFormat(true);
+//        registrar.registerFormatters(registry);
+//    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedHeaders("*")
+                .allowCredentials(true)
+                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH")
+                .exposedHeaders("Content-Disposition");
+    }
+
+}

+ 74 - 0
src/main/java/com/izouma/ticketExchange/config/WxMpConfiguration.java

@@ -0,0 +1,74 @@
+package com.izouma.ticketExchange.config;
+
+import com.izouma.ticketExchange.mpHandler.LogHandler;
+import lombok.AllArgsConstructor;
+import me.chanjar.weixin.mp.api.WxMpMessageRouter;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
+import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@AllArgsConstructor
+@Configuration
+@EnableConfigurationProperties(WxMpProperties.class)
+public class WxMpConfiguration {
+    private final WxMpProperties properties;
+    private final LogHandler     logHandler;
+
+    @Bean
+    public WxMpService wxMpService() {
+        WxMpDefaultConfigImpl mpConfig = new WxMpDefaultConfigImpl();
+        mpConfig.setAppId(properties.getAppId());
+        mpConfig.setSecret(properties.getAppSecret());
+        mpConfig.setAccessToken(properties.getToken());
+        mpConfig.setAesKey(properties.getAesKey());
+        WxMpService service = new WxMpServiceImpl();
+        service.setWxMpConfigStorage(mpConfig);
+        return service;
+    }
+
+    @Bean
+    public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
+        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
+
+        // 记录所有事件的日志 (异步执行)
+        newRouter.rule().handler(this.logHandler).next();
+
+        /*// 接收客服会话管理事件
+        newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION).handler(this.kfSessionHandler).end();
+        newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION).handler(this.kfSessionHandler).end();
+        newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION).handler(this.kfSessionHandler).end();
+
+        // 门店审核事件
+        newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();
+
+        // 自定义菜单事件
+        newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.CLICK).handler(this.menuHandler).end();
+
+        // 点击菜单连接事件
+        newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.VIEW).handler(this.nullHandler).end();
+
+        // 关注事件
+        newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
+
+        // 取消关注事件
+        newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
+
+        // 上报地理位置事件
+        newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.LOCATION).handler(this.locationHandler).end();
+
+        // 接收地理位置消息
+        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION).handler(this.locationHandler).end();
+
+        // 扫码事件
+        newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.SCAN).handler(this.scanHandler).end();
+
+        // 默认
+        newRouter.rule().async(false).handler(this.msgHandler).end();*/
+
+        return newRouter;
+    }
+
+}

+ 13 - 0
src/main/java/com/izouma/ticketExchange/config/WxMpProperties.java

@@ -0,0 +1,13 @@
+package com.izouma.ticketExchange.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "wx.mp")
+public class WxMpProperties {
+    private String appId;
+    private String appSecret;
+    private String token;
+    private String aesKey;
+}

+ 47 - 0
src/main/java/com/izouma/ticketExchange/config/WxPayConfiguration.java

@@ -0,0 +1,47 @@
+package com.izouma.ticketExchange.config;
+
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Binary Wang
+ */
+@Configuration
+@ConditionalOnClass(WxPayService.class)
+@EnableConfigurationProperties(WxPayProperties.class)
+public class WxPayConfiguration {
+    private WxPayProperties properties;
+
+    @Autowired
+    public WxPayConfiguration(WxPayProperties properties) {
+        this.properties = properties;
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    public WxPayService wxService() {
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
+        payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
+        payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
+        payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
+        payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
+        payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
+
+        // 可以指定是否使用沙箱环境
+        payConfig.setUseSandboxEnv(false);
+
+        WxPayService wxPayService = new WxPayServiceImpl();
+        wxPayService.setConfig(payConfig);
+        return wxPayService;
+    }
+
+}

+ 97 - 0
src/main/java/com/izouma/ticketExchange/config/WxPayProperties.java

@@ -0,0 +1,97 @@
+package com.izouma.ticketExchange.config;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * wxpay pay properties
+ *
+ * @author Binary Wang
+ */
+@ConfigurationProperties(prefix = "wx.pay")
+public class WxPayProperties {
+  /**
+   * 设置微信公众号或者小程序等的appid
+   */
+  private String appId;
+
+  /**
+   * 微信支付商户号
+   */
+  private String mchId;
+
+  /**
+   * 微信支付商户密钥
+   */
+  private String mchKey;
+
+  /**
+   * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
+   */
+  private String subAppId;
+
+  /**
+   * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
+   */
+  private String subMchId;
+
+  /**
+   * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
+   */
+  private String keyPath;
+
+  public String getAppId() {
+    return this.appId;
+  }
+
+  public void setAppId(String appId) {
+    this.appId = appId;
+  }
+
+  public String getMchId() {
+    return mchId;
+  }
+
+  public void setMchId(String mchId) {
+    this.mchId = mchId;
+  }
+
+  public String getMchKey() {
+    return mchKey;
+  }
+
+  public void setMchKey(String mchKey) {
+    this.mchKey = mchKey;
+  }
+
+  public String getSubAppId() {
+    return subAppId;
+  }
+
+  public void setSubAppId(String subAppId) {
+    this.subAppId = subAppId;
+  }
+
+  public String getSubMchId() {
+    return subMchId;
+  }
+
+  public void setSubMchId(String subMchId) {
+    this.subMchId = subMchId;
+  }
+
+  public String getKeyPath() {
+    return this.keyPath;
+  }
+
+  public void setKeyPath(String keyPath) {
+    this.keyPath = keyPath;
+  }
+
+  @Override
+  public String toString() {
+    return ToStringBuilder.reflectionToString(this,
+        ToStringStyle.MULTI_LINE_STYLE);
+  }
+}

+ 32 - 0
src/main/java/com/izouma/ticketExchange/converter/LongArrayConverter.java

@@ -0,0 +1,32 @@
+package com.izouma.ticketExchange.converter;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.persistence.AttributeConverter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class LongArrayConverter implements AttributeConverter<List<Long>, String> {
+    @Override
+    public String convertToDatabaseColumn(List<Long> longs) {
+        if (longs != null && !longs.isEmpty())
+            return StringUtils.join(longs, ",");
+        return null;
+    }
+
+    @Override
+    public List<Long> convertToEntityAttribute(String s) {
+        if (StringUtils.isNotEmpty(s)) {
+            return Arrays.asList(s.split(",")).stream().map(new Function<String, Long>() {
+                @Override
+                public Long apply(String s) {
+                    return Long.parseLong(s);
+                }
+            }).collect(Collectors.toList());
+        }
+        return new ArrayList<>();
+    }
+}

+ 25 - 0
src/main/java/com/izouma/ticketExchange/converter/StringArrayConverter.java

@@ -0,0 +1,25 @@
+package com.izouma.ticketExchange.converter;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.persistence.AttributeConverter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class StringArrayConverter implements AttributeConverter<List<String>, String> {
+    @Override
+    public String convertToDatabaseColumn(List<String> strings) {
+        if (strings != null && !strings.isEmpty())
+            return StringUtils.join(strings, ",");
+        return null;
+    }
+
+    @Override
+    public List<String> convertToEntityAttribute(String s) {
+        if (StringUtils.isNotEmpty(s)) {
+            return Arrays.asList(s.split(","));
+        }
+        return new ArrayList<>();
+    }
+}

+ 24 - 0
src/main/java/com/izouma/ticketExchange/converter/StringToMapConverter.java

@@ -0,0 +1,24 @@
+package com.izouma.ticketExchange.converter;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Nullable;
+import java.io.IOException;
+import java.util.Map;
+
+@Component
+public class StringToMapConverter implements Converter<String, Map<String, Object>> {
+
+    @Override
+    public Map<String, Object> convert(@Nullable String source) {
+        try {
+            return new ObjectMapper().readValue(source, new TypeReference<Map<String, Object>>() {
+            });
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+}

+ 81 - 0
src/main/java/com/izouma/ticketExchange/domain/BaseEntity.java

@@ -0,0 +1,81 @@
+package com.izouma.ticketExchange.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.hibernate.envers.Audited;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@MappedSuperclass
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public abstract class BaseEntity {
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    private Long id;
+
+    @JsonIgnore
+    @CreatedBy
+    private String createdBy;
+
+    @JsonIgnore
+    @CreatedDate
+    private LocalDateTime createdAt;
+
+    @JsonIgnore
+    @LastModifiedBy
+    private String modifiedBy;
+
+    @JsonIgnore
+    @LastModifiedDate
+    private LocalDateTime modifiedAt;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    public void setCreatedBy(String createdBy) {
+        this.createdBy = createdBy;
+    }
+
+    public LocalDateTime getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(LocalDateTime createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public String getModifiedBy() {
+        return modifiedBy;
+    }
+
+    public void setModifiedBy(String modifiedBy) {
+        this.modifiedBy = modifiedBy;
+    }
+
+    public LocalDateTime getModifiedAt() {
+        return modifiedAt;
+    }
+
+    public void setModifiedAt(LocalDateTime modifiedAt) {
+        this.modifiedAt = modifiedAt;
+    }
+}

+ 79 - 0
src/main/java/com/izouma/ticketExchange/domain/BedInfo.java

@@ -0,0 +1,79 @@
+package com.izouma.ticketExchange.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.izouma.ticketExchange.annotations.Searchable;
+import com.izouma.ticketExchange.enums.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "床位信息", description = "床位信息")
+public class BedInfo extends BaseEntity implements Serializable {
+
+    @ApiModelProperty(value = "房间Id", name = "roomId")
+    private Long roomId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "roomId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private RoomInfo roomInfo;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "名称", name = "bedName")
+    private String bedName;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "号码", name = "bedCode")
+    private String bedCode;
+
+    @Searchable
+    @ApiModelProperty(value = "简称", name = "shortName")
+    private String shortName;
+
+
+    @ApiModelProperty(value = "预定状态", name = "bookStatus")
+    @Enumerated(EnumType.STRING)
+    private BookStatus bookStatus;
+
+    @ApiModelProperty(value = "入住状态", name = "checkInStatus")
+    @Enumerated(EnumType.STRING)
+    private CheckInStatus checkInStatus;
+
+    @ApiModelProperty(value = "卫生状态", name = "cleaningStatus")
+    @Enumerated(EnumType.STRING)
+    private CleaningStatus cleaningStatus;
+
+    @ApiModelProperty(value = "维修状态", name = "repairStatus")
+    @Enumerated(EnumType.STRING)
+    private RepairStatus repairStatus;
+
+    @ApiModelProperty(value = "锁定状态", name = "lockStatus")
+    @Enumerated(EnumType.STRING)
+    private LockStatus lockStatus;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+
+}

+ 40 - 0
src/main/java/com/izouma/ticketExchange/domain/BuildingInfo.java

@@ -0,0 +1,40 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import java.io.Serializable;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "楼栋信息", description = "楼栋信息")
+public class BuildingInfo extends BaseEntity implements Serializable {
+
+    @ApiModelProperty(value = "门店Id", name = "storeId")
+    private Long storeId;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "名称", name = "name")
+    private String name;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+
+}

+ 95 - 0
src/main/java/com/izouma/ticketExchange/domain/CheckinInfo.java

@@ -0,0 +1,95 @@
+package com.izouma.ticketExchange.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.izouma.ticketExchange.enums.CheckInType;
+import com.izouma.ticketExchange.enums.DepositStatus;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "入住信息", description = "入住信息")
+public class CheckinInfo extends BaseEntity {
+    @ApiModelProperty(value = "门店ID", name = "storeId")
+    private Long storeId;
+
+    @ApiModelProperty(value = "房间ID", name = "roomId")
+    private Long roomId;
+
+    @ApiModelProperty(value = "床位ID", name = "bedId")
+    private Long bedId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "storeId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private StoreInfo storeInfo;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "roomId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private RoomInfo roomInfo;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "bedId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private BedInfo bedInfo;
+
+    @ApiModelProperty(value = "姓名", name = "name")
+    private String name;
+
+    @ApiModelProperty(value = "身份证", name = "idNo")
+    private String idNo;
+
+    @ApiModelProperty(value = "手机", name = "phone")
+    private String phone;
+
+    @ApiModelProperty(value = "入住时间", name = "checkinTime")
+    private LocalDateTime checkinTime;
+
+    @ApiModelProperty(value = "退宿时间", name = "checkoutTime")
+    private LocalDateTime checkoutTime;
+
+    @ApiModelProperty(value = "订单ID", name = "orderId")
+    private Long orderId;
+
+    @Column(precision = 10, scale = 2)
+    @ApiModelProperty(value = "押金金额", name = "depositAmount")
+    private BigDecimal depositAmount;
+
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty(value = "押金状态", name = "depositStatus")
+    private DepositStatus depositStatus;
+
+    @ApiModelProperty(value = "押金付款记录", name = "depositRecordId")
+    private Long depositRecordId;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "退宿", name = "checkout")
+    private Boolean checkout = false;
+
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty(value = "入住类型", name = "checkInType")
+    private CheckInType checkInType;
+
+    @ApiModelProperty(value = "性别", name = "sex")
+    private String sex;
+}

+ 77 - 0
src/main/java/com/izouma/ticketExchange/domain/Department.java

@@ -0,0 +1,77 @@
+package com.izouma.ticketExchange.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.izouma.ticketExchange.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+import org.hibernate.envers.Audited;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@ApiModel(value = "部门信息", description = "部门信息")
+public class Department implements Serializable {
+
+    @Id
+    private Long id;
+
+    @JsonIgnore
+    @CreatedBy
+    private String createdBy;
+
+    @JsonIgnore
+    @CreatedDate
+    private LocalDateTime createdAt;
+
+    @JsonIgnore
+    @LastModifiedBy
+    private String modifiedBy;
+
+    @JsonIgnore
+    @LastModifiedDate
+    private LocalDateTime modifiedAt;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "部门名称", name = "name")
+    private String name;
+
+    @Searchable
+    @ApiModelProperty(value = "父级Id", name = "parentid")
+    private Long parentid;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+
+    @OneToMany(fetch = FetchType.LAZY)
+    @JsonIgnore
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JoinColumn(name = "parentid", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
+    List<Department> children;
+
+}

+ 50 - 0
src/main/java/com/izouma/ticketExchange/domain/DepositRecord.java

@@ -0,0 +1,50 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.enums.PayMethod;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@ApiModel(value = "部门信息", description = "部门信息")
+public class DepositRecord extends BaseEntity {
+    @ApiModelProperty(value = "用户ID", name = "userId")
+    private Long userId;
+
+    @ApiModelProperty(value = "入住ID", name = "checkinInfoId")
+    private Long checkinInfoId;
+
+    @Column(precision = 10, scale = 2)
+    @ApiModelProperty(value = "金额", name = "amount")
+    private BigDecimal amount;
+
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty(value = "支付方式", name = "payMethod")
+    private PayMethod payMethod;
+
+    @ApiModelProperty(value = "第三方单号", name = "transactionId")
+    private String transactionId;
+
+    @ApiModelProperty(value = "退款单号", name = "refundId")
+    private String refundId;
+
+    @ApiModelProperty(value = "是否退回", name = "refunded")
+    private Boolean refunded;
+
+    @ApiModelProperty(value = "退款时间", name = "refundTime")
+    private LocalDateTime refundTime;
+}

+ 35 - 0
src/main/java/com/izouma/ticketExchange/domain/FeeType.java

@@ -0,0 +1,35 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.enums.FeeTypeClass;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.io.Serializable;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "费用类型", description = "费用类型")
+public class FeeType extends BaseEntity implements Serializable {
+
+
+    @ApiModelProperty(value = "分类", name = "feeTypeClass")
+    @Enumerated(EnumType.STRING)
+    private FeeTypeClass feeTypeClass;
+
+    @ApiModelProperty(value = "费用名称", name = "name")
+    private String name;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+}

+ 43 - 0
src/main/java/com/izouma/ticketExchange/domain/FloorInfo.java

@@ -0,0 +1,43 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import java.io.Serializable;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "楼层信息", description = "楼层信息")
+public class FloorInfo extends BaseEntity implements Serializable {
+
+    @ApiModelProperty(value = "门店Id", name = "storeId")
+    private Long storeId;
+
+    @ApiModelProperty(value = "楼栋Id", name = "buildingId")
+    private Long buildingId;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "名称", name = "name")
+    private String name;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+
+}

+ 35 - 0
src/main/java/com/izouma/ticketExchange/domain/Menu.java

@@ -0,0 +1,35 @@
+package com.izouma.ticketExchange.domain;
+
+import lombok.Data;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Entity
+@Where(clause = "active = 1")
+public class Menu extends BaseEntity implements Serializable {
+    private String name;
+
+    private String path;
+
+    private String icon;
+
+    private Integer sort;
+
+    private Long parent;
+
+    private Boolean root;
+
+    private Boolean enabled;
+
+    private Boolean active;
+
+    @OneToMany
+    @JoinColumn(name = "parent", insertable = false, updatable = false)
+    List<Menu> children;
+}

+ 57 - 0
src/main/java/com/izouma/ticketExchange/domain/PropertyCompany.java

@@ -0,0 +1,57 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.annotations.Searchable;
+import com.izouma.ticketExchange.enums.CooperationType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.io.Serializable;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "物业公司", description = "物业公司")
+public class PropertyCompany extends BaseEntity implements Serializable {
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "物业名称", name = "companyName")
+    private String companyName;
+
+    @Searchable
+    @ApiModelProperty(value = "城市", name = "city")
+    private String city;
+
+    @ApiModelProperty(value = "地址", name = "address")
+    private String address;
+
+    @ApiModelProperty(value = "负责人", name = "principal")
+    private String principal;
+
+    @ApiModelProperty(value = "联系电话", name = "telephone")
+    private String telephone;
+
+    @ApiModelProperty(value = "合作类型", name = "cooperationType")
+    @Enumerated(EnumType.STRING)
+    private CooperationType cooperationType;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+
+}

+ 46 - 0
src/main/java/com/izouma/ticketExchange/domain/RechargeRecord.java

@@ -0,0 +1,46 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.enums.PayMethod;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class RechargeRecord extends BaseEntity {
+
+    @ApiModelProperty(value = "门店ID", name = "storeId")
+    private Long storeId;
+
+    @ApiModelProperty(value = "房间ID", name = "roomId")
+    private Long roomId;
+
+    @ApiModelProperty(value = "用户ID", name = "userId")
+    private Long userId;
+
+    @Column(precision = 10, scale = 2)
+    @ApiModelProperty(value = "金额", name = "amount")
+    private BigDecimal amount;
+
+    @ApiModelProperty(value = "支付方式", name = "payMethod")
+    private PayMethod payMethod;
+
+    @ApiModelProperty(value = "支付时间", name = "payTime")
+    private LocalDateTime payTime;
+
+    @ApiModelProperty(value = "第三方单号", name = "transactionId")
+    private String transactionId;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+}

+ 51 - 0
src/main/java/com/izouma/ticketExchange/domain/RoomFee.java

@@ -0,0 +1,51 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.enums.FeeStatus;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "房间费用", description = "房间费用")
+public class RoomFee extends BaseEntity implements Serializable {
+
+    @ApiModelProperty(value = "房间Id", name = "roomId")
+    private Long roomId;
+
+    @ApiModelProperty(value = "费用类型Id", name = "feeTypeId")
+    private Long feeTypeId;
+
+    @ApiModelProperty(value = "费用类型", name = "feeType")
+    @ManyToOne
+    @JoinColumn(name = "feeTypeId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    private FeeType feeType;
+
+    @ApiModelProperty(value = "费用状态", name = "feeStatus")
+    @Enumerated(EnumType.STRING)
+    private FeeStatus feeStatus;
+
+    @ApiModelProperty(value = "费用金额", name = "money")
+    private BigDecimal money;
+
+    @ApiModelProperty(value = "缴费时间", name = "settleTime")
+    private LocalDateTime settleTime;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+}

+ 120 - 0
src/main/java/com/izouma/ticketExchange/domain/RoomInfo.java

@@ -0,0 +1,120 @@
+package com.izouma.ticketExchange.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.izouma.ticketExchange.annotations.Searchable;
+import com.izouma.ticketExchange.enums.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "房间信息", description = "房间信息")
+public class RoomInfo extends BaseEntity implements Serializable {
+
+    @ApiModelProperty(value = "门店Id", name = "storeId")
+    private Long storeId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "storeId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private StoreInfo storeInfo;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "房间名称", name = "roomName")
+    private String roomName;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "房间号码", name = "roomCode")
+    private String roomCode;
+
+    @ApiModelProperty(value = "房型Id", name = "roomTypeId")
+    private Long roomTypeId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "roomTypeId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private RoomTypeInfo roomTypeInfo;
+
+    @ApiModelProperty(value = "楼栋Id", name = "buildingId")
+    private Long buildingId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "buildingId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private BuildingInfo buildingInfo;
+
+    @ApiModelProperty(value = "楼层Id", name = "floorId")
+    private Long floorId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "floorId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JsonIgnore
+    private FloorInfo floorInfo;
+
+    @Searchable
+    @ApiModelProperty(value = "门卡", name = "doorCard")
+    private String doorCard;
+
+    @ApiModelProperty(value = "预定状态", name = "bookStatus")
+    @Enumerated(EnumType.STRING)
+    private BookStatus bookStatus;
+
+    @ApiModelProperty(value = "入住状态", name = "checkInStatus")
+    @Enumerated(EnumType.STRING)
+    private CheckInStatus checkInStatus;
+
+    @ApiModelProperty(value = "卫生状态", name = "cleaningStatus")
+    @Enumerated(EnumType.STRING)
+    private CleaningStatus cleaningStatus;
+
+    @ApiModelProperty(value = "维修状态", name = "repairStatus")
+    @Enumerated(EnumType.STRING)
+    private RepairStatus repairStatus;
+
+    @ApiModelProperty(value = "锁定状态", name = "lockStatus")
+    @Enumerated(EnumType.STRING)
+    private LockStatus lockStatus;
+
+    @ApiModelProperty(value = "联系电话", name = "telephone")
+    private String telephone;
+
+    @Column(precision = 10, scale = 2)
+    @ApiModelProperty(value = "余额", name = "balance")
+    private BigDecimal balance;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+
+    @OneToMany(fetch = FetchType.LAZY)
+    @JsonIgnore
+    @NotFound(action = NotFoundAction.IGNORE)
+    @JoinColumn(name = "roomId", insertable = false, updatable = false)
+    List<BedInfo> bedInfos;
+
+}

+ 73 - 0
src/main/java/com/izouma/ticketExchange/domain/RoomTypeInfo.java

@@ -0,0 +1,73 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "房型信息", description = "房型信息")
+public class RoomTypeInfo extends BaseEntity implements Serializable {
+
+    @ApiModelProperty(value = "门店Id", name = "storeId")
+    private Long storeId;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "房型名称", name = "typeName")
+    private String typeName;
+
+    @Searchable
+    @ApiModelProperty(value = "简称", name = "shortName")
+    private String shortName;
+
+    @Searchable
+    @ApiModelProperty(value = "英文名称", name = "enName")
+    private String enName;
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "简码", name = "typeCode")
+    private String typeCode;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "虚拟房型", name = "virtual")
+    private Boolean virtual = false;
+
+    @ApiModelProperty(value = "房间数量", name = "roomCount")
+    private Long roomCount;
+
+    @ApiModelProperty(value = "床位数量", name = "bedCount")
+    private Long bedCount;
+
+    @ApiModelProperty(value = "超定数量", name = "overCount")
+    private Long overCount;
+
+    @ApiModelProperty(value = "基础价格", name = "basePrice")
+    private BigDecimal basePrice;
+
+    @ApiModelProperty(value = "月租价格", name = "monthPrice")
+    private BigDecimal monthPrice;
+
+    @ApiModelProperty(value = "售卖方式", name = "sellMode")
+    private String sellMode;
+
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+}

+ 32 - 0
src/main/java/com/izouma/ticketExchange/domain/SmsRecord.java

@@ -0,0 +1,32 @@
+package com.izouma.ticketExchange.domain;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "短信验证码记录", description = "短信验证码记录")
+public class SmsRecord extends BaseEntity {
+    @ApiModelProperty(value = "会话ID", name = "sessionId")
+    private String        sessionId;
+    @ApiModelProperty(value = "手机号", name = "phone;")
+    private String        phone;
+    @ApiModelProperty(value = "验证码", name = "code")
+    private String        code;
+    @ApiModelProperty(value = "过期时间", name = "expiresAt")
+    private LocalDateTime expiresAt;
+    @ApiModelProperty(value = "是否过期", name = "expired")
+    private Boolean       expired;
+    @ApiModelProperty(value = "验证码用途", name = "scope")
+    private String        scope;
+}

+ 80 - 0
src/main/java/com/izouma/ticketExchange/domain/StoreInfo.java

@@ -0,0 +1,80 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.annotations.Searchable;
+import com.izouma.ticketExchange.enums.CooperationType;
+import com.izouma.ticketExchange.enums.StoreStatus;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "门店信息", description = "门店信息")
+public class StoreInfo extends BaseEntity implements Serializable {
+
+    @Column(nullable = false)
+    @Searchable
+    @ApiModelProperty(value = "门店名称", name = "storeName")
+    private String storeName;
+
+    @Searchable
+    @ApiModelProperty(value = "城市", name = "city")
+    private String city;
+
+    @ApiModelProperty(value = "物业公司", name = "city")
+    private Long propertyCompanyId;
+
+    @ApiModelProperty(value = "地址", name = "address")
+    private String address;
+
+    @ApiModelProperty(value = "开业时间", name = "openingTime")
+    private LocalDateTime openingTime;
+
+    @ApiModelProperty(value = "经营类型", name = "cooperationType")
+    @Enumerated(EnumType.STRING)
+    private CooperationType cooperationType;
+
+    @ApiModelProperty(value = "状态", name = "storeStatus")
+    @Enumerated(EnumType.STRING)
+    private StoreStatus storeStatus;
+
+    @ApiModelProperty(value = "负责人", name = "principal")
+    private String principal;
+
+    @ApiModelProperty(value = "联系电话", name = "telephone")
+    private String telephone;
+
+    @ApiModelProperty(value = "传真", name = "fax")
+    private String fax;
+
+    @ApiModelProperty(value = "邮编", name = "postalCode")
+    private String postalCode;
+
+    @ApiModelProperty(value = "简称", name = "shortName")
+    private String shortName;
+
+    @ApiModelProperty(value = "简码", name = "shortCode")
+    private String shortCode;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @Column(nullable = false)
+    @ApiModelProperty(value = "有效", name = "enabled")
+    private Boolean enabled = true;
+}

+ 29 - 0
src/main/java/com/izouma/ticketExchange/domain/Tenant.java

@@ -0,0 +1,29 @@
+package com.izouma.ticketExchange.domain;
+
+import com.izouma.ticketExchange.enums.DepositStatus;
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Data
+@Entity
+public class Tenant extends BaseEntity {
+    private Long userId;
+
+    private String idNumber;
+
+    private String name;
+
+    @Enumerated(EnumType.STRING)
+    private DepositStatus depositStatus;
+
+    private Long depositRecordId;
+
+    @OneToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "depositRecordId", insertable = false, updatable = false)
+    private DepositRecord depositRecord;
+
+    @OneToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "userId", insertable = false, updatable = false)
+    private User user;
+}

+ 112 - 0
src/main/java/com/izouma/ticketExchange/domain/User.java

@@ -0,0 +1,112 @@
+package com.izouma.ticketExchange.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.izouma.ticketExchange.annotations.Searchable;
+import com.izouma.ticketExchange.config.Constants;
+import com.izouma.ticketExchange.security.Authority;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.BatchSize;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.*;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "用户", description = "用户")
+public class User extends BaseEntity implements Serializable {
+
+    @Pattern(regexp = Constants.Regex.USERNAME)
+    @Size(min = 1, max = 50)
+    @Column(nullable = false, unique = true)
+    @Searchable
+    private String username;
+
+    @Searchable
+    private String nickname;
+
+    private String avatar;
+
+    @JsonIgnore
+    private String password;
+
+    @Column(nullable = false)
+    private Boolean enabled = true;
+
+    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.DETACH})
+    @JoinTable(
+            name = "user_authority",
+            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
+            inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")})
+    @BatchSize(size = 20)
+    @ExcelIgnore
+    private List<Authority> authorities = new ArrayList<>();
+
+    private String openId;
+
+    private String sex;
+
+    private String language;
+
+    private String city;
+
+    private String province;
+
+    private String country;
+
+    @Pattern(regexp = Constants.Regex.CHINESE)
+    private String realName;
+
+    @Pattern(regexp = Constants.Regex.ID_NO)
+    private String idNo;
+
+
+    @ApiModelProperty(value = "钉钉userid", name = "dingUserid")
+    private String dingUserid;
+
+    @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH})
+    @JoinTable(
+            name = "user_department",
+            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
+            inverseJoinColumns = {@JoinColumn(name = "department_id", referencedColumnName = "id")})
+    @BatchSize(size = 20)
+    @ExcelIgnore
+    @ApiModelProperty(value = "部门", name = "departments")
+    private Set<Department> departments = new HashSet<>();
+
+    @Searchable
+    private String phone;
+
+    private String position;
+
+    private String email;
+
+
+    @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH})
+    @JoinTable(
+            name = "user_store",
+            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
+            inverseJoinColumns = {@JoinColumn(name = "store_id", referencedColumnName = "id")})
+    @BatchSize(size = 20)
+    @ExcelIgnore
+    @ApiModelProperty(value = "店铺", name = "stores")
+    private Set<StoreInfo> stores = new HashSet<>();
+
+
+}

+ 55 - 0
src/main/java/com/izouma/ticketExchange/domain/client/DepositRefundApply.java

@@ -0,0 +1,55 @@
+package com.izouma.ticketExchange.domain.client;
+
+import com.izouma.ticketExchange.domain.BaseEntity;
+import com.izouma.ticketExchange.domain.CheckinInfo;
+import com.izouma.ticketExchange.domain.DepositRecord;
+import com.izouma.ticketExchange.enums.DepositRefundStatus;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "押金退款申请", description = "押金退款申请")
+public class DepositRefundApply extends BaseEntity {
+
+    @ApiModelProperty(value = "入住ID", name = "checkinInfoId")
+    private Long checkinInfoId;
+
+    @ApiModelProperty(value = "押金ID", name = "depositRecordId")
+    private Long depositRecordId;
+
+    @ApiModelProperty(value = "备注", name = "remark")
+    private String remark;
+
+    @ApiModelProperty(value = "状态", name = "status")
+    private DepositRefundStatus status;
+
+    private LocalDateTime auditTime;
+
+    private LocalDateTime refundTime;
+
+    @OneToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "checkinInfoId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    private CheckinInfo checkinInfo;
+
+    @OneToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "depositRecordId", insertable = false, updatable = false)
+    @NotFound(action = NotFoundAction.IGNORE)
+    private DepositRecord depositRecord;
+}

+ 56 - 0
src/main/java/com/izouma/ticketExchange/domain/gen/TestGenCode.java

@@ -0,0 +1,56 @@
+package com.izouma.ticketExchange.domain.gen;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.izouma.ticketExchange.annotations.Searchable;
+import com.izouma.ticketExchange.config.Constants;
+import com.izouma.ticketExchange.converter.StringArrayConverter;
+import com.izouma.ticketExchange.domain.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.Lob;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+public class TestGenCode extends BaseEntity implements Serializable {
+
+    @Pattern(regexp = Constants.Regex.USERNAME)
+    @Size(min = 1, max = 50)
+    @Column(nullable = false, unique = true)
+    @Searchable
+    private String username;
+
+    @Searchable
+    private String nickname;
+
+    @JsonIgnore
+    private String password;
+
+    @Column(nullable = false)
+    private Boolean enabled = true;
+
+    private String avatar;
+
+    private String testa;
+
+    @Lob
+    @Column(length = 100000)
+    @Convert(converter = StringArrayConverter.class)
+    private List<String> testb;
+
+    private String testc;
+}

+ 38 - 0
src/main/java/com/izouma/ticketExchange/domain/sale/CollectionAccount.java

@@ -0,0 +1,38 @@
+package com.izouma.ticketExchange.domain.sale;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * com.izouma.zhumj.domain.sale
+ *
+ * 应收款项
+ * @author Pine
+ * @email 771190883@qq.com
+ * @date 2019/10/16
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CollectionAccount implements Serializable {
+    /**
+     * 应收账款总额
+     */
+    private BigDecimal Account;
+    /**
+     * 销售员应收账款总额
+     */
+    private BigDecimal saleAccount;
+    /**
+     * 15天内应收款项
+     */
+    private BigDecimal fifteenAccount;
+    /**
+     * 30天内应收款项
+     */
+    private BigDecimal thirtyAccount;
+}

+ 185 - 0
src/main/java/com/izouma/ticketExchange/domain/sale/Contract.java

@@ -0,0 +1,185 @@
+package com.izouma.ticketExchange.domain.sale;
+import	java.math.BigDecimal;
+
+import com.izouma.ticketExchange.domain.BaseEntity;
+import com.izouma.ticketExchange.enums.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+import org.springframework.format.annotation.DateTimeFormat;
+
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.validation.constraints.NotEmpty;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 合同管理预约订单
+ * @Author: Pine
+ * @Date: 2019/10/9
+ * @Email:771190883@qq.com
+ */
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Where(clause = "enabled = 1")
+@ApiModel(value = "合同管理预约订单", description = "合同管理预约订单")
+public class Contract extends BaseEntity implements Serializable {
+
+    /**
+     * 合同编号
+     */
+    @ApiModelProperty(value = "合同编号", name = "contractNumber")
+    @NotEmpty(message = "合同编号不能为空")
+    private String contractNumber;
+    /**
+     * 公司全称
+     */
+    @ApiModelProperty(value = "公司全称", name = "coFullName")
+    private String coFullName;
+    /**
+     *  公司简称
+     */
+    @ApiModelProperty(value = "公司简称", name = "coSimpleName")
+    private String coSimpleName;
+    /**
+     * 房型
+     */
+    @ApiModelProperty(value = "房型", name = "roomType")
+    private String roomType;
+    /**
+     * 床位数
+     */
+    @ApiModelProperty(value = "床位数", name = "beds")
+    private Integer beds;
+    /**
+     * 单价
+     */
+    @ApiModelProperty(value = "单价", name = "price")
+    private BigDecimal price;
+    /**
+     * 押金
+     */
+    @ApiModelProperty(value = "押金", name = "deposit")
+    private BigDecimal deposit;
+    /**
+     * 月租金
+     */
+    @ApiModelProperty(value = "月租金", name = "monthlyRent")
+    private BigDecimal monthlyRent;
+    /**
+     * 合同总租金
+     */
+    @ApiModelProperty(value = "合同总租金", name = "contractTotalRent")
+    private BigDecimal contractTotalRent;
+    /**
+     * 合同开始时间
+     */
+    @ApiModelProperty(value = "合同开始时间", name = "contractBeginTime")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime contractBeginTime;
+    /**
+     * 合同结束时间
+     */
+    @ApiModelProperty(value = "合同结束时间", name = "contractEndTime")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime contractEndTime;
+    /**
+     * 合同期(天)
+     */
+    @ApiModelProperty(value = "合同期(天)", name = "contractDays")
+    private Integer contractDays;
+    /**
+     * 合同期(月)
+     */
+    @ApiModelProperty(value = "合同期(月)", name = "contractDays")
+    private Integer contractMonthly;
+    /**
+     *  付款方式
+     */
+    @ApiModelProperty(value = "付款方式", name = "payType")
+    private String payType;
+    /**
+     * 续约次数
+     */
+    @ApiModelProperty(value = "续约次数", name = "contractRenewals")
+    private Integer contractRenewals;
+    /**
+     * 销售员
+     */
+    @ApiModelProperty(value = "销售员", name = "saleName")
+    private String saleName;
+    /**
+     * 销售员ID
+     */
+    @ApiModelProperty(value = "销售员ID", name = "saleId")
+    private Long saleId;
+    /**
+     * 销售员部门id(预留)
+     */
+    @ApiModelProperty(value = "销售员部门id(预留)", name = "departmentId")
+    private Long departmentId;
+    /**
+     * 销售员部门名称(预留)
+     */
+    @ApiModelProperty(value = "销售员部门名称(预留)", name = "departmentName")
+    private String departmentName;
+    /**
+     * 客户来源
+     */
+    @ApiModelProperty(value = "客户来源", name = "customerSource")
+    @Enumerated(EnumType.STRING)
+    private CustomerSource customerSource;
+    /**
+     * 客户行业
+     */
+    @ApiModelProperty(value = "客户行业", name = "customerIndustry")
+    private String customerIndustry;
+    /**
+     * 联系人
+     */
+    @ApiModelProperty(value = "联系人", name = "contacts")
+    private String contacts;
+    /**
+     * 联系电话
+     */
+    @ApiModelProperty(value = "联系电话", name = "contactPhone")
+    private String contactPhone;
+    /**
+     * 联系地址
+     */
+    @ApiModelProperty(value = "联系地址", name = "contactAddress")
+    private String contactAddress;
+    /**
+     * 状态(1 在住 0 已退)
+     */
+    @ApiModelProperty(value = "状态(在住  已退)", name = "status")
+    @Enumerated(EnumType.STRING)
+    private ContractStatus status;
+    /**
+     * 合同状态
+     */
+    @ApiModelProperty(value = "合同数据更新状态(未开始 已更新)", name = "status")
+    private ContractDataUp contractStatus;
+
+    /**
+     * 合同付款状态
+     */
+    @ApiModelProperty(value = "合同付款状态", name = "contractPayStatus")
+    private String contractPayStatus;
+
+    @Column(nullable = false)
+    private Boolean enabled = true;
+
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов