chenbiao vor 3 Jahren
Ursprung
Commit
a92b3fe7ef
100 geänderte Dateien mit 6652 neuen und 0 gelöschten Zeilen
  1. 0 0
      README.md
  2. 24 0
      deploy/apiclient_cert.pem
  3. 28 0
      deploy/apiclient_key.pem
  4. BIN
      deploy/vars/apiclient_cert_sx.p12
  5. 8 0
      deploy/vars/dev.properties
  6. 8 0
      deploy/vars/prd.properties
  7. 74 0
      netflix-common/pom.xml
  8. 10 0
      netflix-common/src/main/java/com/cyksj/common/constant/WeChatTemplateConst.java
  9. 96 0
      netflix-common/src/main/java/com/cyksj/common/exception/BusinessRuntimeException.java
  10. 232 0
      netflix-common/src/main/java/com/cyksj/common/snowflake/Sequence.java
  11. 79 0
      netflix-common/src/main/java/com/cyksj/common/snowflake/SystemClock.java
  12. 50 0
      netflix-common/src/main/java/com/cyksj/common/task/BaseTaskBean.java
  13. 82 0
      netflix-common/src/main/java/com/cyksj/common/task/BaseTaskBeanDelayed.java
  14. 79 0
      netflix-common/src/main/java/com/cyksj/common/task/GlobalDelayQueueTask.java
  15. 116 0
      netflix-common/src/main/java/com/cyksj/common/task/GlobalThreadPoolTaskExecutor.java
  16. 793 0
      netflix-common/src/main/java/com/cyksj/common/util/Codec.java
  17. 118 0
      netflix-common/src/main/java/com/cyksj/common/util/IoKit.java
  18. 327 0
      netflix-common/src/main/java/com/cyksj/common/util/J11HttpC.java
  19. 226 0
      netflix-common/src/main/java/com/cyksj/common/util/Jsons.java
  20. 21 0
      netflix-common/src/main/java/com/cyksj/common/util/StreamUtil.java
  21. 396 0
      netflix-common/src/main/java/com/cyksj/common/util/StringUtil.java
  22. 137 0
      netflix-common/src/main/java/com/cyksj/common/util/Xmls.java
  23. 41 0
      netflix-common/src/main/java/com/cyksj/dto/RedisKey.java
  24. 66 0
      netflix-common/src/main/java/com/cyksj/dto/Result.java
  25. 71 0
      netflix-common/src/main/java/com/cyksj/enums/GatewayApiCode.java
  26. 111 0
      netflix-common/src/main/java/com/cyksj/enums/GatewayResponse.java
  27. 44 0
      netflix-common/src/main/java/com/cyksj/enums/WeChatAuthRedirectUrl.java
  28. 38 0
      netflix-dao/pom.xml
  29. 40 0
      netflix-dao/src/main/java/com/cyksj/MyMetaObjectHandler.java
  30. 37 0
      netflix-dao/src/main/java/com/cyksj/MybatisPlusConfig.java
  31. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/AccountMapper.java
  32. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonMapper.java
  33. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSkuMapper.java
  34. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSpecMapper.java
  35. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsMapper.java
  36. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java
  37. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/HomeGroupMapper.java
  38. 18 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  39. 19 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java
  40. 12 0
      netflix-dao/src/main/java/com/cyksj/mapper/WxAppMapper.java
  41. 12 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/AdminMapper.java
  42. 36 0
      netflix-dao/src/main/java/com/cyksj/model/BaseEntity.java
  43. 25 0
      netflix-dao/src/main/java/com/cyksj/model/dto/AccountJsTicket.java
  44. 21 0
      netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java
  45. 39 0
      netflix-dao/src/main/java/com/cyksj/model/dto/AuthToken.java
  46. 30 0
      netflix-dao/src/main/java/com/cyksj/model/dto/Authentication.java
  47. 55 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GzhOAuth2UserInfo.java
  48. 76 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GzhUnionidUserinfo.java
  49. 58 0
      netflix-dao/src/main/java/com/cyksj/model/dto/H5JsPayParams.java
  50. 68 0
      netflix-dao/src/main/java/com/cyksj/model/dto/H5PayParams.java
  51. 44 0
      netflix-dao/src/main/java/com/cyksj/model/dto/JsSdkTicket.java
  52. 141 0
      netflix-dao/src/main/java/com/cyksj/model/dto/UnifiedOrder.java
  53. 33 0
      netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java
  54. 32 0
      netflix-dao/src/main/java/com/cyksj/model/dto/WeChatAccessToken.java
  55. 33 0
      netflix-dao/src/main/java/com/cyksj/model/dto/WxMpTemplateData.java
  56. 83 0
      netflix-dao/src/main/java/com/cyksj/model/dto/WxMpTemplateMessage.java
  57. 42 0
      netflix-dao/src/main/java/com/cyksj/model/entity/Account.java
  58. 34 0
      netflix-dao/src/main/java/com/cyksj/model/entity/BaseEntity.java
  59. 56 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  60. 59 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java
  61. 36 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSpec.java
  62. 48 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java
  63. 73 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTrips.java
  64. 21 0
      netflix-dao/src/main/java/com/cyksj/model/entity/HomeGroup.java
  65. 78 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  66. 15 0
      netflix-dao/src/main/java/com/cyksj/model/entity/Platform.java
  67. 44 0
      netflix-dao/src/main/java/com/cyksj/model/entity/User.java
  68. 66 0
      netflix-dao/src/main/java/com/cyksj/model/entity/WxApp.java
  69. 51 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelOrderDonInfo.java
  70. 25 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelSheetAndData.java
  71. 31 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExportExcelError.java
  72. 24 0
      netflix-dao/src/main/java/com/cyksj/model/manage/dto/AdminInfo.java
  73. 63 0
      netflix-dao/src/main/java/com/cyksj/model/manage/entity/Admin.java
  74. 49 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java
  75. 26 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuSpec.java
  76. 28 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpecSingle.java
  77. 64 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java
  78. 56 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java
  79. 103 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java
  80. 60 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationView.java
  81. 52 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/HomeGroupView.java
  82. 48 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java
  83. 60 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java
  84. 29 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderAttach.java
  85. 48 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  86. 27 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonViews.java
  87. 51 0
      netflix-dao/src/main/java/com/cyksj/model/views/GroupsView.java
  88. 39 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  89. 20 0
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  90. 34 0
      netflix-service/pom.xml
  91. 44 0
      netflix-service/src/main/java/com/cyksj/config/BaseWeChatConfig.java
  92. 27 0
      netflix-service/src/main/java/com/cyksj/config/WeChatConfig.java
  93. 38 0
      netflix-service/src/main/java/com/cyksj/config/WeChatFactory.java
  94. 574 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  95. 23 0
      netflix-service/src/main/java/com/cyksj/service/authorization/AuthorizationService.java
  96. 58 0
      netflix-service/src/main/java/com/cyksj/service/authorization/impl/AuthorizationServiceImpl.java
  97. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/AdminService.java
  98. 16 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
  99. 15 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonService.java
  100. 16 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonSkuService.java

+ 0 - 0
README.md


+ 24 - 0
deploy/apiclient_cert.pem

@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID8DCCAtigAwIBAgIUdy4r1Cl1K8MXLTLt2DS6jcQv1jYwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjAxMjE3MDgyOTQwWhcNMjUxMjE2MDgyOTQwWjCBgTETMBEGA1UEAwwK
+MTUzNzU5ODE5MTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL
+DCTopb/lronluILlloTooYzlhaznm4rmhYjlloTln7rph5HkvJoxCzAJBgNVBAYM
+AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAJ+WaPpa69+oLASrY2rLbUqkj5Uz95NslwL0YBmSEaSiDImbK8hhbsVN
+PROpofQQ+6n7Lm/njL95kyHBY2Ghy5pQf5lmpBHiFMzUZMrkMEoXb9HSsbO7qdId
+4TyALSbvTqdAVlln+aOxgVb8bIfI6xKeUh7V8UQrGbqI+7RWhW9lNLE96+68ASzV
+EzMbYU8Wo+evhVPi/SNRDF/VQmkfUL0FGQVj1udki2MZyNNDqdEtIEEwxULs6voO
+b4Z3mBWyZKsGacPofjpjetGiQVzKMj6cLX29eNZSm4H+M9LxdR50Jpx6gLtKs7qw
+enS5ZInI7lJpRjU+AjHB79yisrECcqUCAwEAAaOBgTB/MAkGA1UdEwQCMAAwCwYD
+VR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0dHA6Ly9ldmNhLml0cnVzLmNv
+bS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1
+NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsFAAOCAQEADU4jbQvgN+4pykJU
+YOKBYL57y74TzD2XMbIO1J8s1FQRDCxFt67BftWzlG0qM66pQiL5QpNJ1TaItF+j
+Oucbz+/soOt2LzE9PSEFmx/WnYbWraI6h2j3zQzR+k8pxVaLVNrAQkpxEbVMEEnk
+56Df+ZBLks3yjan59gvQyA5qrzZcOOrzjnOeFOEVY+ahpBYdNKN6HlvvgOxlzFup
+UqNGJ0BBlfbT1jAAj6jJhzhktnPhIQqF+ORAmyMArfie7FJV6w0XuEdezwo+5iz0
+UDTvBWqmDbcyO9Hjv2X1wqUttGaAROHC2lzpUf0rHnz1qJay7Y54f+bD9CKnXVyl
+BvBLig==
+-----END CERTIFICATE-----

+ 28 - 0
deploy/apiclient_key.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCflmj6WuvfqCwE
+q2Nqy21KpI+VM/eTbJcC9GAZkhGkogyJmyvIYW7FTT0TqaH0EPup+y5v54y/eZMh
+wWNhocuaUH+ZZqQR4hTM1GTK5DBKF2/R0rGzu6nSHeE8gC0m706nQFZZZ/mjsYFW
+/GyHyOsSnlIe1fFEKxm6iPu0VoVvZTSxPevuvAEs1RMzG2FPFqPnr4VT4v0jUQxf
+1UJpH1C9BRkFY9bnZItjGcjTQ6nRLSBBMMVC7Or6Dm+Gd5gVsmSrBmnD6H46Y3rR
+okFcyjI+nC19vXjWUpuB/jPS8XUedCaceoC7SrO6sHp0uWSJyO5SaUY1PgIxwe/c
+orKxAnKlAgMBAAECggEAFughE2Z/mu/puZXcRFUE0AUE8xatf8TDfFIVhTYZQDde
+c1YJl86cdseab7sWmxDg/somJTvoUQejXeIDYN03e2P4nM1F2adI8wm9mf3dDJWG
+oGiMx061lophbSy8zmzlLk6m1lh9VcjB1vmOnoLxcw+0m+Z7phxFqifFcWJF7vIu
+52ST3KUJeq4f8l9FwwSXfbp/7swXVMKG2jA5vUiNIBUVt4WkWueZBrOxxRidRqv1
+U4PjsNS7ctvGbkIJ0nYNWjcz3rlzg5lIwNOkh+tP94OmPD6PuL2yY9KtgiXWESMi
+p5Ri1UA7g2H/pAww5V2xqV15UosNfd72P0Ni8nj3oQKBgQDSFMTCUzZ+yV4I4jQK
+4QCsGdXKwBBrQEP6CMIY8GbQpC9zYZI4kzncYsBAafObXAA8Ujk2zdg1twG0LMos
+W8GQ3NHvmmGQMtkjZvX978QrcW8S6zDWM0kdrhAKhjdO5Uadjrjm0h6/CHN5S9pT
+N8BuSqeMgv8bug96MKNHNxyLKQKBgQDCeD0YRCsFKI7V1ZeSBTG9SSgINdNUD69+
+d92GjlkF+Ldx+L5F14dnHyLY+EiQA8ToFZPW72wqX7oaWkpjP88Ibf07HCEP6MRg
+/jAhsVWaTgs6vfX7EsrsaRZR4VULVjyXGpKlbqBUEFRhadzIgiiHrP6/Rk4/dW0P
+shqE3tYXHQKBgQDLWKcLohhBqRCIcMwHK7vG2ksCsd4yskYaI5gdI7WhhwsXF/69
+HGUJWdzVfLj8TJU9zijrT1xUwgu4JxKa1UYLvnLHBhwhw9ZCWksJvaeYlXf6TAU9
+kO7Y9783MKsghvVPVPLNGd4A82Eyq6Vsn654E3MSo0njwLlygNnK+SF74QKBgBGB
+2Z4xpN3WBOXjUL3okc3EpEH49ol+0AHGsL7IWeNbvMgZ6KdI+/ugpfZ6g63TaQqr
+xp929nnqHEr7De9Zcz4DCOUlZySTg/pnZ9XgrSAzHnevWlG8I2CdJVFBw/I9VT8V
+OVaDWxO2VKJgcWvrq9JrFJQLtEeqPqNHGXQUy5lRAoGAXUPSyKnrp7OCkXB76pn4
+8ISAUVRxMMVuzhKnPg+mkpiGPuQ1JHUcRfU4+fMcuKgh1csfsno7J8EjBZ8P0uLK
+/g7lune97p9MWXopNNjeA4mesRvVUOrsgst0cJfAg9u2xEEZ9abmU7o3gKhQKhl5
+6xXUDzaDUgT8d38ytaComkQ=
+-----END PRIVATE KEY-----

BIN
deploy/vars/apiclient_cert_sx.p12


+ 8 - 0
deploy/vars/dev.properties

@@ -0,0 +1,8 @@
+activeProfile=dev
+
+#log4jdbc
+log4jdbc.jdbc.audit=WARN
+log4jdbc.jdbc.resultset=WARN
+log4jdbc.jdbc.sqlonly=WARN
+log4jdbc.jdbc.sqltiming=INFO
+log4jdbc.jdbc.connection=WARN

+ 8 - 0
deploy/vars/prd.properties

@@ -0,0 +1,8 @@
+activeProfile=prd
+
+#log4jdbc
+log4jdbc.jdbc.audit=WARN
+log4jdbc.jdbc.resultset=WARN
+log4jdbc.jdbc.sqlonly=WARN
+log4jdbc.jdbc.sqltiming=WARN
+log4jdbc.jdbc.connection=WARN

+ 74 - 0
netflix-common/pom.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>netflix</artifactId>
+        <groupId>com.netflix</groupId>
+        <version>1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>netflix-common</artifactId>
+
+    <name>netflix-common</name>
+    <description>有客来-common</description>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-xml</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!-- jce -->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.64</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.4.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 10 - 0
netflix-common/src/main/java/com/cyksj/common/constant/WeChatTemplateConst.java

@@ -0,0 +1,10 @@
+package com.cyksj.common.constant;
+
+/**
+ * @author chan
+ * @date 2022/10/9 10:47 AM
+ */
+public interface WeChatTemplateConst {
+
+    String EXPIRY_TEMPLATE = "g2_1-GzOU5RXj2IC9-ttmpSxd1FcDS_3fOe2w0MiH6Y";
+}

+ 96 - 0
netflix-common/src/main/java/com/cyksj/common/exception/BusinessRuntimeException.java

@@ -0,0 +1,96 @@
+package com.cyksj.common.exception;
+
+
+import com.cyksj.enums.GatewayApiCode;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @className BusinessRuntimeException
+ * @description 业务业务异常类
+ * @date 2020/11/4 4:34 下午
+ */
+@Getter
+@Setter
+public final class BusinessRuntimeException extends RuntimeException {
+
+    private static final long serialVersionUID = 4236266714060887509L;
+
+    public static final String ERR_DEF = "DEF001";
+
+    private String code;
+
+    private String msg;
+
+    /**
+     * 传入code 和Msg 构建BusinessException对象
+     *
+     * @param code
+     * @param msg
+     */
+    public BusinessRuntimeException(String code, String msg) {
+        super(msg);
+        this.code = code;
+    }
+
+    public BusinessRuntimeException(Integer code, String msg) {
+        super(msg);
+        this.code = code.toString();
+    }
+
+    public BusinessRuntimeException(String msg) {
+        super(msg);
+        this.code = GatewayApiCode.METADATA_SYSTEM_ERROR.getCode().toString();
+    }
+
+
+    /***
+     * 提供一个简便的构建BusinessException对象方法
+     *
+     * @param patterm
+     *            异常信息模板 如 xxxx {} xxxx
+     * @param args
+     *            传入模板所需要的参数
+     * @return
+     */
+    public static BusinessRuntimeException getInstance(String patterm, Object... args) {
+        String msg = java.text.MessageFormat.format(patterm, args);
+        return new BusinessRuntimeException(ERR_DEF, msg);
+    }
+
+    public static BusinessRuntimeException getInstance(String msg) {
+        return new BusinessRuntimeException(ERR_DEF, msg);
+    }
+
+    /***
+     * 提供一个简便的构建BusinessException带Exception的对象方法
+     *
+     * @param e
+     *            异常参数
+     * @param patterm
+     *            异常信息模板 如 xxxx {} xxxx
+     * @param args
+     *            传入模板所需要的参数
+     * @return
+     */
+    public static BusinessRuntimeException getInstance(Throwable e, String patterm, Object... args) {
+        String msg = java.text.MessageFormat.format(patterm, args);
+        return new BusinessRuntimeException(ERR_DEF, msg, e);
+    }
+
+
+
+    public BusinessRuntimeException(String code, String msg, Throwable e) {
+        super(msg, e);
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public BusinessRuntimeException(Throwable e, String msg) {
+        super(e);
+        this.msg = msg;
+    }
+
+
+}

+ 232 - 0
netflix-common/src/main/java/com/cyksj/common/snowflake/Sequence.java

@@ -0,0 +1,232 @@
+package com.cyksj.common.snowflake;
+
+import java.net.InetAddress;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * 基于Twitter的Snowflake算法实现分布式高效有序ID生产黑科技(sequence)——升级版Snowflake
+ *
+ * <br>
+ * SnowFlake的结构如下(每部分用-分开):<br>
+ * <br>
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
+ * <br>
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
+ * <br>
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下START_TIME属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
+ * <br>
+ * 10位的数据机器位,可以部署在1024个节点,包括5位dataCenterId和5位workerId<br>
+ * <br>
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
+ * <br>
+ * <br>
+ * 加起来刚好64位,为一个Long型。<br>
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ * <p>
+ * <p>
+ * 特性:
+ * 1.支持自定义允许时间回拨的范围<p>
+ * 2.解决跨毫秒起始值每次为0开始的情况(避免末尾必定为偶数,而不便于取余使用问题)<p>
+ * 3.解决高并发场景中获取时间戳性能问题<p>
+ * 4.支撑根据IP末尾数据作为workerId
+ * 5.时间回拨方案思考:1024个节点中分配10个点作为时间回拨序号(连续10次时间回拨的概率较小)
+ *
+ * @author lry
+ * @version 3.0
+ */
+public final class Sequence {
+
+    /**
+               * 起始时间戳
+     **/
+    private final static long START_TIME = 1519740777809L;
+
+    /**
+     * dataCenterId占用的位数:2
+     **/
+    private final static long DATA_CENTER_ID_BITS = 2L;
+    /**
+     * workerId占用的位数:8
+     **/
+    private final static long WORKER_ID_BITS = 8L;
+    /**
+               * 序列号占用的位数:12(表示只允许workId的范围为:0-4095)
+     **/
+    private final static long SEQUENCE_BITS = 12L;
+
+    /**
+     * workerId可以使用范围:0-255
+     **/
+    private final static long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
+    /**
+     * dataCenterId可以使用范围:0-3
+     **/
+    private final static long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
+
+    private final static long WORKER_ID_SHIFT = SEQUENCE_BITS;
+    private final static long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
+    private final static long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;
+
+    /**
+               * 用mask防止溢出:位与运算保证计算的结果范围始终是 0-4095
+     **/
+    private final static long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
+
+    private final long workerId;
+    private final long dataCenterId;
+    private long sequence = 0L;
+    private long lastTimestamp = -1L;
+
+    private static byte LAST_IP = 0;
+    private final boolean clock;
+    private final long timeOffset;
+    private final boolean randomSequence;
+    private final ThreadLocalRandom tlr = ThreadLocalRandom.current();
+
+    public Sequence(long dataCenterId) {
+        this(dataCenterId, 0x000000FF & getLastIpAddress(), false, 5L, false);
+    }
+
+    public Sequence(long dataCenterId, boolean clock, boolean randomSequence) {
+        this(dataCenterId, 0x000000FF & getLastIpAddress(), clock, 5L, randomSequence);
+    }
+
+    /**
+               * 基于Snowflake创建分布式ID生成器
+     *
+     * @param dataCenterId   数据中心ID,数据范围为0~3
+     * @param workerId       工作机器ID,数据范围为0~255
+     * @param clock          true表示解决高并发下获取时间戳的性能问题
+     * @param timeOffset     允许时间回拨的毫秒量,建议5ms
+     * @param randomSequence true表示使用毫秒内的随机序列(超过范围则取余)
+     */
+    public Sequence(long dataCenterId, long workerId, boolean clock, long timeOffset, boolean randomSequence) {
+        if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
+            throw new IllegalArgumentException("Data Center Id can't be greater than " + MAX_DATA_CENTER_ID + " or less than 0");
+        }
+        if (workerId > MAX_WORKER_ID || workerId < 0) {
+            throw new IllegalArgumentException("Worker Id can't be greater than " + MAX_WORKER_ID + " or less than 0");
+        }
+
+        this.workerId = workerId;
+        this.dataCenterId = dataCenterId;
+        this.clock = clock;
+        this.timeOffset = timeOffset;
+        this.randomSequence = randomSequence;
+    }
+
+    /**
+               * 获取ID
+     *
+     * @return long
+     */
+    public synchronized Long nextId() {
+        long currentTimestamp = this.timeGen();
+
+        // 闰秒:如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过,这个时候应当抛出异常
+        if (currentTimestamp < lastTimestamp) {
+            // 校验时间偏移回拨量
+            long offset = lastTimestamp - currentTimestamp;
+            if (offset > timeOffset) {
+                throw new RuntimeException("Clock moved backwards, refusing to generate id for [" + offset + "ms]");
+            }
+
+            try {
+                // 时间回退timeOffset毫秒内,则允许等待2倍的偏移量后重新获取,解决小范围的时间回拨问题
+                this.wait(offset << 1);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            // 再次获取
+            currentTimestamp = this.timeGen();
+            // 再次校验
+            if (currentTimestamp < lastTimestamp) {
+                throw new RuntimeException("Clock moved backwards, refusing to generate id for [" + offset + "ms]");
+            }
+        }
+
+        // 同一毫秒内序列直接自增
+        if (lastTimestamp == currentTimestamp) {
+            // randomSequence为true表示随机生成允许范围内的序列起始值并取余数,否则毫秒内起始值为0L开始自增
+            long tempSequence = sequence + 1;
+            if (randomSequence && tempSequence > SEQUENCE_MASK) {
+                tempSequence = tempSequence % SEQUENCE_MASK;
+            }
+
+            // 通过位与运算保证计算的结果范围始终是 0-4095
+            sequence = tempSequence & SEQUENCE_MASK;
+            if (sequence == 0) {
+                currentTimestamp = this.tilNextMillis(lastTimestamp);
+            }
+        } else {
+            // randomSequence为true表示随机生成允许范围内的序列起始值,否则毫秒内起始值为0L开始自增
+            sequence = randomSequence ? tlr.nextLong(SEQUENCE_MASK + 1) : 0L;
+        }
+
+        lastTimestamp = currentTimestamp;
+        long currentOffsetTime = currentTimestamp - START_TIME;
+
+        /*
+         * 1.左移运算是为了将数值移动到对应的段(41、5、5,12那段因为本来就在最右,因此不用左移)
+         * 2.然后对每个左移后的值(la、lb、lc、sequence)做位或运算,是为了把各个短的数据合并起来,合并成一个二进制数
+         * 3.最后转换成10进制,就是最终生成的id
+         */
+        return (currentOffsetTime << TIMESTAMP_LEFT_SHIFT) |
+                // 数据中心位
+                (dataCenterId << DATA_CENTER_ID_SHIFT) |
+                // 工作ID位
+                (workerId << WORKER_ID_SHIFT) |
+                // 毫秒序列化位
+                sequence;
+    }
+
+    /**
+               * 保证返回的毫秒数在参数之后(阻塞到下一个毫秒,直到获得新的时间戳)——CAS
+     *
+     * @param lastTimestamp last timestamp
+     * @return next millis
+     */
+    private long tilNextMillis(long lastTimestamp) {
+        long timestamp = this.timeGen();
+        while (timestamp <= lastTimestamp) {
+            // 如果发现时间回拨,则自动重新获取(可能会处于无限循环中)
+            timestamp = this.timeGen();
+        }
+
+        return timestamp;
+    }
+
+    /**
+               * 获得系统当前毫秒时间戳
+     *
+     * @return timestamp 毫秒时间戳
+     */
+    private long timeGen() {
+        return clock ? SystemClock.INSTANCE.currentTimeMillis() : System.currentTimeMillis();
+    }
+
+    /**
+               * 用IP地址最后几个字节标示
+     * <p>
+     * eg:192.168.1.30->30
+     *
+     * @return last IP
+     */
+    public static byte getLastIpAddress() {
+        if (LAST_IP != 0) {
+            return LAST_IP;
+        }
+
+        try {
+            InetAddress inetAddress = InetAddress.getLocalHost();
+            byte[] addressByte = inetAddress.getAddress();
+            LAST_IP = addressByte[addressByte.length - 1];
+        } catch (Exception e) {
+            throw new RuntimeException("Unknown Host Exception", e);
+        }
+
+        return LAST_IP;
+    }
+
+}

+ 79 - 0
netflix-common/src/main/java/com/cyksj/common/snowflake/SystemClock.java

@@ -0,0 +1,79 @@
+package com.cyksj.common.snowflake;
+
+
+import java.sql.Timestamp;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * System Clock
+ * <p>
+ * 利用ScheduledExecutorService实现高并发场景下System.curentTimeMillis()的性能问题的优化.
+ *
+ * @author lry
+ */
+public enum SystemClock {
+
+    // ====
+
+    INSTANCE(1);
+
+    private final long period;
+    private final AtomicLong nowTime;
+    private boolean started = false;
+    private ScheduledExecutorService executorService;
+
+    SystemClock(long period) {
+        this.period = period;
+        this.nowTime = new AtomicLong(System.currentTimeMillis());
+    }
+
+    /**
+     * The initialize scheduled executor service
+     */
+    public void initialize() {
+        if (started) {
+            return;
+        }
+
+        this.executorService = new ScheduledThreadPoolExecutor(1, r -> {
+            Thread thread = new Thread(r, "system-clock");
+            thread.setDaemon(true);
+            return thread;
+        });
+        executorService.scheduleAtFixedRate(() -> nowTime.set(System.currentTimeMillis()),
+                this.period, this.period, TimeUnit.MILLISECONDS);
+        Runtime.getRuntime().addShutdownHook(new Thread(this::destroy));
+        started = true;
+    }
+
+    /**
+     * The get current time milliseconds
+     *
+     * @return long time
+     */
+    public long currentTimeMillis() {
+        return started ? nowTime.get() : System.currentTimeMillis();
+    }
+
+    /**
+     * The get string current time
+     *
+     * @return string time
+     */
+    public String currentTime() {
+        return new Timestamp(currentTimeMillis()).toString();
+    }
+
+    /**
+     * The destroy of executor service
+     */
+    public void destroy() {
+        if (executorService != null) {
+            executorService.shutdown();
+        }
+    }
+
+}

+ 50 - 0
netflix-common/src/main/java/com/cyksj/common/task/BaseTaskBean.java

@@ -0,0 +1,50 @@
+package com.cyksj.common.task;
+
+/**
+ * @author chan
+ * @className BaseTaskBean
+ * @description 任务列表
+ * @date 2020-05-21 16:35
+ */
+public abstract class BaseTaskBean implements Runnable {
+
+	/**
+	 * 任务Id
+	 * **/
+	private String taskId;
+
+	/**
+	 * 任务名称
+	 * **/
+	private String taskName;
+
+	/**
+	 * 执行任务
+	 * **/
+	private Runnable task;
+	
+	public String getTaskId() {
+		return taskId;
+	}
+
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+
+	public String getTaskName() {
+		return taskName;
+	}
+
+	public void setTaskName(String taskName) {
+		this.taskName = taskName;
+	}
+
+	public Runnable getTask() {
+		return task;
+	}
+
+	public void setTask(Runnable task) {
+		this.task = task;
+	}
+
+}

+ 82 - 0
netflix-common/src/main/java/com/cyksj/common/task/BaseTaskBeanDelayed.java

@@ -0,0 +1,82 @@
+package com.cyksj.common.task;
+
+import java.util.concurrent.Delayed;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author chan
+ * @className BaseTaskBeanDelayed
+ * @description 延时队列
+ * @date 2020-05-21 16:35
+ */
+public abstract class BaseTaskBeanDelayed implements Delayed, Runnable {
+
+	/**
+	 * 任务Id
+	 **/
+	private String taskId;
+
+	/**
+	 * 任务名称
+	 **/
+	private String taskName;
+
+	/**
+	 * 延迟时间
+	 **/
+	private long expire;
+
+	/**
+	 * 任务
+	 **/
+	private Runnable task;
+
+	/**
+	 * 优先队列里面优先级规则 TimeUnit .MILLISECONDS 获取单位 为毫秒的时间戳
+	 **/
+	@Override
+	public int compareTo(Delayed o) {
+		return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
+	}
+
+	/**
+	 * 剩余时间=到期时间-当前时间 convert: 将给定单元的时间段转换到此单元。
+	 **/
+	@Override
+	public long getDelay(TimeUnit unit) {
+		return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
+	}
+
+	public String getTaskId() {
+		return taskId;
+	}
+
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+
+	public String getTaskName() {
+		return taskName;
+	}
+
+	public void setTaskName(String taskName) {
+		this.taskName = taskName;
+	}
+
+	public Runnable getTask() {
+		return task;
+	}
+
+	public void setTask(Runnable task) {
+		this.task = task;
+	}
+
+	public long getExpire() {
+		return expire;
+	}
+
+	public void setExpire(long expire) {
+		this.expire = expire;
+	}
+
+}

+ 79 - 0
netflix-common/src/main/java/com/cyksj/common/task/GlobalDelayQueueTask.java

@@ -0,0 +1,79 @@
+package com.cyksj.common.task;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean;
+import org.springframework.scheduling.concurrent.ScheduledExecutorTask;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.DelayQueue;
+
+/**
+ * @author chan
+ * @className GlobalDelayQueueTask
+ * @description 全局延时队列异步处理
+ * @date 2020-05-21 16:35
+ */
+@Component
+@Slf4j
+public final class GlobalDelayQueueTask {
+
+	private GlobalDelayQueueTask() {
+	}
+
+	private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors();
+	
+	private static final GlobalDelayQueueTask INSTANCE = new GlobalDelayQueueTask();
+
+	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
+	
+	private static final DelayQueue<BaseTaskBeanDelayed> DELAY_QUEUE = new DelayQueue<BaseTaskBeanDelayed>();
+
+	private static final ScheduledExecutorFactoryBean SCHEDULED_FACTORY = new ScheduledExecutorFactoryBean();
+
+	static {
+		log.info("GlobalDelayQueueTask 线程池创建[start]");
+		ScheduledExecutorTask task = new ScheduledExecutorTask();
+		task.setDelay(0);
+		task.setFixedRate(false);
+		task.setPeriod(1000 * 15);
+		task.setRunnable(new Runnable() {
+			@Override
+			public void run() {
+				BaseTaskBeanDelayed taskBean = null;
+				do {
+					taskBean = DELAY_QUEUE.poll();
+					if (taskBean != null) {
+						TASK_POOL.execute(taskBean);
+					}
+				} while (taskBean != null);
+			}
+		});
+
+		SCHEDULED_FACTORY.setScheduledExecutorTasks(task);
+		// 调度遇到异常后,调度计划继续执行.
+		SCHEDULED_FACTORY.setContinueScheduledExecutionAfterException(true);
+		SCHEDULED_FACTORY.setThreadNamePrefix("YICANG_TASK_DELAY");
+		SCHEDULED_FACTORY.setPoolSize(CORE_SIZE);
+		SCHEDULED_FACTORY.initialize();
+		log.info("GlobalDelayQueueTask 线程池创建[end]");
+	}
+	/**
+	 * @author chan 获取单例对象
+	 * **/
+	public static GlobalDelayQueueTask getInstance() {
+		return INSTANCE;
+	}
+	
+	/**
+	 * @author chan 覆盖任务执行
+	 * **/
+	public void compareAndSet(BaseTaskBeanDelayed taskBean) {
+		if (DELAY_QUEUE.contains(taskBean)) {
+			DELAY_QUEUE.remove(taskBean);
+			DELAY_QUEUE.add(taskBean);
+		} else {
+			DELAY_QUEUE.add(taskBean);
+		}
+	}
+
+}

+ 116 - 0
netflix-common/src/main/java/com/cyksj/common/task/GlobalThreadPoolTaskExecutor.java

@@ -0,0 +1,116 @@
+package com.cyksj.common.task;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @author chan
+ * @className GlobalThreadPoolTaskExecutor
+ * @description 全局任务异步处理
+ * @date 2020-05-21 16:35
+ */
+@Component
+public final class GlobalThreadPoolTaskExecutor {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(GlobalThreadPoolTaskExecutor.class);
+	
+	private GlobalThreadPoolTaskExecutor() {
+	}
+
+	private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors();
+
+	private static final ThreadPoolTaskExecutor POOLTASKEXECUTOR = new ThreadPoolTaskExecutor();
+
+	static {
+		// 队列深度.
+		POOLTASKEXECUTOR.setQueueCapacity(Integer.MAX_VALUE);
+		// 核心线程数.
+		POOLTASKEXECUTOR.setCorePoolSize(CORE_SIZE * 4);
+		// 最大线程数.
+		POOLTASKEXECUTOR.setMaxPoolSize(CORE_SIZE * 4);
+		// 线程名前缀.
+		POOLTASKEXECUTOR.setThreadNamePrefix("DISPATCH_TASK_");
+		// discard
+		POOLTASKEXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
+
+		POOLTASKEXECUTOR.initialize();
+		POOLTASKEXECUTOR.getThreadPoolExecutor().prestartAllCoreThreads();
+		
+		LOGGER.info("线程池启动成功,CPU数: " + CORE_SIZE + ", 核心线程数: " + CORE_SIZE * 4);
+	}
+
+	private static final GlobalThreadPoolTaskExecutor INSTANCE = new GlobalThreadPoolTaskExecutor();
+
+	/**
+	 * 获取单例线程池对象
+	 * 
+	 * @author chan
+	 * @return 单例对象
+	 **/
+	public static GlobalThreadPoolTaskExecutor getInstance() {
+		return INSTANCE;
+	}
+
+	/**
+	 * 提交异步任务
+	 * 
+	 * @author chan
+	 * @param taskBean 任务
+	 * @return void
+	 **/
+	public void execute(BaseTaskBean taskBean) {
+		POOLTASKEXECUTOR.execute(taskBean);
+	}
+
+	/**
+	 * 提交延迟异步任务
+	 * 
+	 * @author chan
+	 * @param taskBean 任务
+	 * @return void
+	 **/
+	public void execute(BaseTaskBeanDelayed taskBean) {
+		POOLTASKEXECUTOR.execute(taskBean);
+	}
+
+	/**
+	 * 提交异步任务
+	 * 
+	 * @author chan
+	 * @param runTask 任务
+	 * @return void
+	 **/
+	public void execute(Runnable runTask) {
+		POOLTASKEXECUTOR.execute(runTask);
+	}
+
+	/**
+	 * 提交异步任务
+	 * 
+	 * @author chan
+	 * @param runTask 任务
+	 * @return 返回异步任务执行结果
+	 **/
+	public <T> Future<T> submit(Callable<T> runTask) {
+		return POOLTASKEXECUTOR.submit(runTask);
+	}
+
+	/**
+	 * 提交异步任务
+	 * 
+	 * @author chan
+	 * @param runTask 任务
+	 * @return 返回异步任务执行结果
+	 **/
+	public ListenableFuture<?> submitListenable(Callable<?> runTask) {
+		ListenableFuture<?> futrue = POOLTASKEXECUTOR.submitListenable(runTask);
+		return futrue;
+	}
+}

+ 793 - 0
netflix-common/src/main/java/com/cyksj/common/util/Codec.java

@@ -0,0 +1,793 @@
+package com.cyksj.common.util;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.InputStream;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+/**
+ * @author valor.
+ * @date 2019/9/20 16:47
+ */
+public class Codec {
+
+    private Codec() { }
+
+    // Base64
+    // Cipher
+    // Hmac
+    // Signature
+    // MessageDigest
+
+    public static class Hexs {
+
+        private Hexs() { }
+
+        /**
+         * Used to build output as Hex
+         */
+        private static final char[] DIGITS =
+                { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+        public static String encodeToString(final byte[] data) {
+            return new String(encode(data));
+        }
+
+        private static char[] encode(final byte[] data) {
+            final int l = data.length;
+            final char[] out = new char[l << 1];
+            // two characters form the hex value.
+            for (int i = 0, j = 0; i < l; i++) {
+                out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
+                out[j++] = DIGITS[0x0F & data[i]];
+            }
+            return out;
+        }
+
+        public static byte[] decode(final char[] data) {
+            final int len = data.length;
+            if ((len & 0x01) != 0) {
+                throw new RuntimeException("Odd number of characters.");
+            }
+
+            final byte[] out = new byte[len >> 1];
+            // two characters form the hex value.
+            for (int i = 0, j = 0; j < len; i++) {
+                int f = toDigit(data[j], j) << 4;
+                j++;
+                f = f | toDigit(data[j], j);
+                j++;
+                out[i] = (byte) (f & 0xFF);
+            }
+            return out;
+        }
+
+        private static int toDigit(final char ch, final int index) {
+            final int digit = Character.digit(ch, 16);
+            if (digit == -1) {
+                throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index);
+            }
+            return digit;
+        }
+    }
+
+    /**
+     * package {@link Base64}
+     */
+    private static class Base64s {
+
+        private Base64s() { }
+
+        /* ----- encode ----- */
+        private static byte[] encode(byte[] var) {
+            return Base64.getEncoder().encode(var);
+        }
+
+        /* ----- decode ----- */
+        private static byte[] decode(byte[] var) {
+            return Base64.getDecoder().decode(var);
+        }
+    }
+
+    /**
+     * package {@link Cipher}
+     */
+    private static class Ciphers {
+
+        private Ciphers() { }
+
+        /**
+         * Cipher算法
+         *
+         * @param mode    模式 加密/解密
+         * @param trans   算法填充
+         * @param content 待加密/解密的byte[]
+         * @param keyByte 加密/解密密钥
+         * @param ivByte  算法向量 (AES CBC类型 需要填充iv偏移量)
+         * @return 输出的byte[]
+         * @throws Exception 抛出异常
+         */
+        private static byte[] doCipher(int mode, DoCipher.Trans trans, byte[] content, byte[] keyByte, byte[] ivByte) throws Exception {
+            String algorithm = trans.getTransformation();
+
+            Cipher cipher = Cipher.getInstance(algorithm);
+            Key sKeySpec = new SecretKeySpec(keyByte, algorithm);
+
+            if (null != ivByte && 0 != ivByte.length) {
+                // AES CBC类型 需要填充iv偏移量
+                AlgorithmParameterSpec iv = new IvParameterSpec(ivByte);
+                cipher.init(mode, sKeySpec, iv);
+            } else {
+                cipher.init(mode, sKeySpec);
+            }
+            return cipher.doFinal(content);
+        }
+    }
+
+    /**
+     * package {@link Mac}
+     */
+    private static class Hmacs {
+
+        private Hmacs() { }
+
+        private static byte[] doHmac(DoHmac.Algorithm algorithm, byte[] content, byte[] keyByte) throws Exception {
+            String hmacAlgorithm = algorithm.getValue();
+
+            Mac mac = Mac.getInstance(hmacAlgorithm);
+            Key sKeySpec = new SecretKeySpec(keyByte, hmacAlgorithm);
+            mac.init(sKeySpec);
+
+            return mac.doFinal(content);
+        }
+    }
+
+    /**
+     * package {@link Signature}
+     */
+    private static class Signatures {
+
+        private Signatures() { }
+
+        private static byte[] sign(DoSign.SignAlgorithm algorithm, byte[] content, PrivateKey privateKey) throws Exception {
+            Signature signature = Signature.getInstance(algorithm.getValue());
+            signature.initSign(privateKey);
+            signature.update(content);
+            return signature.sign();
+        }
+
+        private static boolean check(DoSign.SignAlgorithm algorithm, byte[] content, byte[] sign, PublicKey publicKey) throws Exception {
+            Signature signature = Signature.getInstance(algorithm.getValue());
+            signature.initVerify(publicKey);
+            signature.update(content);
+            return signature.verify(sign);
+        }
+
+        private static PublicKey getPublicKeyFromX509(DoSign.KeyAlgorithm algorithm, byte[] publicKeyBytes) throws Exception {
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm.getValue());
+            byte[] key = Base64s.decode(publicKeyBytes);
+            return keyFactory.generatePublic(new X509EncodedKeySpec(key));
+        }
+
+        private static PrivateKey getPrivateKeyFromPKCS8(DoSign.KeyAlgorithm algorithm, byte[] privateKeyBytes) throws Exception {
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm.getValue());
+            byte[] key = Base64s.decode(privateKeyBytes);
+            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(key));
+        }
+    }
+
+    private static class Digests {
+
+        private Digests() { }
+
+        private static byte[] doDigest(DoDigest.Algorithm algorithm, byte[] content) throws Exception {
+            MessageDigest digest = MessageDigest.getInstance(algorithm.getValue());
+            return digest.digest(content);
+        }
+
+        private static byte[] doDigest(DoDigest.Algorithm algorithm, InputStream in) throws Exception {
+            MessageDigest digest = MessageDigest.getInstance(algorithm.getValue());
+
+            byte[] buffer = new byte[1024];
+            int offset;
+            while (true) {
+                offset = in.read(buffer);
+                if (offset < 0) {
+                    break;
+                }
+                digest.update(buffer, 0, offset);
+            }
+
+            // close
+            IoKit.close(in);
+            return digest.digest();
+        }
+    }
+
+    public static class DoDigest {
+
+        public enum Algorithm {
+            MD2("MD2"),
+            MD5("MD5"),
+            SHA1("SHA-1"),
+            SHA224("SHA-224"),
+            SHA256("SHA-256"),
+            SHA384("SHA-384"),
+            SHA512("SHA-512"),
+            SHA3224("SHA3-224"),
+            SHA3256("SHA3-256"),
+            SHA3384("SHA3-384"),
+            SHA3512("SHA3-512");
+
+            private String value;
+
+            Algorithm(String algorithm) {
+                this.value = algorithm;
+            }
+
+            public String getValue() {
+                return this.value;
+            }
+        }
+
+        private Algorithm algorithm;
+        private byte[] data;
+
+        private DoDigest() { }
+
+        public static DoDigest custom() {
+            return new DoDigest();
+        }
+
+        public DoDigest setAlgorithm(Algorithm algorithm) {
+            this.algorithm = algorithm;
+            return this;
+        }
+
+        public DoDigest setData(byte[] data) {
+            this.data = data;
+            return this;
+        }
+
+        public DoDigest setBase64Data(String data, IoKit.Charsets charset) {
+            this.data = DoBase64.custom().setData(data, charset).decode();
+            return this;
+        }
+
+        public DoDigest setBase64Data(String data) {
+            return this.setBase64Data(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoDigest setStringData(String data, IoKit.Charsets charset) {
+            this.data = data.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoDigest setStringData(String data) {
+            return this.setStringData(data, IoKit.Charsets.UTF_8);
+        }
+
+        public byte[] toBytes() throws Exception {
+            return Digests.doDigest(this.algorithm, this.data);
+        }
+
+        public String toHexString() throws Exception {
+            return Hexs.encodeToString(this.toBytes());
+        }
+
+        public String toBase64String(IoKit.Charsets charset) throws Exception {
+            return DoBase64.custom().setData(this.toBytes()).encodeAsText(charset);
+        }
+
+        public String toBase64String() throws Exception {
+            return this.toBase64String(IoKit.Charsets.UTF_8);
+        }
+
+        public String toText(IoKit.Charsets charset) throws Exception {
+            return new String(this.toBytes(), charset.getCharset());
+        }
+
+        public String toText() throws Exception {
+            return this.toText(IoKit.Charsets.UTF_8);
+        }
+    }
+
+    public static class DoSign {
+
+        public enum KeyAlgorithm {
+            RSA("RSA"),
+            DSA("DSA"),
+            EC("EC");
+
+            private String value;
+
+            KeyAlgorithm(String algorithm) {
+                this.value = algorithm;
+            }
+
+            public String getValue() {
+                return this.value;
+            }
+        }
+
+        public enum SignAlgorithm {
+            NONEwithRSA("NONEwithRSA"),
+            MD2withRSA("MD2withRSA"),
+            MD5withRSA("MD5withRSA"),
+            SHA1withRSA("SHA1withRSA"),
+            SHA224withRSA("SHA224withRSA"),
+            SHA256withRSA("SHA256withRSA"),
+            SHA384withRSA("SHA384withRSA"),
+            SHA512withRSA("SHA512withRSA"),
+
+            NONEwithDSA("NONEwithDSA"),
+            SHA1withDSA("SHA1withDSA"),
+            SHA224withDSA("SHA224withDSA"),
+            SHA256withDSA("SHA256withDSA"),
+
+            NONEwithECDSA("NONEwithECDSA"),
+            SHA1withECDSA("SHA1withECDSA"),
+            SHA224withECDSA("SHA224withECDSA"),
+            SHA256withECDSA("SHA256withECDSA"),
+            SHA384withECDSA("SHA384withECDSA"),
+            SHA512withECDSA("SHA512withECDSA");
+
+            private String value;
+
+            SignAlgorithm(String algorithm) {
+                this.value = algorithm;
+            }
+
+            public String getValue() {
+                return this.value;
+            }
+        }
+
+        private KeyAlgorithm keyAlgorithm;
+        private SignAlgorithm signAlgorithm;
+        private byte[] data;
+        private byte[] key;
+        private byte[] signature;
+
+        private DoSign() { }
+
+        public static DoSign custom() {
+            return new DoSign();
+        }
+
+        public DoSign setKeyAlgorithm(KeyAlgorithm keyAlgorithm) {
+            this.keyAlgorithm = keyAlgorithm;
+            return this;
+        }
+
+        public DoSign setSignAlgorithm(SignAlgorithm signAlgorithm) {
+            this.signAlgorithm = signAlgorithm;
+            return this;
+        }
+
+        public DoSign setData(byte[] data) {
+            this.data = data;
+            return this;
+        }
+
+        public DoSign setBase64Data(String data, IoKit.Charsets charset) {
+            this.data = DoBase64.custom().setData(data, charset).decode();
+            return this;
+        }
+
+        public DoSign setBase64Data(String data) {
+            return this.setBase64Data(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoSign setStringData(String data, IoKit.Charsets charset) {
+            this.data = data.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoSign setStringData(String data) {
+            return this.setStringData(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoSign setKey(byte[] key) {
+            this.key = key;
+            return this;
+        }
+
+        public DoSign setBase64Key(String key, IoKit.Charsets charset) {
+            this.key = DoBase64.custom().setData(key, charset).decode();
+            return this;
+        }
+
+        public DoSign setBase64Key(String key) {
+            return this.setBase64Key(key, IoKit.Charsets.UTF_8);
+        }
+
+        public DoSign setStringKey(String key, IoKit.Charsets charset) {
+            this.key = key.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoSign setStringKey(String key) {
+            return this.setStringKey(key, IoKit.Charsets.UTF_8);
+        }
+
+        public DoSign setSignature(byte[] signature) {
+            this.signature = signature;
+            return this;
+        }
+
+        public DoSign setBase64Signature(String signature, IoKit.Charsets charset) {
+            this.signature = DoBase64.custom().setData(signature, charset).decode();
+            return this;
+        }
+
+        public DoSign setBase64Signature(String signature) {
+            return this.setBase64Signature(signature, IoKit.Charsets.UTF_8);
+        }
+
+        public DoSign setStringSignature(String signature, IoKit.Charsets charset) {
+            this.signature = signature.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoSign setStringSignature(String signature) {
+            return this.setStringSignature(signature, IoKit.Charsets.UTF_8);
+        }
+
+        public byte[] sign() throws Exception {
+            PrivateKey privateKey = Signatures.getPrivateKeyFromPKCS8(this.keyAlgorithm, this.key);
+            return Signatures.sign(this.signAlgorithm, this.data, privateKey);
+        }
+
+        public String toHexString() throws Exception {
+            return Hexs.encodeToString(this.sign());
+        }
+
+        public String toBase64String(IoKit.Charsets charset) throws Exception {
+            return DoBase64.custom().setData(this.sign()).encodeAsText(charset);
+        }
+
+        public String toBase64String() throws Exception {
+            return this.toBase64String(IoKit.Charsets.UTF_8);
+        }
+
+        public String toText(IoKit.Charsets charset) throws Exception {
+            return new String(this.sign(), charset.getCharset());
+        }
+
+        public String toText() throws Exception {
+            return this.toText(IoKit.Charsets.UTF_8);
+        }
+
+        public boolean check() throws Exception {
+            PublicKey publicKey = Signatures.getPublicKeyFromX509(this.keyAlgorithm, this.key);
+            return Signatures.check(this.signAlgorithm, this.data, this.signature, publicKey);
+        }
+    }
+
+    public static class DoHmac {
+
+        public enum Algorithm {
+            HmacMD5("HmacMD5"),
+            HmacSHA1("HmacSHA1"),
+            HmacSHA224("HmacSHA224"),
+            HmacSHA256("HmacSHA256"),
+            HmacSHA384("HmacSHA384"),
+            HmacSHA512("HmacSHA512");
+
+            private String value;
+
+            Algorithm(String algorithm) {
+                this.value = algorithm;
+            }
+
+            public String getValue() {
+                return this.value;
+            }
+        }
+
+        private Algorithm algorithm;
+        private byte[] data;
+        private byte[] key;
+
+        private DoHmac() { }
+
+        public static DoHmac custom() {
+            return new DoHmac();
+        }
+
+        public DoHmac setAlgorithm(Algorithm algorithm) {
+            this.algorithm = algorithm;
+            return this;
+        }
+
+        public DoHmac setData(byte[] data) {
+            this.data = data;
+            return this;
+        }
+
+        public DoHmac setBase64Data(String data, IoKit.Charsets charset) {
+            this.data = DoBase64.custom().setData(data, charset).decode();
+            return this;
+        }
+
+        public DoHmac setBase64Data(String data) {
+            return this.setBase64Data(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoHmac setStringData(String data, IoKit.Charsets charset) {
+            this.data = data.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoHmac setStringData(String data) {
+            return this.setStringData(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoHmac setKey(byte[] key) {
+            this.key = key;
+            return this;
+        }
+
+        public DoHmac setBase64Key(String key, IoKit.Charsets charset) {
+            this.key = DoBase64.custom().setData(key, charset).decode();
+            return this;
+        }
+
+        public DoHmac setBase64Key(String key) {
+            return this.setBase64Key(key, IoKit.Charsets.UTF_8);
+        }
+
+        public DoHmac setStringKey(String key, IoKit.Charsets charset) {
+            this.key = key.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoHmac setStringKey(String key) {
+            return this.setStringKey(key, IoKit.Charsets.UTF_8);
+        }
+
+        public byte[] toBytes() throws Exception {
+            return Hmacs.doHmac(this.algorithm, this.data, this.key);
+        }
+
+        public String toHexString() throws Exception {
+            return Hexs.encodeToString(this.toBytes());
+        }
+
+        public String toBase64String(IoKit.Charsets charset) throws Exception {
+            return DoBase64.custom().setData(this.toBytes()).encodeAsText(charset);
+        }
+
+        public String toBase64String() throws Exception {
+            return this.toBase64String(IoKit.Charsets.UTF_8);
+        }
+
+        public String toText(IoKit.Charsets charset) throws Exception {
+            return new String(this.toBytes(), charset.getCharset());
+        }
+
+        public String toText() throws Exception {
+            return this.toText(IoKit.Charsets.UTF_8);
+        }
+    }
+
+    public static class DoCipher {
+
+        static {
+            // for Cipher PKCS7Padding
+            Security.addProvider(new BouncyCastleProvider());
+        }
+
+        public enum Trans {
+
+            AES_CBC_NoPadding("AES/CBC/NoPadding", "128"),
+            AES_CBC_PKCS5Padding("AES/CBC/PKCS5Padding", "128"),
+            AES_CBC_PKCS7Padding("AES/CBC/PKCS7Padding", "128"),
+            AES_ECB_NoPadding("AES/ECB/NoPadding", "128"),
+            AES_ECB_PKCS5Padding("AES/ECB/PKCS5Padding", "128"),
+            AES_ECB_PKCS7Padding("AES/ECB/PKCS7Padding", "128"),
+
+            DES_CBC_NoPadding("DES/CBC/NoPadding", "56"),
+            DES_CBC_PKCS5Padding("DES/CBC/PKCS5Padding", "56"),
+            DES_ECB_NoPadding("DES/ECB/NoPadding", "56"),
+            DES_ECB_PKCS5Padding("DES/ECB/PKCS5Padding", "56"),
+
+            DESede_CBC_NoPadding("DESede/CBC/NoPadding", "168"),
+            DESede_CBC_PKCS5Padding("DESede/CBC/PKCS5Padding", "168"),
+            DESede_ECB_NoPadding("DESede/ECB/NoPadding", "168"),
+            DESede_ECB_PKCS5Padding("DESede/ECB/PKCS5Padding", "168"),
+
+            RSA_ECB_PKCS1Padding("RSA/ECB/PKCS1Padding", "1024, 2048"),
+            RSA_ECB_OAEPWithSHA1AndMGF1Padding("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", "1024, 2048"),
+            RSA_ECB_OAEPWithSHA256AndMGF1Padding("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", "1024, 2048");
+
+            private String transformation;
+
+            Trans(String transformation, String bits) {
+                this.transformation = transformation;
+            }
+
+            public String getTransformation() {
+                return this.transformation;
+            }
+        }
+
+        private Trans algorithm;
+        private byte[] data;
+        private byte[] key;
+        private byte[] iv;
+        private int mode;
+
+        private DoCipher() { }
+
+        public static DoCipher custom() {
+            return new DoCipher();
+        }
+
+        public DoCipher setAlgorithm(Trans algorithm) {
+            this.algorithm = algorithm;
+            return this;
+        }
+
+        public DoCipher setData(byte[] data) {
+            this.data = data;
+            return this;
+        }
+
+        public DoCipher setBase64Data(String data, IoKit.Charsets charset) {
+            this.data = DoBase64.custom().setData(data, charset).decode();
+            return this;
+        }
+
+        public DoCipher setBase64Data(String data) {
+            return this.setBase64Data(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoCipher setStringData(String data, IoKit.Charsets charset) {
+            this.data = data.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoCipher setStringData(String data) {
+            return this.setStringData(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoCipher setKey(byte[] key) {
+            this.key = key;
+            return this;
+        }
+
+        public DoCipher setBase64Key(String key, IoKit.Charsets charset) {
+            this.key = DoBase64.custom().setData(key, charset).decode();
+            return this;
+        }
+
+        public DoCipher setBase64Key(String key) {
+            return this.setBase64Key(key, IoKit.Charsets.UTF_8);
+        }
+
+        public DoCipher setStringKey(String key, IoKit.Charsets charset) {
+            this.key = key.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoCipher setStringKey(String key) {
+            return this.setStringKey(key, IoKit.Charsets.UTF_8);
+        }
+
+        public DoCipher setIv(byte[] iv) {
+            this.iv = iv;
+            return this;
+        }
+
+        public DoCipher setBase64Iv(String iv, IoKit.Charsets charset) {
+            this.iv = DoBase64.custom().setData(iv, charset).decode();
+            return this;
+        }
+
+        public DoCipher setBase64Iv(String iv) {
+            return this.setBase64Iv(iv, IoKit.Charsets.UTF_8);
+        }
+
+        public DoCipher setStringIv(String iv, IoKit.Charsets charset) {
+            this.iv = iv.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public DoCipher setStringIv(String iv) {
+            return this.setStringIv(iv, IoKit.Charsets.UTF_8);
+        }
+
+        public DoCipher ofDecrypt() {
+            this.mode = Cipher.DECRYPT_MODE;
+            return this;
+        }
+
+        public DoCipher ofEncrypt() {
+            this.mode = Cipher.ENCRYPT_MODE;
+            return this;
+        }
+
+        public byte[] toBytes() throws Exception {
+            return Ciphers.doCipher(this.mode, this.algorithm, this.data, this.key, this.iv);
+        }
+
+        public String toHexString() throws Exception {
+            return Hexs.encodeToString(this.toBytes());
+        }
+
+        public String toBase64String(IoKit.Charsets charset) throws Exception {
+            return DoBase64.custom().setData(this.toBytes()).encodeAsText(charset);
+        }
+
+        public String toBase64String() throws Exception {
+            return this.toBase64String(IoKit.Charsets.UTF_8);
+        }
+
+        public String toText(IoKit.Charsets charset) throws Exception {
+            return new String(this.toBytes(), charset.getCharset());
+        }
+
+        public String toText() throws Exception {
+            return this.toText(IoKit.Charsets.UTF_8);
+        }
+    }
+
+    public static class DoBase64 {
+
+        private byte[] var;
+
+        private DoBase64() { }
+
+        public static DoBase64 custom() {
+            return new DoBase64();
+        }
+
+        public DoBase64 setData(byte[] data) {
+            this.var = data;
+            return this;
+        }
+
+        public DoBase64 setData(String data) {
+            return this.setData(data, IoKit.Charsets.UTF_8);
+        }
+
+        public DoBase64 setData(String data, IoKit.Charsets charset) {
+            this.var = data.getBytes(charset.getCharset());
+            return this;
+        }
+
+        public byte[] encode() {
+            return Base64s.encode(this.var);
+        }
+
+        public byte[] decode() {
+            return Base64s.decode(this.var);
+        }
+
+        public String encodeAsText(IoKit.Charsets charset) {
+            return new String(this.encode(), charset.getCharset());
+        }
+
+        public String decodeAsText(IoKit.Charsets charset) {
+            return new String(this.decode(), charset.getCharset());
+        }
+
+        public String encodeAsText() {
+            return this.encodeAsText(IoKit.Charsets.UTF_8);
+        }
+
+        public String decodeAsText() {
+            return this.decodeAsText(IoKit.Charsets.UTF_8);
+        }
+    }
+}

+ 118 - 0
netflix-common/src/main/java/com/cyksj/common/util/IoKit.java

@@ -0,0 +1,118 @@
+package com.cyksj.common.util;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author valor.
+ * @date 2019/8/25 15:10
+ */
+public class IoKit {
+
+    private static final int buf_size = 8192;
+
+    private IoKit() {}
+
+    public enum Charsets {
+        UTF_8("utf-8", StandardCharsets.UTF_8);
+
+        private String value;
+
+        private Charset charset;
+
+        Charsets(String value, Charset charset) {
+            this.value = value;
+            this.charset = charset;
+        }
+
+        public String getValue() {
+            return this.value;
+        }
+
+        public Charset getCharset() {
+            return charset;
+        }
+    }
+
+    /**
+     * default charset 'UTF-8'
+     */
+    public static String toString(byte[] bytes) {
+        return toString(bytes, Charsets.UTF_8);
+    }
+
+    public static String toString(byte[] bytes, Charsets charset) {
+        return new String(bytes, charset.getCharset());
+    }
+
+    /**
+     * default charset 'UTF-8'
+     */
+    public static String toString(InputStream in) throws IOException {
+        return toString(in, Charsets.UTF_8);
+    }
+
+    public static String toString(InputStream in, Charsets charset) throws IOException {
+        return new String(toBytes(in), charset.getCharset());
+    }
+
+    public static byte[] toBytes(String str) {
+        return toBytes(str, Charsets.UTF_8);
+    }
+
+    public static byte[] toBytes(String str, Charsets charset) {
+        return str.getBytes(charset.getCharset());
+    }
+
+    public static byte[] toBytes(InputStream in) throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        write(in, out);
+        byte[] bytes = out.toByteArray();
+        close(out);
+        return bytes;
+    }
+
+    /**
+     * default charset 'UTF-8'
+     */
+    public static void write(String var, OutputStream out) throws IOException {
+        write(var, out, Charsets.UTF_8);
+    }
+
+    public static void write(String var, OutputStream out, Charsets charset) throws IOException {
+        out.write(var.getBytes(charset.getCharset()));
+    }
+
+    public static void write(byte[] var, OutputStream out) throws IOException {
+        out.write(var);
+    }
+
+    public static void write(InputStream in, OutputStream out) throws IOException {
+        byte[] buffer = new byte[buf_size];
+
+        int readSize;
+        while (true) {
+            readSize = in.read(buffer);
+            if (readSize < 0) {
+                break;
+            }
+            out.write(buffer, 0, readSize);
+        }
+        out.flush();
+
+        // close
+        close(in);
+    }
+
+    public static void close(Closeable closeable) {
+        if (null != closeable) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                // ignore exception
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 327 - 0
netflix-common/src/main/java/com/cyksj/common/util/J11HttpC.java

@@ -0,0 +1,327 @@
+package com.cyksj.common.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * debug jvm params:
+ *   1. httpClient:
+ *     -Djdk.internal.httpclient.debug=true
+ *   2. webSocket:
+ *     -Djdk.internal.httpclient.websocket.debug=true
+ *   3. hpack
+ *     -Djdk.internal.httpclient.hpack.debug=true
+ *
+ * <p>
+ *     jdk11 Http Client is Thread-safe
+ *     Build connection pool and selector thread pool internally
+ * </p>
+ *
+ * @author valor.
+ */
+public class J11HttpC {
+
+    private J11HttpC() { }
+
+    private static final J11HttpC instance;
+    static {
+        instance = new J11HttpC();
+    }
+
+    /* ---------- register http client (Editable) ---------- */
+
+    /**
+     * 连接超时时间
+     */
+    private static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(4);
+
+    /**
+     * 读取超时时间
+     */
+    private static final Duration SOCKET_TIMEOUT = Duration.ofSeconds(6);
+
+    /**
+     * Thread-safe
+     */
+    private static final HttpClient defaultClient;
+    static {
+        defaultClient = HttpClient.newBuilder()
+                .connectTimeout(CONNECT_TIMEOUT)
+                .build();
+    }
+
+    /**
+     * http clients
+     */
+    public enum Client {
+        BASE(defaultClient);
+
+        private HttpClient symbol;
+
+        Client(HttpClient symbol) {
+            this.symbol = symbol;
+        }
+    }
+
+    /* ---------- http request builder ---------- */
+
+    public static Builder custom() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private String url;
+        private Method method;
+        private KVAdapter[] headers;
+        private HttpRequest.BodyPublisher bodyPublisher;
+
+        /**
+         * cache URI
+         */
+        private boolean cacheURI;
+
+        private Builder() {
+            this.cacheURI = false;
+        }
+
+        public Builder url(String url) {
+            this.url = url;
+            return this;
+        }
+
+        public Builder cacheURI() {
+            this.cacheURI = true;
+            return this;
+        }
+
+        public Builder method(Method method) {
+            this.method = method;
+            return this;
+        }
+
+        public Builder ofGet() {
+            this.method = Method.GET;
+            return this;
+        }
+
+        public Builder ofPost() {
+            this.method = Method.POST;
+            return this;
+        }
+
+        public Builder headers(ReqType reqType) {
+            this.headers = new KVAdapter[] {ofHeader("content-type", reqType.mime)};
+            return this;
+        }
+
+        public Builder headers(KVAdapter... headers) {
+            this.headers = headers;
+            return this;
+        }
+
+        public Builder headers(ReqType reqType, KVAdapter... headers) {
+            final int oldLength = headers.length;
+            final int newLength = oldLength+ 1;
+            KVAdapter[] newHeaders = new KVAdapter[newLength];
+            System.arraycopy(headers, 0, newHeaders, 1, oldLength);
+
+            newHeaders[0] = ofHeader("content-type", reqType.mime);
+            this.headers = newHeaders;
+            return this;
+        }
+
+        public Builder body(HttpRequest.BodyPublisher bodyPublisher) {
+            this.bodyPublisher = bodyPublisher;
+            return this;
+        }
+
+        /* --- 同步send --- */
+
+        public <T> HttpResponse<T> send(HttpResponse.BodyHandler<T> responseBodyHandler) throws IOException, InterruptedException {
+            return this.send(Client.BASE, responseBodyHandler);
+        }
+
+        public <T> HttpResponse<T> send(Client httpClient, HttpResponse.BodyHandler<T> responseBodyHandler) throws IOException, InterruptedException {
+            return instance.send(httpClient.symbol, this.getRequest(), responseBodyHandler);
+        }
+
+        /* --- 异步send --- */
+
+        public <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpResponse.BodyHandler<T> responseBodyHandler) {
+            return this.sendAsync(Client.BASE, responseBodyHandler);
+        }
+
+        public <T> CompletableFuture<HttpResponse<T>> sendAsync(Client httpClient, HttpResponse.BodyHandler<T> responseBodyHandler) {
+            return instance.sendAsync(httpClient.symbol, this.getRequest(), responseBodyHandler);
+        }
+
+        /* --- ------- --- */
+
+        private HttpRequest getRequest() {
+            // require http URL
+            if (StringUtils.isBlank(this.url)) {
+                throw new RuntimeException("Empty Http URL.");
+            }
+
+            // default http method: GET
+            if (this.method == null) {
+                this.method = Method.GET;
+            }
+            // default http request body: noBody
+            if (this.bodyPublisher == null) {
+                this.bodyPublisher = HttpRequest.BodyPublishers.noBody();
+            }
+
+            URI uri = getURI(this.url, this.cacheURI);
+            HttpRequest request;
+            if (this.headers == null || this.headers.length <= 0) {
+                request = instance.buildRequest(uri, this.method, this.bodyPublisher);
+            } else {
+                request = instance.buildRequest(uri, this.method, this.bodyPublisher, this.headers);
+            }
+            return request;
+        }
+
+    }
+
+    /* ---------- cache http request uri ---------- */
+
+    /**
+     * 缓存URI的数量
+     */
+//    private static final int URI_CACHE_SIZE = 25;
+
+    /**
+     * 减少URI类的解析 LRU cache
+     */
+//    private static volatile LruCache<String, URI> uriCache = new LruCache<>(URI_CACHE_SIZE);
+
+    /**
+     * 获取URI
+     */
+    private static URI getURI(String url, boolean cache) {
+        // 非常频繁的接口调用 会导致cache维护开销增加
+//        if (cache) {
+//            URI uri = uriCache.get(url);
+//            if (null == uri) {
+//                uri = URI.create(url);
+//                uriCache.put(url, uri);
+//            }
+//            return uri;
+//        }
+        return URI.create(url);
+    }
+
+    /* ---------- pack http client ---------- */
+
+    /**
+     * 构建request
+     *
+     * @param uri           {@link URI}
+     * @param headers       {@link J11HttpC.KVAdapter}
+     * @param httpMethod    {@link J11HttpC.Method}
+     * @param bodyPublisher {@link HttpRequest.BodyPublisher}
+     * @return {@link HttpRequest}
+     */
+    private HttpRequest buildRequest(URI uri,
+                                     Method httpMethod,
+                                     HttpRequest.BodyPublisher bodyPublisher,
+                                     KVAdapter... headers) {
+
+        HttpRequest.Builder builder = HttpRequest.newBuilder();
+        builder.timeout(SOCKET_TIMEOUT);
+        builder.uri(uri);
+
+        // 设置请求头
+        if (headers.length > 0) {
+            for (KVAdapter e : headers) {
+                builder.setHeader(e.name, e.value);
+            }
+        }
+
+        // 设置请求方式和body参数
+        builder.method(httpMethod.symbol, bodyPublisher);
+        return builder.build();
+    }
+
+    /**
+     * 同步send
+     *
+     * @see HttpClient#send(HttpRequest, HttpResponse.BodyHandler)
+     */
+    public <T> HttpResponse<T>
+    send(HttpClient httpClient, HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler)
+            throws IOException, InterruptedException {
+        return httpClient.send(request, responseBodyHandler);
+    }
+
+    /**
+     * 同步send
+     *
+     * @see HttpClient#sendAsync(HttpRequest, HttpResponse.BodyHandler)
+     */
+    public <T> CompletableFuture<HttpResponse<T>>
+    sendAsync(HttpClient httpClient, HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler) {
+        return httpClient.sendAsync(request, responseBodyHandler);
+    }
+
+    /* ---------- http extensions ---------- */
+
+    public static KVAdapter ofHeader(String name, String value) {
+        return new KVAdapter(name, value);
+    }
+
+    /**
+     * Http Request Header
+     */
+    public static final class KVAdapter {
+        private String name;
+        private String value;
+
+        private KVAdapter(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
+    }
+
+    public enum Method {
+        GET("GET"),
+        POST("POST"),
+        HEAD("HEAD"),
+        OPTIONS("OPTIONS"),
+        PUT("PUT"),
+        DELETE("DELETE"),
+        TRACE("TRACE");
+
+        private String symbol;
+
+        Method(String symbol) {
+            this.symbol = symbol;
+        }
+    }
+
+    public enum ReqType {
+//        form_data("multipart/form-data"),
+        form_urlencoded("application/x-www-form-urlencoded; charset=utf-8"),
+        raw_text("text/plain; charset=utf-8"),
+        raw_js("application/javascript; charset=utf-8"),
+        raw_json("application/json; charset=utf-8"),
+        raw_html("text/html; charset=utf-8"),
+        raw_xml("application/xml; charset=utf-8");
+//        binary("application/octet-stream");
+
+        private String mime;
+
+        ReqType(String mime) {
+            this.mime = mime;
+        }
+    }
+
+}

+ 226 - 0
netflix-common/src/main/java/com/cyksj/common/util/Jsons.java

@@ -0,0 +1,226 @@
+package com.cyksj.common.util;
+
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author valor
+ * @date 2018/9/25 16:48
+ */
+public class Jsons {
+
+    private Jsons() { }
+
+    private static ObjectMapper mapper;
+
+    /**
+     * @return parser
+     */
+    public static ObjectMapper parser() {
+        return mapper;
+    }
+
+    /**
+     *
+     * @return typeFactory
+     */
+    public static TypeFactory javaType() {
+        return TypeFactory.defaultInstance();
+    }
+
+    static {
+        mapper = new ObjectMapper();
+
+        // 注册自定义序列化方案 (null值处理)
+//        mapper.setSerializerFactory(mapper.getSerializerFactory().withSerializerModifier(new CustomizeBeanSerializerModifier()));
+        // 在序列化时忽略值为 null 的属性
+//        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+        // 序列化时不包括没有@JsonView注解的属性
+        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
+        // 在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        // 将日期转为时间戳
+        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+    }
+
+    /**
+     * format entity to json.
+     *
+     * @return String 「Json」
+     */
+    public static String toJson(Object o) throws Exception {
+        return parser().writeValueAsString(o);
+    }
+
+    /**
+     * parse json and get child integer by key.
+     *
+     * @return integer 「value」
+     */
+    public static Integer parseGetInteger(String json, String key) throws Exception {
+        JsonNode node = parser().readTree(json).findValue(key);
+        if (null == node || node.isNull()) {
+            return null;
+        } else if (node.canConvertToInt()) {
+            return node.asInt();
+        }
+        return null;
+    }
+
+    /**
+     * parse bytes and get child integer by key.
+     *
+     * @return integer 「value」
+     */
+    public static Integer parseGetInteger(byte[] bytes, String key) throws Exception {
+        JsonNode node = parser().readTree(bytes).findValue(key);
+        if (null == node || node.isNull()) {
+            return null;
+        } else if (node.canConvertToInt()) {
+            return node.asInt();
+        }
+        return null;
+    }
+
+    /**
+     * parse json to map.
+     *
+     * @return Map<String, T> 「HashMap」
+     */
+    public static <T> Map<String, T> toMap(String json) throws Exception {
+        JavaType type = javaType().constructMapType(HashMap.class, String.class, Object.class);
+        return parser().readValue(json, type);
+    }
+
+    /**
+     * format entity to map.
+     *
+     * @return Map<String, T> 「HashMap」
+     */
+    public static <T> Map<String, T> toMap(Object o) {
+        JavaType type = javaType().constructMapType(HashMap.class, String.class, Object.class);
+        return parser().convertValue(o, type);
+    }
+
+    /**
+     * parse json to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(String json, Class<T> clazz) throws Exception {
+        return parser().readValue(json, clazz);
+    }
+
+    /**
+     * parse json to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(String json, JavaType javaType) throws Exception {
+        return parser().readValue(json, javaType);
+    }
+
+    /**
+     * parse json to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(byte[] bytes, Class<T> clazz) throws Exception {
+        return parser().readValue(bytes, clazz);
+    }
+
+    /**
+     * parse bytes to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(byte[] bytes, JavaType javaType) throws Exception {
+        return parser().readValue(bytes, javaType);
+    }
+
+    /**
+     * parse json to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(Object o, Class<T> clazz) {
+        return parser().convertValue(o, clazz);
+    }
+
+    /**
+     * parse json to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(Object o, JavaType javaType) {
+        return parser().convertValue(o, javaType);
+    }
+
+    /**
+     * parse json to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(String json, Class<T> clazz) throws Exception {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, clazz);
+        return parser().readValue(json, type);
+    }
+
+    /**
+     * parse json to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(String json, JavaType javaType) throws Exception {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, javaType);
+        return parser().readValue(json, type);
+    }
+
+    /**
+     * parse json to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(byte[] bytes, Class<T> clazz) throws Exception {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, clazz);
+        return parser().readValue(bytes, type);
+    }
+
+    /**
+     * parse json to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(byte[] bytes, JavaType javaType) throws Exception {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, javaType);
+        return parser().readValue(bytes, type);
+    }
+
+    /**
+     * parse json to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(Object o, Class<T> clazz) {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, clazz);
+        return parser().convertValue(o, type);
+    }
+
+    /**
+     * parse json to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(Object o, JavaType javaType) {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, javaType);
+        return parser().convertValue(o, type);
+    }
+
+}

+ 21 - 0
netflix-common/src/main/java/com/cyksj/common/util/StreamUtil.java

@@ -0,0 +1,21 @@
+package com.cyksj.common.util;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * @author chan
+ * @className StreamUtil
+ * @description stream 相关方法
+ * @date 2020/8/4 2:34 下午
+ */
+public class StreamUtil {
+
+    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
+        Map<Object, Boolean> concurrentHashMap = new ConcurrentHashMap<>(32);
+        return t -> concurrentHashMap.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
+    }
+
+}

+ 396 - 0
netflix-common/src/main/java/com/cyksj/common/util/StringUtil.java

@@ -0,0 +1,396 @@
+package com.cyksj.common.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  chan 字符串操作辅助类
+ **/
+public final class StringUtil {
+
+	/**
+	 * Linux and macOS.
+	 */
+	private static final String LF = "\n";
+
+	/**
+	 * Classic macOS.
+	 */
+	private static final String CR = "\r";
+
+	/**
+	 * Windows.
+	 */
+	private static final String CRLF = "\r\n";
+
+	/**
+	 * An empty immutable {@code String} array.
+	 */
+	public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+
+	public static final String EMPTY = "";
+
+	/**
+	 * provate constructor
+	 */
+	private StringUtil() { }
+
+	// Empty checks
+	//-----------------------------------------------------------------------
+	/**
+	 * <p>Checks if a CharSequence is empty ("") or null.</p>
+	 *
+	 * <pre>
+	 * Strings.isEmpty(null)      = true
+	 * Strings.isEmpty("")        = true
+	 * Strings.isEmpty(" ")       = false
+	 * Strings.isEmpty("bob")     = false
+	 * Strings.isEmpty("  bob  ") = false
+	 * </pre>
+	 *
+	 * <p>NOTE: This method changed in Lang version 2.0.
+	 * It no longer trims the CharSequence.
+	 * That functionality is available in isBlank().</p>
+	 *
+	 * @param cs  the CharSequence to check, may be null
+	 * @return {@code true} if the CharSequence is empty or null
+	 */
+	public static boolean isEmpty(final String cs) {
+		return cs == null || cs.isEmpty();
+	}
+
+	/**
+	 * <p>Checks if a CharSequence is not empty ("") and not null.</p>
+	 *
+	 * <pre>
+	 * Strings.isNotEmpty(null)      = false
+	 * Strings.isNotEmpty("")        = false
+	 * Strings.isNotEmpty(" ")       = true
+	 * Strings.isNotEmpty("bob")     = true
+	 * Strings.isNotEmpty("  bob  ") = true
+	 * </pre>
+	 *
+	 * @param cs  the CharSequence to check, may be null
+	 * @return {@code true} if the CharSequence is not empty and not null
+	 */
+	public static boolean isNotEmpty(final String cs) {
+		return !isEmpty(cs);
+	}
+
+	/**
+	 * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
+	 *
+	 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+	 *
+	 * <pre>
+	 * Strings.isBlank(null)      = true
+	 * Strings.isBlank("")        = true
+	 * Strings.isBlank(" ")       = true
+	 * Strings.isBlank("bob")     = false
+	 * Strings.isBlank("  bob  ") = false
+	 * </pre>
+	 *
+	 * @param cs  the CharSequence to check, may be null
+	 * @return {@code true} if the CharSequence is null, empty or whitespace only
+	 */
+	public static boolean isBlank(final String cs) {
+		return cs == null || cs.isBlank();
+	}
+
+	/**
+	 * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
+	 *
+	 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+	 *
+	 * <pre>
+	 * Strings.isNotBlank(null)      = false
+	 * Strings.isNotBlank("")        = false
+	 * Strings.isNotBlank(" ")       = false
+	 * Strings.isNotBlank("bob")     = true
+	 * Strings.isNotBlank("  bob  ") = true
+	 * </pre>
+	 *
+	 * @param cs  the CharSequence to check, may be null
+	 * @return {@code true} if the CharSequence is
+	 *  not empty and not null and not whitespace only
+	 */
+	public static boolean isNotBlank(final String cs) {
+		return !isBlank(cs);
+	}
+
+	/**
+	 * <p>Compares two CharSequences, returning {@code true} if they represent
+	 * equal sequences of characters.</p>
+	 *
+	 * <p>{@code null}s are handled without exceptions. Two {@code null}
+	 * references are considered to be equal. The comparison is <strong>case sensitive</strong>.</p>
+	 *
+	 * <pre>
+	 * StringUtils.equals(null, null)   = true
+	 * StringUtils.equals(null, "abc")  = false
+	 * StringUtils.equals("abc", null)  = false
+	 * StringUtils.equals("abc", "abc") = true
+	 * StringUtils.equals("abc", "ABC") = false
+	 * </pre>
+	 *
+	 * @param cs1  the first CharSequence, may be {@code null}
+	 * @param cs2  the second CharSequence, may be {@code null}
+	 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
+	 */
+	public static boolean equals(final String cs1, final String cs2) {
+		if (cs1 == null && cs2 == null) {
+			return true;
+		}
+		if (cs1 == null || cs2 == null) {
+			return false;
+		}
+		if (cs1.length() != cs2.length()) {
+			return false;
+		}
+		return cs1.equals(cs2);
+	}
+
+	/**
+	 * <p>Compares two CharSequences, returning {@code true} if they represent
+	 * equal sequences of characters, ignoring case.</p>
+	 *
+	 * <p>{@code null}s are handled without exceptions. Two {@code null}
+	 * references are considered equal. The comparison is <strong>case insensitive</strong>.</p>
+	 *
+	 * <pre>
+	 * StringUtils.equalsIgnoreCase(null, null)   = true
+	 * StringUtils.equalsIgnoreCase(null, "abc")  = false
+	 * StringUtils.equalsIgnoreCase("abc", null)  = false
+	 * StringUtils.equalsIgnoreCase("abc", "abc") = true
+	 * StringUtils.equalsIgnoreCase("abc", "ABC") = true
+	 * </pre>
+	 *
+	 * @param cs1  the first CharSequence, may be {@code null}
+	 * @param cs2  the second CharSequence, may be {@code null}
+	 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
+	 */
+	public static boolean equalsIgnoreCase(final String cs1, final String cs2) {
+		if (cs1 == null && cs2 == null) {
+			return true;
+		}
+		if (cs1 == null || cs2 == null) {
+			return false;
+		}
+		if (cs1.length() != cs2.length()) {
+			return false;
+		}
+		return cs1.equalsIgnoreCase(cs2);
+	}
+
+	/**
+	 * <p>Check if a CharSequence starts with a specified prefix.</p>
+	 *
+	 * <p>{@code null}s are handled without exceptions. Two {@code null}
+	 * references are considered to be equal. The comparison is case sensitive.</p>
+	 *
+	 * <pre>
+	 * StringUtils.startsWith(null, null)      = true
+	 * StringUtils.startsWith(null, "abc")     = false
+	 * StringUtils.startsWith("abcdef", null)  = false
+	 * StringUtils.startsWith("abcdef", "abc") = true
+	 * StringUtils.startsWith("ABCDEF", "abc") = false
+	 * </pre>
+	 *
+	 * @see String#startsWith(String)
+	 * @param str  the CharSequence to check, may be null
+	 * @param prefix the prefix to find, may be null
+	 * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
+	 *  both {@code null}
+	 */
+	public static boolean startsWith(final String str, final String prefix) {
+		if (null == str && prefix == null) {
+			return true;
+		}
+		if (null == str || prefix == null) {
+			return false;
+		}
+		return str.startsWith(prefix);
+	}
+
+	/**
+	 * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p>
+	 *
+	 * @see String#endsWith(String)
+	 * @param str  the CharSequence to check, may be null
+	 * @param suffix the suffix to find, may be null
+	 * @return {@code true} if the CharSequence starts with the prefix or
+	 *  both {@code null}
+	 */
+	public static boolean endsWith(final String str, final String suffix) {
+		if (null == str && suffix == null) {
+			return true;
+		}
+		if (null == str || suffix == null) {
+			return false;
+		}
+		return str.endsWith(suffix);
+	}
+
+	/**
+	 * Performs the logic for the {@code split} and
+	 * {@code splitPreserveAllTokens} methods that do not return a
+	 * maximum array length.
+	 *
+	 * @param str  the String to parse, may be {@code null}
+	 * @param separatorChar the separate character
+	 * @return an array of parsed Strings, {@code null} if null String input
+	 */
+	public static String[] split(final String str, final char separatorChar) {
+		// Performance tuned for 2.0 (JDK1.4)
+
+		if (str == null) {
+			return null;
+		}
+		final int len = str.length();
+		if (len == 0) {
+			return EMPTY_STRING_ARRAY;
+		}
+		final List<String> list = new ArrayList<>();
+		int i = 0, start = 0;
+		boolean match = false;
+		while (i < len) {
+			if (str.charAt(i) == separatorChar) {
+				if (match) {
+					list.add(str.substring(start, i));
+					match = false;
+				}
+				start = ++i;
+				continue;
+			}
+			match = true;
+			i++;
+		}
+		if (match) {
+			list.add(str.substring(start, i));
+		}
+		return list.toArray(new String[list.size()]);
+	}
+
+	/**
+	 * Performs the logic for the {@code split} and
+	 * {@code splitPreserveAllTokens} methods that return a maximum array
+	 * length.
+	 *
+	 * @param str  the String to parse, may be {@code null}
+	 * @param separatorChars the separate character
+	 * @return an array of parsed Strings, {@code null} if null String input
+	 */
+	public static String[] split(final String str, final String separatorChars) {
+		// Performance tuned for 2.0 (JDK1.4)
+		// Direct code is quicker than StringTokenizer.
+		// Also, StringTokenizer uses isSpace() not isWhitespace()
+
+		if (str == null) {
+			return null;
+		}
+		final int len = str.length();
+		if (len == 0) {
+			return EMPTY_STRING_ARRAY;
+		}
+		final List<String> list = new ArrayList<>();
+		int sizePlus1 = 1;
+		int i = 0, start = 0;
+		boolean match = false;
+
+		final int max = -1;
+
+		if (separatorChars == null) {
+			// Null separator means use whitespace
+			while (i < len) {
+				if (Character.isWhitespace(str.charAt(i))) {
+					if (match) {
+						if (sizePlus1++ == max) {
+							i = len;
+						}
+						list.add(str.substring(start, i));
+						match = false;
+					}
+					start = ++i;
+					continue;
+				}
+				match = true;
+				i++;
+			}
+		} else if (separatorChars.length() == 1) {
+			// Optimise 1 character case
+			final char sep = separatorChars.charAt(0);
+			while (i < len) {
+				if (str.charAt(i) == sep) {
+					if (match) {
+						if (sizePlus1++ == max) {
+							i = len;
+						}
+						list.add(str.substring(start, i));
+						match = false;
+					}
+					start = ++i;
+					continue;
+				}
+				match = true;
+				i++;
+			}
+		} else {
+			// standard case
+			while (i < len) {
+				if (separatorChars.indexOf(str.charAt(i)) >= 0) {
+					if (match) {
+						if (sizePlus1++ == max) {
+							i = len;
+						}
+						list.add(str.substring(start, i));
+						match = false;
+					}
+					start = ++i;
+					continue;
+				}
+				match = true;
+				i++;
+			}
+		}
+		if (match) {
+			list.add(str.substring(start, i));
+		}
+		return list.toArray(new String[list.size()]);
+	}
+
+
+	/**
+	 * @author chan
+	 * @param obj 需要转换的对象
+	 * @return string
+	 **/
+	public static String getString(Object obj) {
+		if (obj == null) {
+			return EMPTY;
+		} else {
+			return obj.toString();
+		}
+	}
+
+	/**
+	 * @author chan 异常栈字符串输出
+	 * @param throwable ex
+	 * @return String
+	 **/
+	public static String getErrorText(Throwable throwable) {
+		if (throwable == null) {
+			return "ERROR,throwable is NULL!";
+		}
+
+		try (StringWriter strWriter = new StringWriter(512); PrintWriter writer = new PrintWriter(strWriter)) {
+			throwable.printStackTrace(writer);
+			StringBuffer sb = strWriter.getBuffer();
+			return sb.toString();
+		} catch (Exception ex) {
+			return "ERROR!";
+		}
+	}
+}

+ 137 - 0
netflix-common/src/main/java/com/cyksj/common/util/Xmls.java

@@ -0,0 +1,137 @@
+package com.cyksj.common.util;
+
+import com.ctc.wstx.stax.WstxInputFactory;
+import com.ctc.wstx.stax.WstxOutputFactory;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author valor.
+ * @date 2019-08-02 13:52
+ */
+public class Xmls {
+
+    public Xmls() { }
+
+    private static XmlMapper xmlMapper;
+
+    /**
+     *
+     * @return typeFactory
+     */
+    public static TypeFactory javaType() {
+        return TypeFactory.defaultInstance();
+    }
+
+    public static XmlMapper parser() {
+        if (null == xmlMapper) {
+            synchronized (Xmls.class) {
+                if (null == xmlMapper) {
+                    // 基于woodstox 处理xml
+                    WstxInputFactory inputFactory = new WstxInputFactory();
+                    WstxOutputFactory outputFactory = new WstxOutputFactory();
+                    xmlMapper = new XmlMapper(inputFactory, outputFactory);
+
+                    // 在序列化时忽略值为 null 的属性
+                    xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+                    // 序列化时不包括没有@JsonView注解的属性
+                    xmlMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
+                    // 在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
+                    xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                    // 将日期转为时间戳
+                    xmlMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+                }
+            }
+        }
+        return xmlMapper;
+    }
+
+    /**
+     * format entity to xml.
+     *
+     * @return String 「Xml」
+     */
+    public static String toXml(Object o) throws JsonProcessingException {
+        return parser().writeValueAsString(o);
+    }
+
+    /**
+     * parse json to map.
+     *
+     * @return Map<String, T> 「HashMap」
+     */
+    public static <T> Map<String, T> toMap(String json) throws Exception {
+        JavaType type = javaType().constructMapType(HashMap.class, String.class, Object.class);
+        return parser().readValue(json, type);
+    }
+
+    /**
+     * parse bytes to map.
+     *
+     * @return Map<String, T> 「HashMap」
+     */
+    public static <T> Map<String, T> toMap(byte[] bytes) throws Exception {
+        JavaType type = javaType().constructMapType(HashMap.class, String.class, Object.class);
+        return parser().readValue(bytes, type);
+    }
+
+    /**
+     * format entity to map.
+     *
+     * @return Map<String, T> 「HashMap」
+     */
+    public static <T> Map<String, T> toMap(Object o) {
+        JavaType type = javaType().constructMapType(HashMap.class, String.class, Object.class);
+        return parser().convertValue(o, type);
+    }
+
+    /**
+     * parse xml to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(String xml, Class<T> clazz) throws Exception {
+        return parser().readValue(xml, clazz);
+    }
+
+    /**
+     * parse xml to entity.
+     *
+     * @return T 「entity」
+     */
+    public static <T> T parseObject(Object o, Class<T> clazz) {
+        return parser().convertValue(o, clazz);
+    }
+
+    /**
+     * parse xml to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(String json, Class<T> clazz) throws Exception {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, clazz);
+        return parser().readValue(json, type);
+    }
+
+    /**
+     * parse xml to ArrayList.
+     *
+     * @return List<T> 「ArrayList」
+     */
+    public static <T> List<T> parseList(Object o, Class<T> clazz) {
+        JavaType type = parser().getTypeFactory().constructCollectionType(ArrayList.class, clazz);
+        return parser().convertValue(o, type);
+    }
+
+}

+ 41 - 0
netflix-common/src/main/java/com/cyksj/dto/RedisKey.java

@@ -0,0 +1,41 @@
+package com.cyksj.dto;
+
+
+/**
+ * @author chan
+ * @date 2022/3/11 下午12:06
+ */
+public class RedisKey {
+
+    /**
+     * access_token
+     */
+    public static String ACCESS_TOKEN_KEY = "wechat:access_token:";
+
+    /**
+     * js_ticket
+     */
+    public static String JS_TICKET_KEY = "wechat:js_ticket:";
+
+    /**
+     * corp_access_token
+     */
+    public static String CORP_ACCESS_TOKEN_KEY = "corp:access_token:";
+
+    /**
+     * corp_js_ticket
+     */
+    public static String CORP_JS_TICKET_KEY = "corp_wechat:js_ticket:";
+
+    /**
+     * corp_agent_js_ticket
+     */
+    public static String CORP_AGENT_JS_TICKET_KEY = "corp_wechat:js_ticket:%s:agent:%s";
+
+
+    /**
+     * reatlion 座位
+     */
+    public static String GROUPS_RELATION_NUM_KEY = "group:relation:";
+
+}

+ 66 - 0
netflix-common/src/main/java/com/cyksj/dto/Result.java

@@ -0,0 +1,66 @@
+package com.cyksj.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author chan
+ * @date 2021-03-22 8:48 下午
+ */
+@Data
+@NoArgsConstructor
+public class Result<T> {
+	/**
+	 * 错误码
+	 */
+	private Integer code;
+
+	/**
+	 * 信息, 一般为状态的描述
+	 */
+	private String msg;
+
+	/**
+	 * 调用成功失败
+	 */
+	private boolean flag;
+
+	/**
+	 * 传递的数据
+	 */
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	private T data;
+
+	/**
+	 * 构造函数
+	 *  @param code
+	 * @param msg
+	 * @param data
+	 */
+	public Result(@JsonProperty("code") Integer code,
+                  @JsonProperty("msg") String msg,
+                  @JsonProperty("flag") boolean flag,
+                  @JsonProperty("data") T data) {
+		this.code = code;
+		this.msg = msg;
+		this.flag = flag;
+		this.data = data;
+	}
+
+	/**
+	 * 静态工厂构造方法
+	 *
+	 * @param code 状态码
+	 * @param msg 错误信息
+	 * @param data DTO
+	 * @param <T>DTO类型
+	 * @return
+	 */
+	public static <T> Result<T> of(Integer code, String msg,boolean flag ,T data) {
+		return new Result<>(code, msg,flag,data);
+	}
+
+
+}

+ 71 - 0
netflix-common/src/main/java/com/cyksj/enums/GatewayApiCode.java

@@ -0,0 +1,71 @@
+package com.cyksj.enums;
+
+import lombok.Getter;
+
+/**
+ * @author chan
+ * @className GatewayApiCode
+ * @description 网关响应码枚举
+ * @date 2021/3/22 9:45 下午
+ */
+@Getter
+public enum GatewayApiCode {
+
+    /**
+     * 接口调用成功
+     */
+    SUCCESS(10000, "success"),
+
+
+    /**
+     * API参数错误
+     */
+    ENUM_TYPE_ILLEGAL(10010, "非法枚举值"),
+    DATE_FORMAT_ILLEGAL(10020, "日期格式不对"),
+    START_TIME_FORMAT_ILLEGAL(10021, "起始时间不对"),
+    END_TIME_FORMAT_ILLEGAL(10022, "结束时间不对"),
+    USER_INFO_ILLEGAL(10023, "获取不到用户信息"),
+    WHITE_LIST_PROMOTION_TYPE_ILLEGAL(10124, "获取不到用户信息"),
+
+    /**
+     * 订单相关
+     */
+    THE_ORDER_CANNOT_BE_FOUND(30001,"该订单不存在"),
+    AMOUNT_TOO_SMALL(30021,"Stripe支付金额不能小于0.5$"),
+
+    /**
+     * 系统异常,10-系统异常
+     */
+    ILLEGAL_ENUM_VALUE(100001, "异常枚举类型"),
+    METADATA_SYSTEM_ERROR(100002, "系统错误"),
+
+    /**
+     * 11-mq处理异常
+     */
+    ILLEGAL_DELAY_MQ_TYPE(110001, "延时消息类型不在有效范围之内"),
+    LOOP_DELAY_MQ_ERR_INTERVAL(110002, "循环延时消息的interval不能为0"),
+    LOOP_DELAY_MQ_NOT_SET_STOP_CONDITION(110003, "循环延时消息未设置终止循环的有效数值"),
+
+    /**
+     * API参数错误-14
+     */
+    PARAMETER_MISSING_ERROR(140001, "参数错误"),
+    REPEAT_REQUEST(140002, "重复请求"),
+
+    /**
+     * 车票
+     */
+    GROUP_INDEX_NOT_FIND(40001,"该车位不存在"),
+
+    GROUP_INDEX_ALREADY_BE_USER(40002,"该车位已有人"),
+    ;
+
+    private Integer code;
+
+    private String msg;
+
+    GatewayApiCode(Integer _code, String _msg) {
+        this.code = _code;
+        this.msg = _msg;
+    }
+}

+ 111 - 0
netflix-common/src/main/java/com/cyksj/enums/GatewayResponse.java

@@ -0,0 +1,111 @@
+package com.cyksj.enums;
+
+
+import com.cyksj.dto.Result;
+
+import java.util.Map;
+
+/**
+ * @author chan
+ * @className GatewayResponse
+ * @date 2020/7/29 3:06 下午
+ */
+public enum GatewayResponse {
+
+    /**
+     * 成功
+     */
+    SUCCESS(GatewayApiCode.SUCCESS.getCode(), GatewayApiCode.SUCCESS.getMsg(),Boolean.TRUE),
+
+    /**
+     * 失败
+     */
+    FAIL(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(), GatewayApiCode.METADATA_SYSTEM_ERROR.getMsg(),Boolean.FALSE);
+
+    GatewayResponse(Integer _code, String _msg, boolean flag) {
+        this.code = _code;
+        this.msg = _msg;
+        this.flag = flag;
+    }
+
+    private Integer code;
+
+    private String msg;
+
+    private boolean flag;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public boolean getFlag(){
+        return flag;
+    }
+
+    public buildGateWay newBuilder() {
+        return new buildGateWay(this);
+    }
+
+    public class buildGateWay {
+
+        private Integer code;
+
+        private String msg;
+
+        private boolean flag;
+
+        buildGateWay(GatewayResponse response) {
+            this.code = response.getCode();
+            this.msg = response.getMsg();
+            this.flag = response.getFlag();
+        }
+
+        public buildGateWay buildGatewayCode(GatewayApiCode gateWayCode) {
+            this.code = gateWayCode.getCode();
+            this.msg = gateWayCode.getMsg();
+            return this;
+        }
+
+        public buildGateWay setMsg(String _msg) {
+            this.msg = _msg;
+            return this;
+        }
+        public buildGateWay setCode(Integer code) {
+            this.code = code;
+            return this;
+        }
+
+
+        public  <T> Result<T> toResult() {
+            return buildMap();
+        }
+
+
+        public <T extends java.io.Serializable> Result<T> toResult(T model) {
+            return Result.of(this.code,this.msg,this.flag,model);
+        }
+
+        @SuppressWarnings("rawtypes")
+        public <T extends java.util.Collection> Result<T>  toResult(T model) {
+            return Result.of(this.code,this.msg,this.flag,model);
+        }
+
+        @SuppressWarnings("rawtypes")
+        public <T> Result<T> toResult(T model) {
+            return Result.of(this.code,this.msg,this.flag,model);
+        }
+
+        @SuppressWarnings("rawtypes")
+        public <T extends Map> Result<T>  toResult(T model) {
+            return Result.of(this.code,this.msg,this.flag,model);
+        }
+
+        private <T> Result<T> buildMap() {
+            return Result.of(this.code,this.msg,this.flag,null);
+        }
+    }
+}

+ 44 - 0
netflix-common/src/main/java/com/cyksj/enums/WeChatAuthRedirectUrl.java

@@ -0,0 +1,44 @@
+package com.cyksj.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * @description
+ * @author chan
+ * @date 2021-10-10 下午3:24
+ */
+@Getter
+@AllArgsConstructor
+public enum WeChatAuthRedirectUrl {
+
+    /**
+     * 普通授权
+     */
+    BASE("base","auth/weChat/baseRedirect","snsapi_userinfo"),
+    /**
+     * 静默授权
+     */
+    SILENT("silent","auth/weChat/silentRedirect","snsapi_base");
+
+    private String name;
+
+    private String url;
+
+    private String scope;
+
+    /**
+     *
+     * @author chan 获取枚举中的字节码文件
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    public static WeChatAuthRedirectUrl get(String name){
+        return Stream.of(WeChatAuthRedirectUrl.values())
+                .filter(enums-> enums.getName().equals(name)).findFirst().orElse(BASE);
+    }
+
+
+}

+ 38 - 0
netflix-dao/pom.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>netflix</artifactId>
+        <groupId>com.netflix</groupId>
+        <version>1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>netflix-dao</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.netflix</groupId>
+            <artifactId>netflix-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.3.0</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/MyMetaObjectHandler.java

@@ -0,0 +1,40 @@
+package com.cyksj;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @className MyMetaObjectHandler
+ * @description
+ * @date 2020/7/29 2:44 下午
+ */
+@Component
+public class MyMetaObjectHandler implements MetaObjectHandler {
+    @Override
+    public void insertFill(MetaObject metaObject) {
+        //根据属性名称设置值
+        this.setFieldValByName("createdTime",new Date(),metaObject);
+        this.setFieldValByName("updateTime",new Date(),metaObject);
+        //this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
+        //this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
+        /* 上面选其一使用,下面的已过时(注意 strictInsertFill 有多个方法,详细查看源码) */
+        //this.setFieldValByName("operator", "Jerry", metaObject);
+        //this.setInsertFieldValByName("operator", "Jerry", metaObject);
+
+    }
+
+    @Override
+    public void updateFill(MetaObject metaObject) {
+
+        this.setFieldValByName("updateTime", new Date(), metaObject);
+        //this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
+        //this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
+        /* 上面选其一使用,下面的已过时(注意 strictUpdateFill 有多个方法,详细查看源码) */
+        //this.setFieldValByName("operator", "Tom", metaObject);
+        //this.setUpdateFieldValByName("operator", "Tom", metaObject);
+    }
+}

+ 37 - 0
netflix-dao/src/main/java/com/cyksj/MybatisPlusConfig.java

@@ -0,0 +1,37 @@
+package com.cyksj;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @author chan
+ * @className MybatisConfig
+ * @date 2020/7/15 3:05 下午
+ */
+
+@EnableTransactionManagement
+@Configuration
+@MapperScan(basePackages = {"com.cyksj.mapper"})
+public class MybatisPlusConfig {
+
+    /**
+     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
+     */
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
+        return interceptor;
+    }
+
+    @Bean
+    public ConfigurationCustomizer configurationCustomizer() {
+        return configuration -> configuration.setUseDeprecatedExecutor(false);
+    }
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/AccountMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.Account;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:22 PM
+ */
+public interface AccountMapper extends BaseMapper<Account> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsDon;
+
+/**
+ * @author chan
+ * @date 2022/9/27 5:31 PM
+ */
+public interface GoodsDonMapper extends BaseMapper<GoodsDon> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSkuMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsDonSku;
+
+/**
+ * @author chan
+ * @date 2022/9/26 6:54 PM
+ */
+public interface GoodsDonSkuMapper  extends BaseMapper<GoodsDonSku> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSpecMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsDonSpec;
+
+/**
+ * @author chan
+ * @date 2022/9/27 5:19 PM
+ */
+public interface GoodsDonSpecMapper extends BaseMapper<GoodsDonSpec> {
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GroupsTrips;
+import org.apache.ibatis.annotations.Update;
+
+/**
+ * @author chan
+ * @date 2022/9/27 4:24 PM
+ */
+public interface GroupsMapper extends BaseMapper<GroupsTrips> {
+    @Update("update groups_trips set available_num = available_num - 1 where id = #{groupId} and available_num > 0")
+    int decrAvailableNum(Long groupId);
+
+    @Update("update groups_trips set available_num = available_num + 1 where id = #{groupId} and available_num < num")
+    int incrAvailableNum(Long groupId);
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GroupsRelation;
+
+/**
+ * @author chan
+ * @date 2022/9/27 11:10 AM
+ */
+public interface GroupsRelationMapper extends BaseMapper<GroupsRelation> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/HomeGroupMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.HomeGroup;
+
+/**
+ * @author chan
+ * @date 2022/10/12 10:52 AM
+ */
+public interface HomeGroupMapper extends BaseMapper<HomeGroup> {
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -0,0 +1,18 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.excel.ExcelOrderDonInfo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2021/10/11 下午4:06
+ */
+public interface OrderDonMapper extends BaseMapper<OrderDon> {
+
+
+    List<ExcelOrderDonInfo> exportOrderInfo(@Param("promotionId") Long promotionId, @Param("start") String start, @Param("end") String end);
+}

+ 19 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java

@@ -0,0 +1,19 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.User;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+/**
+ * @author chan
+ * @date 2021/10/10 下午3:28
+ */
+public interface UserMapper extends BaseMapper<User> {
+
+    @Update("update user set lottery_time = lottery_time - 1 where id = #{userId} and lottery_time > 0")
+    int decrLotteryTime(@Param("userId") Long userId);
+
+    @Update("update user set lottery_time = lottery_time + 1 where id = #{id}")
+    void incrLotteryTime(@Param("id") Long userId);
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/mapper/WxAppMapper.java

@@ -0,0 +1,12 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.WxApp;
+
+/**
+ * @author chan
+ * @date 2021-10-10 下午12:19
+ */
+public interface WxAppMapper extends BaseMapper<WxApp> {
+
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/AdminMapper.java

@@ -0,0 +1,12 @@
+package com.cyksj.mapper.manage;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.manage.entity.Admin;
+
+/**
+ * @author chan
+ * @date 2021/10/12 下午9:11
+ */
+public interface AdminMapper extends BaseMapper<Admin> {
+
+}

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/BaseEntity.java

@@ -0,0 +1,36 @@
+package com.cyksj.model;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @className BaseEntity
+ * @description
+ * @date 2020/7/29 2:28 下午
+ */
+@Data
+@Accessors(chain = true)
+public class BaseEntity {
+
+    @TableId(value = "id",type =IdType.AUTO)
+    private Long id;
+
+    /**
+     * 创建时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createdTime;
+
+    /**
+     * 修改时间
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+}

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/AccountJsTicket.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author valor.
+ * @date 2019/12/12 14:33
+ */
+@Data
+@Accessors(chain = true)
+public class AccountJsTicket {
+
+    /* 参考 https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.6171762253872093#62 */
+
+    private Integer errcode;
+
+    private String errmsg;
+
+    private String ticket;
+
+    @JsonProperty("expires_in")
+    private Integer expiresIn;
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * @author valor
+ * @date 2019-04-03 15:47
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class AuthRedirect {
+    private Long mappingId;
+
+    private String authType;
+
+    private Long sharedId;
+
+}

+ 39 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/AuthToken.java

@@ -0,0 +1,39 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author valor
+ * @date 2018-12-13 11:30
+ */
+@Getter
+@Setter
+public class AuthToken {
+
+    /* 参考 https://mp.weixin.qq.com/wiki?action=doc&id=mp1421140842&t=0.4622491167403#1 */
+
+    @JsonProperty("access_token")
+    private String accessToken;
+
+    @JsonProperty("expires_in")
+    private Integer expiresIn;
+
+    @JsonProperty("refresh_token")
+    private String refreshToken;
+
+    private String openid;
+
+    private String scope;
+
+    public String println() {
+        return "AuthToken{" +
+                "accessToken='" + accessToken + '\'' +
+                ", expiresIn=" + expiresIn +
+                ", refreshToken='" + refreshToken + '\'' +
+                ", openid='" + openid + '\'' +
+                ", scope='" + scope + '\'' +
+                '}';
+    }
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/Authentication.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @author valor.
+ * @date 2019-07-24 14:54
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class Authentication {
+
+    private long id;
+
+    private Date time;
+    /**
+     * 记录用户最近一次登录时间
+     */
+    private long entry;
+
+    public Authentication() {
+        this.entry = System.currentTimeMillis();
+    }
+
+}

+ 55 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GzhOAuth2UserInfo.java

@@ -0,0 +1,55 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @date 2021-10-10 下午1:58
+ */
+@Getter
+@Setter
+public class GzhOAuth2UserInfo {
+
+    /**
+     * openid
+     */
+    private String openid;
+
+    /**
+     * 用户昵称
+     */
+    private String nickname;
+
+    /**
+     * 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
+     */
+    private Integer sex;
+
+    /**
+     * 用户个人资料填写的省份
+     */
+    private String province;
+
+    /**
+     * 普通用户个人资料填写的城市
+     */
+    private String city;
+
+    /**
+     * 国家,如中国为CN
+     */
+    private String country;
+
+    /**
+     * 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像)
+     * 用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
+     */
+    private String headimgurl;
+
+    /**
+     * 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
+     */
+    private String unionid;
+
+}

+ 76 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GzhUnionidUserinfo.java

@@ -0,0 +1,76 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author valor.
+ * @date 2019/12/4 10:11
+ */
+@Getter
+@Setter
+public class GzhUnionidUserinfo {
+
+    /**
+     * 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息
+     */
+    private Integer subscribe;
+
+    /**
+     * 益仓公众号openid
+     */
+    private String openid;
+
+    /**
+     * 用户昵称
+     */
+    private String nickname;
+
+    /**
+     * 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
+     */
+    private Integer sex;
+
+    /**
+     * 用户个人资料填写的省份
+     */
+    private String province;
+
+    /**
+     * 普通用户个人资料填写的城市
+     */
+    private String city;
+
+    /**
+     * 国家,如中国为CN
+     */
+    private String country;
+
+    /**
+     * 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像)
+     * 用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
+     */
+    private String headimgurl;
+
+    /**
+     * 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
+     */
+    private String unionid;
+
+    /**
+     *返回用户关注的渠道来源,
+     * ADD_SCENE_SEARCH 公众号搜索,
+     * ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,
+     * ADD_SCENE_PROFILE_CARD 名片分享,
+     * ADD_SCENE_QR_CODE 扫描二维码,
+     * ADD_SCENE_PROFILE_LINK 图文页内名称点击,
+     * ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,
+     * ADD_SCENE_PAID 支付后关注,
+     * ADD_SCENE_WECHAT_ADVERTISEMENT 微信广告,
+     * ADD_SCENE_OTHERS 其他
+     */
+    @JsonProperty(value = "subscribe_scene")
+    private String subscribeScene;
+
+}

+ 58 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/H5JsPayParams.java

@@ -0,0 +1,58 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * h5发起支付 必要的参数
+ *
+ * @author valor
+ * @date 2019-01-07 17:10
+ */
+@Getter
+@Setter
+public abstract class H5JsPayParams implements Serializable {
+
+    /**
+     * 公众号唯一标识
+     */
+    private String appId;
+
+    /**
+     * 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+     */
+    private Long timestamp;
+
+    /**
+     * 支付签名随机串,不长于 32 位
+     */
+    private String nonceStr;
+
+    /**
+     * 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+     */
+    private String prepayId;
+
+    /**
+     * 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
+     */
+    private String signType;
+
+    /**
+     * 支付签名
+     */
+    private String paySign;
+
+    private String orderNo;
+
+    public String println(String shopKey) {
+        return "appId=" + this.appId +
+                "&nonceStr=" + this.nonceStr +
+                "&package=" + this.prepayId +
+                "&signType=" + this.signType +
+                "&timeStamp=" + this.timestamp +
+                "&key=" + shopKey;
+    }
+}

+ 68 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/H5PayParams.java

@@ -0,0 +1,68 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+/**
+ * @author chan
+ * @className H5PayParams
+ * @description H5 参数
+ * @date 2020/7/23 3:30 下午
+ */
+@Getter
+@Setter
+public class H5PayParams extends H5JsPayParams {
+
+    /**
+     * 公众号唯一标识
+     */
+    private String appId;
+
+    /**
+     * 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+     */
+    private Long timestamp;
+
+    /**
+     * 支付签名随机串,不长于 32 位
+     */
+    private String nonceStr;
+
+    /**
+     * 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+     */
+    private String prepayId;
+
+    /**
+     * 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
+     */
+    private String signType;
+
+    /**
+     * 支付签名
+     */
+    private String paySign;
+
+    /**
+     * 支付跳转链接
+     */
+    private String mWebUrl;
+
+    /**
+     * 订单id
+     */
+    private Long orderId;
+
+    private String orderNo;
+
+    @Override
+    public String println(String shopKey) {
+        return "appId=" + this.appId +
+                "&nonceStr=" + this.nonceStr +
+                "&package=" + this.prepayId +
+                "&signType=" + this.signType +
+                "&timeStamp=" + this.timestamp +
+                "&key=" + shopKey;
+    }
+}

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/JsSdkTicket.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2021-10-10 下午12:23
+ */
+@Getter
+@Setter
+public class JsSdkTicket implements Serializable {
+
+    /**
+     * 公众号的唯一标识
+     */
+    private String appid;
+
+    /**
+     * 生成签名的时间戳
+     */
+    private Long timestamp;
+
+    /**
+     * 生成签名的随机串
+     */
+    private String nonceStr;
+
+    /**
+     * 签名
+     */
+    private String signature;
+
+    public String println() {
+        return "JsSdkTicket{" +
+                "appid='" + appid + '\'' +
+                ", timestamp=" + timestamp +
+                ", nonceStr='" + nonceStr + '\'' +
+                ", signature='" + signature + '\'' +
+                '}';
+    }
+}

+ 141 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/UnifiedOrder.java

@@ -0,0 +1,141 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * 微信H5支付 统一订单
+ * https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1
+ * @author chan
+ * @date 2021-10-10 下午9:47
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+@JacksonXmlRootElement(localName = "xml")
+public class UnifiedOrder {
+
+    /**
+     * 公众号appid
+     */
+    @JacksonXmlCData
+    private String appid;
+
+    /**
+     * 商户号
+     */
+    @JacksonXmlCData
+    @JsonProperty("mch_id")
+    private String mchId;
+
+    /**
+     * 随机字符串
+     */
+    @JacksonXmlCData
+    @JsonProperty("nonce_str")
+    private String nonceStr;
+
+    /**
+     * 签名
+     */
+    @JacksonXmlCData
+    private String sign;
+
+    /**
+     * 签名类型 支持HMAC-SHA256和MD5,默认为MD5
+     */
+    @JacksonXmlCData
+    @JsonProperty("sign_type")
+    private String signType;
+
+    /**
+     * 商品描述
+     */
+    @JacksonXmlCData
+    private String body;
+
+    /**
+     * 附加数据 在查询API和支付通知中原样返回 用于处理订单
+     */
+    @JacksonXmlCData
+    private String attach;
+
+    /**
+     * 商户订单号
+     */
+    @JacksonXmlCData
+    @JsonProperty("out_trade_no")
+    private String outTradeNo;
+
+    /**
+     * 订单总金额 单位为分
+     */
+    @JacksonXmlCData
+    @JsonProperty("total_fee")
+    private Integer totalFee;
+
+    /**
+     * 终端IP
+     */
+    @JacksonXmlCData
+    @JsonProperty("spbill_create_ip")
+    private String spbillCreateIp;
+
+    /**
+     * 通知地址
+     */
+    @JacksonXmlCData
+    @JsonProperty("notify_url")
+    private String notifyUrl;
+
+    /**
+     * 交易类型 默认为JSAPI
+     */
+    @JacksonXmlCData
+    @JsonProperty("trade_type")
+    private String tradeType;
+
+    /**
+     * 用户标识 trade_type=JSAPI 此参数必传
+     */
+    @JacksonXmlCData
+    private String openid;
+
+    @JacksonXmlCData
+    @JsonProperty("scene_info")
+    private String sceneInfo;
+
+    public String println(String shopKey) {
+        return "appid=" + this.appid +
+                "&attach=" + this.attach +
+                "&body=" + this.body +
+                "&mch_id=" + this.mchId +
+                "&nonce_str=" + this.nonceStr +
+                "&notify_url=" + this.notifyUrl +
+                "&openid=" + this.openid +
+                "&out_trade_no=" + this.outTradeNo +
+                "&spbill_create_ip=" + this.spbillCreateIp +
+                "&total_fee=" + totalFee +
+                "&trade_type=JSAPI" +
+                "&key=" + shopKey;
+    }
+
+    public String H5Println(String shopKey) {
+        return "appid=" + this.appid +
+                "&attach=" + this.attach +
+                "&body=" + this.body +
+                "&mch_id=" + this.mchId +
+                "&nonce_str=" + this.nonceStr +
+                "&notify_url=" + this.notifyUrl +
+                "&out_trade_no=" + this.outTradeNo +
+                "&scene_info=" + this.sceneInfo +
+                "&spbill_create_ip=" + this.spbillCreateIp +
+                "&total_fee=" + totalFee +
+                "&trade_type=MWEB" +
+                "&key=" + shopKey;
+    }
+}

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java

@@ -0,0 +1,33 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ *
+ * @author chan
+ * @date 2021-10-18 下午5:24
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class UserWhoami implements Serializable {
+
+    private Long id;
+
+    /**
+     * 名称
+     */
+    private String nickname;
+
+    /**
+     * 头像
+     */
+    private String headimgurl;
+
+
+}

+ 32 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/WeChatAccessToken.java

@@ -0,0 +1,32 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author chan
+ * @date 2021-10-10 下午1:58
+ */
+@Data
+@Accessors(chain = true)
+public class WeChatAccessToken {
+
+    /* 参考 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183 */
+
+    @JsonProperty("access_token")
+    private String accessToken;
+
+    @JsonProperty("expires_in")
+    private Integer expiresIn;
+
+    /**
+     * 错误码
+     */
+    private Integer errcode;
+
+    /**
+     * 错误信息
+     */
+    private String errmsg;
+}

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/WxMpTemplateData.java

@@ -0,0 +1,33 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2022-10-09 10:31 AM
+ */
+@Data
+public class WxMpTemplateData implements Serializable {
+  private static final long serialVersionUID = 6301835292940277870L;
+
+  private String name;
+  private String value;
+  private String color;
+
+  public WxMpTemplateData() {
+  }
+
+  public WxMpTemplateData(String name, String value) {
+    this.name = name;
+    this.value = value;
+  }
+
+  public WxMpTemplateData(String name, String value, String color) {
+    this.name = name;
+    this.value = value;
+    this.color = color;
+  }
+
+}

+ 83 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/WxMpTemplateMessage.java

@@ -0,0 +1,83 @@
+package com.cyksj.model.dto;
+
+import com.cyksj.common.util.Jsons;
+import lombok.*;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author chan
+ * @date 2022-10-09 10:31 AM
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class WxMpTemplateMessage implements Serializable {
+  private static final long serialVersionUID = 5063374783759519418L;
+
+  /**
+   * 接收者openid.
+   */
+  private String toUser;
+
+  /**
+   * 模板ID.
+   */
+  private String templateId;
+
+  /**
+   * 模板跳转链接.
+   * <pre>
+   * url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。
+   * 开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。
+   * </pre>
+   */
+  private String url;
+
+  /**
+   * 跳小程序所需数据,不需跳小程序可不用传该数据.
+   *
+   * @see #url
+   */
+  private MiniProgram miniProgram;
+
+  /**
+   * 模板数据.
+   */
+  @Builder.Default
+  private List<WxMpTemplateData> data = new ArrayList<>();
+
+  public WxMpTemplateMessage addData(WxMpTemplateData datum) {
+    if (this.data == null) {
+      this.data = new ArrayList<>();
+    }
+    this.data.add(datum);
+    return this;
+  }
+
+  public String toJson() throws Exception {
+    return Jsons.toJson(this);
+  }
+
+  @Data
+  @NoArgsConstructor
+  @AllArgsConstructor
+  public static class MiniProgram implements Serializable {
+    private static final long serialVersionUID = -7945254706501974849L;
+
+    private String appid;
+    private String pagePath;
+
+    /**
+     * 是否使用path,否则使用pagepath.
+     * 加入此字段是基于微信官方接口变化多端的考虑
+     */
+    private boolean usePath = false;
+  }
+
+}

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/Account.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:17 PM
+ */
+@Getter
+@Setter
+public class Account extends BaseEntity {
+
+    private String title;
+
+    private String account;
+
+    private String password;
+
+    private Long platformId;
+
+    private String platform;
+
+    private Date startTime;
+
+    private Date expiryTime;
+
+    /**
+     * 国区id
+     */
+    private String cnAccount;
+
+    /**
+     * 美区id
+     */
+    private String usAccount;
+
+    private String remark;
+
+}

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/BaseEntity.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2021-10-10 下午12:18
+ */
+@Data
+@Accessors(chain = true)
+public class BaseEntity {
+
+    @TableId(value = "id",type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 创建时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createdTime;
+
+    /**
+     * 修改时间
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+}

+ 56 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -0,0 +1,56 @@
+package com.cyksj.model.entity;
+
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @date 2022/9/26 4:58 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don")
+public class GoodsDon extends BaseEntity {
+
+    /**
+     * 商品录入人
+     */
+    private String writer;
+
+    /**
+     * 标签
+     */
+    private String tags;
+
+    /**
+     * 商品名称
+     */
+    private String title;
+
+    /**
+     * 缩略图
+     */
+    private String logo;
+
+    /**
+     * 背景图
+     */
+    private String img;
+
+
+    /**
+     * true 上架 / false 下架
+     */
+    private Boolean status;
+
+    /**
+     * true 存在 / false 删除
+     */
+    private Boolean deleted;
+
+    /**
+     * 详情
+     */
+    private String detail;
+}

+ 59 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java

@@ -0,0 +1,59 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author chan
+ * @date 2022/9/26 4:58 PM
+ */
+@Getter
+@Setter
+public class GoodsDonSku extends BaseEntity {
+
+    private Long goodsId;
+
+    /**
+     * 商品规格 ids
+     */
+    private String specIds;
+
+    /**
+     * 商品规格 value
+     */
+    private String specVal;
+
+    /**
+     * 商品规格 json
+     */
+    private String specJson;
+
+    /**
+     * 商品预览图
+     */
+    private String picture;
+
+
+    /**
+     * true 上架 / false 下架
+     */
+    private Boolean status;
+
+
+    /**
+     * 车位数
+     */
+    private Integer num;
+
+    /**
+     * 价格
+     */
+    private BigDecimal price;
+
+    /**
+     * 月数
+     */
+    private Integer months;
+}

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSpec.java

@@ -0,0 +1,36 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @date 2022/9/26 4:58 PM
+ */
+@Getter
+@Setter
+public class GoodsDonSpec extends BaseEntity {
+
+    private Long goodsId;
+
+    /**
+     * 商品总规格 json
+     */
+    private String specsJson;
+
+    /**
+     * 规格属性值最大id
+     */
+    private Integer maxId;
+
+    /**
+     * 商品规格数量
+     */
+    private Integer specNumber;
+
+    /**
+     * 属性id - 整体 映射
+     */
+    private String specMapping;
+
+}

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/26 6:31 PM
+ */
+@Getter
+@Setter
+public class GroupsRelation extends BaseEntity {
+
+    private Long groupsId;
+
+    private Long userId;
+
+    private Date startTime;
+
+    private Date expiryTime;
+
+    private Integer num;
+
+    /**
+     * locking 锁定中
+     * overdue 过期
+     * validity 有效
+     * none 无人
+     */
+    private Status status;
+
+
+
+    @AllArgsConstructor
+    @Getter
+    public enum Status{
+        locking("锁定中"),
+        overdue("过期"),
+        validity("有效"),
+        none("无人");
+
+        private String desc;
+
+    }
+}

+ 73 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTrips.java

@@ -0,0 +1,73 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/26 6:31 PM
+ */
+@Getter
+@Setter
+public class GroupsTrips extends BaseEntity {
+
+    /**
+     * 商品skuid
+     */
+    private Long skuId;
+
+    /**
+     * 账号id
+     */
+    private Long accountId;
+
+    /**
+     * 录入人
+     */
+    private Long writer;
+
+    /**
+     * 车位数量
+     */
+    private Integer num;
+
+    /**
+     * 可用车位数
+     */
+    private Integer availableNum;
+
+    /**
+     * 状态
+     */
+    private Status status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 修改价格时间
+     */
+    private Date upValTime;
+
+    /**
+     * 续费时间
+     */
+    private Date renewalTime;
+
+
+    @AllArgsConstructor
+    @Getter
+    public enum Status{
+        waiting("等待发车"),
+        validity("已发车"),
+        close("关闭");
+
+        private String desc;
+
+    }
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/HomeGroup.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.entity;
+
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2022/10/12 10:46 AM
+ */
+@Data
+public class HomeGroup extends BaseEntity{
+
+    private Long accountId;
+
+    private Long relationId;
+
+    /**
+     * invited
+     * uninvited
+     */
+    private String status;
+}

+ 78 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java

@@ -0,0 +1,78 @@
+package com.cyksj.model.entity;
+
+import lombok.*;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2021/10/11 下午4:04
+ */
+@Getter
+@Setter
+public class OrderDon extends BaseEntity implements Serializable {
+
+    /**
+     * 座位id
+     */
+    private Long relationId;
+
+    /**
+     * 商品id
+     */
+    private Long skuId;
+
+    /** 订单号 */
+    private String orderNo ;
+
+    /**
+     * 微信订单号
+     */
+    private String transactionId;
+
+
+    /** 用户id */
+    private Long userId ;
+
+    /**
+     * openId
+     */
+    private String openId;
+
+    /** 金额 */
+    private BigDecimal money ;
+
+
+    /** 支付状态 */
+    private Status status ;
+
+    /**
+     * 支付时间
+     */
+    private Date payTime;
+
+    public enum Status {
+        /**
+         * 订单状态
+         */
+        close("关闭订单"),
+        noPayment("待付款"),
+        hasPayment("已付款"),
+        transport("已发货"),
+        received("已签收"),
+        complete("已完成");
+        ;
+
+        private String desc;
+
+        Status(String desc) {
+            this.desc = desc;
+        }
+
+        public String getDesc() {
+            return desc;
+        }
+    }
+}

+ 15 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/Platform.java

@@ -0,0 +1,15 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @date 2022/9/26 5:31 PM
+ */
+@Getter
+@Setter
+public class Platform extends BaseEntity {
+
+
+}

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/User.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2021/10/10 下午2:53
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class User extends BaseEntity implements Serializable{
+    /** 手机号;手机号 */
+    private String phone ;
+    /** 昵称;昵称 */
+    private String nickname ;
+    /** 头像;头像 */
+    private String headimgurl ;
+    /** 开放平台唯一id;开放平台唯一id */
+    private String unionid ;
+
+    /**
+     * openid
+     */
+    private String openId;
+
+    /** 省份;省份 */
+    private String province ;
+    /** 国家;国家 */
+    private String country ;
+
+    /**
+     * 城市
+     */
+    private String city ;
+
+    /** 性别;性别 */
+    private Integer sex ;
+}
+

+ 66 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/WxApp.java

@@ -0,0 +1,66 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * @author chan
+ * @date 2021-10-10 下午12:17
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class WxApp extends BaseEntity {
+
+    /**
+     * 应用类型
+     */
+    private String category;
+
+    /**
+     * appId
+     */
+    private String appId;
+
+    /**
+     * appSecret
+     */
+    private String appSecret;
+
+    /**
+     * 域名地址
+     */
+    private String host;
+
+    /**
+     * 账号
+     */
+    private String account;
+
+    /**
+     * 密码
+     */
+    private String passCode;
+
+    /**
+     * 管理员
+     */
+    private String admin;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    @AllArgsConstructor
+    @Getter
+    public enum Category{
+        Mini_Program("小程序"),
+        APP("公众号");
+        private String desc;
+
+    }
+
+}

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelOrderDonInfo.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2021/10/13 下午10:16
+ */
+@Getter
+@Setter
+public class ExcelOrderDonInfo implements Serializable {
+
+    @ExcelProperty("订单号")
+    private String orderNo;
+
+    @ExcelProperty("微信名称")
+    private String nickName;
+
+    /** 姓名 */
+    @ExcelProperty("姓名")
+    private String realName ;
+
+    /** 推荐人 */
+    @ExcelProperty("推荐人微信名称")
+    private String sharedName ;
+
+    /** 金额 */
+    @ExcelProperty("金额")
+    private BigDecimal price ;
+
+    /** 电话号码 */
+    @ExcelProperty("电话号码")
+    private String phone ;
+
+    /** 生源 */
+    @ExcelProperty("生源")
+    private String source ;
+
+    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
+    @ExcelProperty("支付时间")
+    private Date payTime;
+
+
+}

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelSheetAndData.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.excel;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @className ExcelSheetAndData
+ * @description excel多sheet
+ * @date 2020/12/3 4:02 下午
+ */
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+public class ExcelSheetAndData {
+
+    private String sheetName;
+
+    private List<?> data;
+
+    private Class<?> clazz;
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExportExcelError.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @ClassName ExportExcelError
+ * @Author chan
+ * @Date 2020-04-28 17:02
+ * @Description 导出 错误 类
+ */
+@Data
+public class ExportExcelError implements Serializable {
+
+    @ExcelIgnore
+    private static final long serialVersionUID = -3474014939899483353L;
+
+    @ExcelProperty(value = "错误代码",index = 0)
+    private String code;
+
+    @ExcelProperty(value = "错误信息",index = 1)
+    private String msg;
+
+    @ExcelProperty(value = "描述信息",index = 2)
+    private String remark;
+
+
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/dto/AdminInfo.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.manage.dto;
+
+import com.cyksj.model.manage.entity.Admin;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2021-10-12 下午9:15
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+@Data
+public class AdminInfo implements Serializable {
+
+    private String token;
+
+    private Admin info;
+}

+ 63 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/entity/Admin.java

@@ -0,0 +1,63 @@
+package com.cyksj.model.manage.entity;
+
+import com.cyksj.model.entity.BaseEntity;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2021-10-12 下午9:10
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class Admin extends BaseEntity implements Serializable {
+
+    /**
+     * 管理员帐户
+     */
+    @NotBlank(message = "请填写账号")
+    private String userName;
+
+    /**
+     * 管理员昵称
+     */
+    @NotBlank(message = "请填写负责人姓名")
+    private String nickName;
+
+    /**
+     * 管理帐户密码
+     */
+    private String passWord;
+
+    /**
+     * 手机号码
+     */
+    private String phone;
+
+    /**
+     * 管理员身份
+     */
+    private Category category;
+
+    /**
+     * 管理员是否允许登录
+     */
+    private Boolean status;
+
+
+    public enum Category {
+        /**
+         * 管理员身份
+         */
+        superoot("超级管理员"),
+        normal("普通管理员");
+
+        Category(String desc) { }
+
+    }
+}

+ 49 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java

@@ -0,0 +1,49 @@
+package com.cyksj.model.manage.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2022/9/27 5:28 PM
+ */
+@Getter
+@Setter
+public class ReqGoodsSkuInsert {
+    @NotNull(message = "请指定商品spu.")
+    private Long goodsId;
+
+    private List<ReqGoodsSkuSpec> specs;
+
+    private List<Sku> skus;
+
+    @Getter
+    @Setter
+    public static class Sku {
+        /**
+         * 商品规格 ids
+         */
+        private String specIds;
+
+        /**
+         * 商品预览图
+         */
+        private String picture;
+
+        /**
+         * 原价 单位分
+         */
+        private BigDecimal price;
+
+        /**
+         * 成本 单位分
+         */
+        private Integer cost;
+
+    }
+
+}

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuSpec.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.manage.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2022/9/27 5:02 PM
+ */
+@Getter
+@Setter
+public class ReqGoodsSkuSpec {
+    private String key;
+
+    private List<Node> values;
+
+    @Getter
+    @Setter
+    public static class Node {
+        private Integer id;
+
+        private String value;
+    }
+}

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpecSingle.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.manage.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author chan
+ * @date 2022/9/27 4:51 PM
+ */
+@Getter
+@Setter
+public class ReqGoodsSpecSingle {
+
+    @NotNull(message = "请指定商品spu")
+    private Long goodsId;
+
+    @NotNull(message = "缺少规格属性id")
+    private Integer id;
+
+    @NotBlank(message = "缺少规格名")
+    private String key;
+
+    @NotBlank(message = "缺少属性名.")
+    private String name;
+}

+ 64 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java

@@ -0,0 +1,64 @@
+package com.cyksj.model.manage.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:09 PM
+ */
+@Getter
+@Setter
+public class ReqGoodsSpuInsert {
+
+    private Long id;
+
+    /**
+     * 商品录入人
+     */
+    private String writer;
+
+    /**
+     * 商品名称
+     */
+    @NotBlank(message = "请填写标题")
+    private String title;
+
+    /**
+     * 缩略图
+     */
+    private String thumbnail;
+
+    /**
+     * 轮播视频
+     */
+    private String video;
+
+
+    /**
+     * 商品描述
+     */
+    private String desc;
+
+
+    /**
+     * 轮播图
+     */
+    private String carousel;
+
+    /**
+     * 详情图
+     */
+    private String details;
+
+    /**
+     * 详情
+     */
+    private String detail;
+
+
+
+
+}

+ 56 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java

@@ -0,0 +1,56 @@
+package com.cyksj.model.manage.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/10/12 12:02 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "account a")
+public class AccountView {
+
+    @DbField("a.id")
+    private Long id;
+
+    @DbField("a.platform")
+    private String title;
+
+    @DbField("a.account")
+    private String account;
+
+    @DbField("a.password")
+    private String password;
+
+    @DbField("a.start_time")
+    private Date startTime;
+
+    @DbField("a.expiry_time")
+    private Date expiryTime;
+
+    /**
+     * 国区id
+     */
+    @DbField("a.cn_account")
+    private String cnAccount;
+
+    /**
+     * 美区id
+     */
+    @DbField("a.us_account")
+    private String usAccount;
+
+    @DbIgnore
+    private Integer unInvited;
+
+    @DbIgnore
+    private Integer total;
+
+}

+ 103 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java

@@ -0,0 +1,103 @@
+package com.cyksj.model.manage.views;
+
+import com.cyksj.model.entity.GoodsDonSku;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:00 PM
+ */
+@Getter
+@Setter
+@ToString
+@SearchBean(tables = "goods_don g left join goods_don_spec gs on g.id = gs.goods_id")
+public class GoodsDonViewer {
+    /**
+     * 商品id
+     */
+    @DbField("g.id")
+    private Long id;
+
+
+    /**
+     * 商品录入人
+     */
+    @DbField("g.writer")
+    private String writer;
+
+    /**
+     * 标签
+     */
+    @DbField("g.tags")
+    private String tags;
+
+    /**
+     * 商品名称
+     */
+    @DbField("g.title")
+    private String title;
+
+    /**
+     * 缩略图
+     */
+    @DbField("g.logo")
+    private String logo;
+
+
+    /**
+     * true 上架 / false 下架
+     */
+    @DbField("g.status")
+    private Boolean status;
+
+    /**
+     * true 存在 / false 删除
+     */
+    @DbField("g.deleted")
+    private Boolean deleted;
+
+    @DbField("gs.goods_id")
+    private Long goodsId;
+
+    /**
+     * 商品总规格 json
+     */
+    @DbField("gs.specs_json")
+    private String specsJson;
+
+    /**
+     * 规格属性值最大id
+     */
+    @DbField("gs.max_id")
+    private Integer maxId;
+
+    /**
+     * 商品规格数量
+     */
+    @DbField("gs.spec_number")
+    private Integer specNumber;
+
+    /**
+     * 属性id - 整体 映射
+     */
+    @DbField("gs.spec_mapping")
+    private String specMapping;
+
+    /**
+     * 详情
+     */
+    @DbField("g.detail")
+    private String detail;
+
+    @DbIgnore
+    private List<GoodsDonSku> skus;
+
+
+}

+ 60 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationView.java

@@ -0,0 +1,60 @@
+package com.cyksj.model.manage.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:47 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "groups_relation gr left join groups_trips g on gr.groups_id = g.id " +
+        "left join account a on a.id = g.account_id left join user u on gr.user_id = u.id")
+public class GroupsRelationView {
+
+    @DbField("gr.groups_id")
+    private Long groupsId;
+
+    @DbField("a.platform")
+    private String platform;
+
+    @DbField("u.nickname")
+    private String nickname;
+
+    @DbField("gr.user_id")
+    private Long userId;
+
+    @DbField("gr.expiry_time")
+    private Date expiryTime;
+
+    @DbField("gr.num")
+    private Integer num;
+
+    @DbField("u.nickname")
+    private String nickName;
+
+    @DbField("u.headimgurl")
+    private String headimgurl;
+
+    /**
+     * locking 锁定中
+     * overdue 过期
+     * validity 有效
+     * none 无人
+     */
+    @DbField("gr.status")
+    private String status;
+
+    /**
+     * 创建时间
+     */
+    @DbField("gr.created_time")
+    private Date createdTime;
+
+
+}

+ 52 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/HomeGroupView.java

@@ -0,0 +1,52 @@
+package com.cyksj.model.manage.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/10/12 12:11 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "home_group hp left join groups_relation gr on gr.id = hp.relation_id " +
+        "left join user u on gr.user_id = u.id " +
+        "left join groups_trips gt on gt.id = gr.groups_id " +
+        "left join goods_don_sku sku on gt.sku_id = sku.id")
+public class HomeGroupView {
+
+    @DbField("hp.id")
+    private Long id;
+
+    @DbField("hp.account_id")
+    private Long accountId;
+
+    @DbField("sku.sepc_val")
+    private String title;
+
+    @DbField("gr.start_time")
+    private String startTime;
+
+    @DbField("gr.user_id")
+    private Long userId;
+
+    @DbField("u.headimgurl")
+    private String headimgurl;
+
+    @DbField("u.nickname")
+    private String nickname;
+
+    @DbField("gr.expiry_time")
+    private Date expiryTime;
+
+    @DbField("gr.account")
+    private String account;
+
+    @DbField("hp.status")
+    private String status;
+
+}

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.manage.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:56 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don o,goods_don g,goods_don_sku sku,platform p,user u"
+        ,where = "o.sku_id = sku.id and g.id = sku.id and p.id = g.platform_id and o.user_id = u.id"
+)
+public class OrderDonView {
+
+    @DbField("o.id")
+    private Long id;
+
+    @DbField("o.order_no")
+    private String orderNo;
+
+    @DbField("p.title")
+    private String platform;
+
+    @DbField("sku.title")
+    private String title;
+
+    @DbField("u.id")
+    private Long userId;
+
+    @DbField("u.nickname")
+    private String nickname;
+
+    @DbField("o.money")
+    private BigDecimal money;
+
+    @DbField("o.status")
+    private String status;
+
+    @DbField("o.created_time")
+    private Date createdTime;
+}

+ 60 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java

@@ -0,0 +1,60 @@
+package com.cyksj.model.manage.views;
+
+import com.cyksj.model.entity.BaseEntity;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @date 2022/10/12 2:31 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user u")
+public class UserView extends BaseEntity {
+
+    /**
+     * id
+     */
+    @DbField("u.id")
+    private Long id;
+
+    /**
+     * 名称
+     */
+    @DbField("u.nickname")
+    private String nickname;
+
+    /**
+     * 手机号
+     */
+    @DbField("u.phone")
+    private String phone;
+
+    /**
+     * 头像
+     */
+    @DbField("u.headimgurl")
+    private String headimgurl;
+
+    /**
+     *  收款码
+     */
+    @DbField("u.img")
+    private String img;
+
+    /**
+     * 积分
+     */
+    @DbField("u.points")
+    private Integer points;
+
+    /**
+     * 账户数
+     */
+    @DbIgnore
+    private Integer accountNum;
+}

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderAttach.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @date 2021-10-11 下午6:18
+ */
+@Getter
+@Setter
+public class OrderAttach {
+
+    /**
+     * 订单id
+     */
+    private Long o;
+
+    /**
+     * 用户id
+     */
+    private int u;
+
+    /**
+     *  分享者id
+     */
+    private Long shared;
+
+}

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/**
+ * @author chan
+ * @date 2021/10/11 下午4:10
+ */
+@Getter
+@Setter
+@ToString
+public class OrderPayRequest {
+
+    private Long userId;
+    /**
+     * 商品id
+     */
+    @NotNull(message = "缺少必填参数")
+    private Long skuId;
+
+    /**
+     * 座位id
+     */
+    private Long relationId;
+
+    /**
+     * 金额
+     */
+    @NotNull(message = "请输入金额")
+    private BigDecimal donMoney;
+
+    /**
+     * 推荐人id
+     */
+    private Long sharedId;
+
+
+    /**
+     * 数量
+     */
+    private Integer num;
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonViews.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.GoodsDonSpec;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2022/9/26 5:41 PM
+ */
+
+@Getter
+@Setter
+public class GoodsDonViews extends GoodsDon {
+
+    @DbIgnore
+    private List<GoodsDonSku> skuList;
+
+    @DbIgnore
+    private GoodsDonSpec specs;
+}

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GroupsView.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GroupsRelation;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2022/9/26 6:35 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "groups_trips g")
+public class GroupsView {
+
+    @DbField("g.id")
+    private Long id;
+
+    @DbField("g.sku_id")
+    private Long skuId;
+
+    /**
+     * 车位数量
+     */
+    @DbField("g.num")
+    private Integer num;
+
+    /**
+     * 状态
+     */
+    @DbField("g.status")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @DbField("g.remark")
+    private String remark;
+
+    /**
+     * 关系
+     */
+    @DbIgnore
+    private List<GroupsRelation> relations;
+
+}

+ 39 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -0,0 +1,39 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/27 11:54 AM
+ */
+@SearchBean(tables = "groups_relation gr left join groups_trips g on g.id = gr.groups_id" +
+        "left join goods_don_sku sku on g.sku_id = sku.id " +
+        "left join goods_don g on g.id = sku.goods_id")
+@Getter
+@Setter
+public class RenewalView {
+
+    @DbField("gr.groups_id")
+    private String groupId;
+
+    @DbField("g.title")
+    private String title;
+
+    @DbField("g.logo")
+    private String logo;
+
+    @DbField("gr.user_id")
+    private Long userId;
+
+    @DbField("gr.expiry_time")
+    private Date expiryTime;
+
+    @DbField("gr.status")
+    private String status;
+
+}

+ 20 - 0
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.OrderDonMapper">
+
+
+    <select id="exportOrderInfo" resultType="com.cyksj.model.excel.ExcelOrderDonInfo">
+        SELECT o.order_no, o.real_name ,o.price,o.phone,o.source,o.pay_time ,u1.nickname as sharedName,u2.nickname as nickName
+        from order_don o  LEFT JOIN user u1 on o.shared_id = u1.id
+        LEFT JOIN user u2 on o.user_id = u2.id
+        where o.promotion_id = #{promotionId,jdbcType=BIGINT}
+         and o.status = 'hasPayment'
+        <if test="start != null and start != ''">
+            and o.pay_time >= #{start,jdbcType=VARCHAR}
+        </if>
+        <if test="end != null and end != ''">
+            and #{end,jdbcType=VARCHAR} >= o.pay_time
+        </if>
+
+    </select>
+</mapper>

+ 34 - 0
netflix-service/pom.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>netflix</artifactId>
+        <groupId>com.netflix</groupId>
+        <version>1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>netflix-service</artifactId>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.netflix</groupId>
+            <artifactId>netflix-dao</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+</project>

+ 44 - 0
netflix-service/src/main/java/com/cyksj/config/BaseWeChatConfig.java

@@ -0,0 +1,44 @@
+package com.cyksj.config;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author chan
+ * @className BaseWeChatConfig
+ * @description 配置
+ * @date 2020/9/1 4:52 下午
+ */
+@Getter
+@Setter
+public abstract class BaseWeChatConfig {
+    /**
+     * 公众号唯一标识
+     */
+    private String appid;
+
+    /**
+     * 公众号唯一标识 对应key
+     */
+    private String secret;
+
+    /**
+     * 公众号授权域名
+     */
+    private String domain;
+
+    /**
+     * 商户平台id
+     */
+    private String shopid;
+
+    /**
+     * 商户平台 对应key
+     */
+    private String shopKey;
+
+    /**
+     * 微信支付title
+     */
+    private String payMsg;
+}

+ 27 - 0
netflix-service/src/main/java/com/cyksj/config/WeChatConfig.java

@@ -0,0 +1,27 @@
+package com.cyksj.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @author chan
+ * @className WeChatConfig
+ * @description 微信配置
+ * @date 2020/7/20 2:28 下午
+ */
+@Configuration
+@ConfigurationProperties(prefix = "wechat")
+@Getter
+@Setter
+public class WeChatConfig extends BaseWeChatConfig {
+
+
+    @PostConstruct
+    public void add() {
+        WeChatFactory.add(this);
+    }
+}

+ 38 - 0
netflix-service/src/main/java/com/cyksj/config/WeChatFactory.java

@@ -0,0 +1,38 @@
+package com.cyksj.config;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author chan
+ * @className WeChatFactory
+ * @description 配置
+ * @date 2020/9/1 4:51 下午
+ */
+public class WeChatFactory {
+    private static Map<String, BaseWeChatConfig> strategyBean = new ConcurrentHashMap<>();
+
+    /**
+     * 初始化
+     *
+     * @param appId
+     * @return
+     */
+    public static BaseWeChatConfig getWeChatConfigStrategy(String appId) {
+        if (StringUtils.isEmpty(appId)) {
+            throw BusinessRuntimeException.getInstance("appid错误");
+        }
+        BaseWeChatConfig baseWeChatConfig = strategyBean.get(appId);
+        Objects.requireNonNull(baseWeChatConfig, "appid错误");
+        return baseWeChatConfig;
+    }
+
+    public static void add(BaseWeChatConfig baseWeChatConfig) {
+        strategyBean.put(baseWeChatConfig.getAppid(), baseWeChatConfig);
+    }
+
+}

+ 574 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -0,0 +1,574 @@
+package com.cyksj.redis;
+
+import com.cyksj.common.util.StringUtil;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * @description 定义常用的 Redis操作
+ * @author chan
+ * @date 2021-03-31 5:34 下午
+ */
+@Service
+@SuppressWarnings("all")
+public class RedisService {
+
+    @Resource
+    private RedisTemplate<String, Object> redisTemplate;
+
+    /**
+     * 指定缓存失效时间
+     *
+     * @param key  键
+     * @param time 时间(秒)
+     * @return Boolean
+     */
+    public Boolean expire(String key, Long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据key获取过期时间
+     *
+     * @param key 键 不能为 null
+     * @return 时间(秒) 返回 0代表为永久有效
+     */
+    public Long getExpire(String key) {
+        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 判断 key是否存在
+     *
+     * @param key 键
+     * @return true 存在 false不存在
+     */
+    public Boolean hasKey(String key) {
+        try {
+            return redisTemplate.hasKey(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除缓存
+     *
+     * @param key 可以传一个值 或多个
+     */
+    public void del(String... key) {
+        if (key != null && key.length > 0) {
+            if (key.length == 1) {
+                redisTemplate.delete(key[0]);
+            } else {
+                redisTemplate.delete(Arrays.asList(key));
+            }
+        }
+    }
+
+    /**
+     * 普通缓存获取
+     *
+     * @param key 键
+     * @return 值
+     */
+    public Object get(String key) {
+        return key == null ? null : redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * String缓存获取
+     * @param key 键
+     * @return 值
+     */
+    public String getStr(String key) {
+            return key == null ? null : StringUtil.getString(redisTemplate.opsForValue().get(key));
+    }
+
+    /**
+     * 普通缓存放入
+     *
+     * @param key   键
+     * @param value 值
+     * @return true成功 false失败
+     */
+    public Boolean set(String key, Object value) {
+        try {
+            redisTemplate.opsForValue().set(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 普通缓存放入并设置时间
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
+     * @return true成功 false 失败
+     */
+    public Boolean set(String key, Object value, Long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+            } else {
+                set(key, value);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 递增
+     *
+     * @param key   键
+     * @param delta 要增加几(大于0)
+     * @return Long
+     */
+    public Long incr(String key, Long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 递减
+     *
+     * @param key   键
+     * @param delta 要减少几
+     * @return Long
+     */
+    public Long decr(String key, Long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, -delta);
+    }
+
+    /**
+     * HashGet
+     *
+     * @param key  键 不能为 null
+     * @param item 项 不能为 null
+     * @return 值
+     */
+    public Object hget(String key, String item) {
+        return redisTemplate.opsForHash().get(key, item);
+    }
+
+    /**
+     * 获取 hashKey对应的所有键值
+     *
+     * @param key 键
+     * @return 对应的多个键值
+     */
+    public Map<Object, Object> hmget(String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * HashSet
+     *
+     * @param key 键
+     * @param map 对应多个键值
+     * @return true 成功 false 失败
+     */
+    public Boolean hmset(String key, Map<String, Object> map) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * HashSet 并设置时间
+     *
+     * @param key  键
+     * @param map  对应多个键值
+     * @param time 时间(秒)
+     * @return true成功 false失败
+     */
+    public Boolean hmset(String key, Map<String, Object> map, Long time) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     *
+     * @param key   键
+     * @param item  项
+     * @param value 值
+     * @return true 成功 false失败
+     */
+    public Boolean hset(String key, String item, Object value) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     *
+     * @param key   键
+     * @param item  项
+     * @param value 值
+     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
+     * @return true 成功 false失败
+     */
+    public Boolean hset(String key, String item, Object value, Long time) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除hash表中的值
+     *
+     * @param key  键 不能为 null
+     * @param item 项 可以使多个不能为 null
+     */
+    public void hdel(String key, Object... item) {
+        redisTemplate.opsForHash().delete(key, item);
+    }
+
+    /**
+     * 判断hash表中是否有该项的值
+     *
+     * @param key  键 不能为 null
+     * @param item 项 不能为 null
+     * @return true 存在 false不存在
+     */
+    public Boolean hHasKey(String key, String item) {
+        return redisTemplate.opsForHash().hasKey(key, item);
+    }
+
+    /**
+     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
+     *
+     * @param key  键
+     * @param item 项
+     * @param by   要增加几(大于0)
+     * @return Double
+     */
+    public Double hincr(String key, String item, Double by) {
+        return redisTemplate.opsForHash().increment(key, item, by);
+    }
+
+    /**
+     * hash递减
+     *
+     * @param key  键
+     * @param item 项
+     * @param by   要减少记(小于0)
+     * @return Double
+     */
+    public Double hdecr(String key, String item, Double by) {
+        return redisTemplate.opsForHash().increment(key, item, -by);
+    }
+
+    /**
+     * 根据 key获取 Set中的所有值
+     *
+     * @param key 键
+     * @return Set
+     */
+    public Set<Object> sGet(String key) {
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 根据value从一个set中查询,是否存在
+     *
+     * @param key   键
+     * @param value 值
+     * @return true 存在 false不存在
+     */
+    public Boolean sHasKey(String key, Object value) {
+        try {
+            return redisTemplate.opsForSet().isMember(key, value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将数据放入set缓存
+     *
+     * @param key    键
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public Long sSet(String key, Object... values) {
+        try {
+            return redisTemplate.opsForSet().add(key, values);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 将set数据放入缓存
+     *
+     * @param key    键
+     * @param time   时间(秒)
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public Long sSetAndTime(String key, Long time, Object... values) {
+        try {
+            Long count = redisTemplate.opsForSet().add(key, values);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return count;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 获取set缓存的长度
+     *
+     * @param key 键
+     * @return Long
+     */
+    public Long sGetSetSize(String key) {
+        try {
+            return redisTemplate.opsForSet().size(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 移除值为value的
+     *
+     * @param key    键
+     * @param values 值 可以是多个
+     * @return 移除的个数
+     */
+    public Long setRemove(String key, Object... values) {
+        try {
+            return redisTemplate.opsForSet().remove(key, values);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 获取list缓存的内容
+     *
+     * @param key   键
+     * @param start 开始
+     * @param end   结束 0 到 -1代表所有值
+     * @return List
+     */
+    public List<Object> lGet(String key, Long start, Long end) {
+        try {
+            return redisTemplate.opsForList().range(key, start, end);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 获取list缓存的长度
+     *
+     * @param key 键
+     * @return Long
+     */
+    public Long lGetListSize(String key) {
+        try {
+            return redisTemplate.opsForList().size(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 通过索引 获取list中的值
+     *
+     * @param key   键
+     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;
+     *              index<0时,-1,表尾,-2倒数第二个元素,依次类推
+     * @return Object
+     */
+    public Object lGetIndex(String key, Long index) {
+        try {
+            return redisTemplate.opsForList().index(key, index);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean lSet(String key, Object value) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒)
+     * @return Boolean
+     */
+    public Boolean lSet(String key, Object value, Long time) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean lSet(String key, List<Object> value) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒)
+     * @return Boolean
+     */
+    public Boolean lSet(String key, List<Object> value, Long time) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据索引修改list中的某条数据
+     *
+     * @param key   键
+     * @param index 索引
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean lUpdateIndex(String key, Long index, Object value) {
+        try {
+            redisTemplate.opsForList().set(key, index, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 移除N个值为value
+     *
+     * @param key   键
+     * @param count 移除多少个
+     * @param value 值
+     * @return 移除的个数
+     */
+    public Long lRemove(String key, Long count, Object value) {
+        try {
+            return redisTemplate.opsForList().remove(key, count, value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+}

+ 23 - 0
netflix-service/src/main/java/com/cyksj/service/authorization/AuthorizationService.java

@@ -0,0 +1,23 @@
+package com.cyksj.service.authorization;
+
+import com.cyksj.model.dto.JsSdkTicket;
+
+/**
+ * @author chan
+ * @className AuthorizationService
+ * @description 授权服务
+ * @date 2021/10/8 1:58 下午
+ */
+public interface AuthorizationService {
+
+    /**
+     * 微信授权转发地址
+     * @param state
+     * @param authType
+     * @return
+     */
+    String createUrl(String state, String authType);
+
+    JsSdkTicket getJsTicket(String appId, String url) throws Exception;
+
+}

+ 58 - 0
netflix-service/src/main/java/com/cyksj/service/authorization/impl/AuthorizationServiceImpl.java

@@ -0,0 +1,58 @@
+package com.cyksj.service.authorization.impl;
+
+import com.cyksj.common.util.Codec;
+import com.cyksj.config.WeChatConfig;
+import com.cyksj.enums.WeChatAuthRedirectUrl;
+import com.cyksj.model.dto.JsSdkTicket;
+import com.cyksj.service.authorization.AuthorizationService;
+import com.cyksj.service.wechat.WeChatService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @className AuthorizationServiceImpl
+ * @description 授权服务
+ * @date 2021/10/8 1:58 下午
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class AuthorizationServiceImpl implements AuthorizationService {
+
+    private final WeChatService weChatService;
+
+    private final WeChatConfig weChatConfig;
+
+
+    @Override
+    public String createUrl(String state, String authType) {
+        return weChatService.createUrl(state,weChatConfig.getDomain() + WeChatAuthRedirectUrl.get(authType).getUrl()
+                ,weChatConfig.getAppid(),WeChatAuthRedirectUrl.get(authType).getScope());
+    }
+
+    @Override
+    public JsSdkTicket getJsTicket(String appId, String url) throws Exception {
+
+        // 获取js-ticket
+        String ticket = weChatService.getJsTicket(appId);
+
+        // 生成js-sdk权限验证 签名
+        JsSdkTicket jsSdkTicket = new JsSdkTicket();
+        jsSdkTicket.setAppid(appId);
+        jsSdkTicket.setNonceStr("chan");
+        jsSdkTicket.setTimestamp(System.currentTimeMillis());
+
+        String str = "jsapi_ticket=" + ticket +
+                "&noncestr=" + jsSdkTicket.getNonceStr() +
+                "&timestamp=" + jsSdkTicket.getTimestamp() +
+                "&url=" + url;
+
+        String sha1Hex = Codec.DoDigest.custom()
+                .setAlgorithm(Codec.DoDigest.Algorithm.SHA1).setStringData(str).toHexString();
+        jsSdkTicket.setSignature(sha1Hex);
+        return jsSdkTicket;
+    }
+
+}

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/mange/AdminService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.mange;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.manage.entity.Admin;
+
+/**
+ * @author chan
+ * @date 2021/10/12 下午9:11
+ */
+public interface AdminService extends IService<Admin> {
+}

+ 16 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java

@@ -0,0 +1,16 @@
+package com.cyksj.service.mange;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.AccountMapper;
+import com.cyksj.model.entity.Account;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:23 PM
+ */
+public interface CmsAccountService extends IService<Account> {
+}

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.mange;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.model.entity.GoodsDon;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2022/9/27 5:31 PM
+ */
+public interface CmsGoodsDonService extends IService<GoodsDon> {
+
+}

+ 16 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonSkuService.java

@@ -0,0 +1,16 @@
+package com.cyksj.service.mange;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.model.entity.GoodsDonSku;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2022/9/27 5:43 PM
+ */
+public interface CmsGoodsDonSkuService extends IService<GoodsDonSku> {
+}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.