Просмотр исходного кода

完善多次缴费及订单查询的流程
核对缴费明细数据

binguoc 4 лет назад
Родитель
Сommit
643cc299b0
100 измененных файлов с 8785 добавлено и 0 удалено
  1. 5 0
      .travis.yml
  2. BIN
      netpay-0.0.1.jar
  3. 66 0
      package.json
  4. 186 0
      pom.xml
  5. 24 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/TuitionPaymentApplication.java
  6. 14 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/anno/AdminLoginCheck.java
  7. 60 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/aop/LoginCheckAspect.java
  8. 56 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/exception/BizCodeEnume.java
  9. 124 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/exception/MyExceptionHandler.java
  10. 65 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/exception/RRException.java
  11. 35 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/BaseResult.java
  12. 47 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/CommonResult.java
  13. 127 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/Constant.java
  14. 141 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/JwtOperator.java
  15. 55 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/MyQuery.java
  16. 33 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/PageParam.java
  17. 101 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/PageUtils.java
  18. 51 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/common/xss/SQLFilter.java
  19. 25 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/config/CCBPayConfig.java
  20. 31 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/config/CorsConfig.java
  21. 20 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/config/JXNXSPayConfig.java
  22. 21 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/config/WechatConfig.java
  23. 22 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/config/WeixiaoConfig.java
  24. 133 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/AdminInfoController.java
  25. 75 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/EnablePayLimitByGradeController.java
  26. 184 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/FeedbackMsgController.java
  27. 119 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayController.java
  28. 131 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayItemController.java
  29. 57 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayItemDetailController.java
  30. 94 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayMethodSettingController.java
  31. 346 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayOrderController.java
  32. 735 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayableInfoController.java
  33. 153 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayableInfoWaterController.java
  34. 54 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/TestController.java
  35. 404 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/WechatController.java
  36. 44 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/conver/aliexcel/CustomPayMethodConverter.java
  37. 38 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/conver/aliexcel/LocalDateTimeConverter.java
  38. 46 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/conver/aliexcel/MsgStatuConverter.java
  39. 17 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/AdminInfoDao.java
  40. 16 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/EnablePayLimitByGradeDao.java
  41. 17 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/FeedbackMsgDao.java
  42. 15 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayItemDao.java
  43. 16 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayItemDetailDao.java
  44. 9 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayMethodSettingDao.java
  45. 17 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayOrderDao.java
  46. 17 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayableInfoDao.java
  47. 18 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayableInfoWaterDao.java
  48. 54 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/AdminInfoEntity.java
  49. 31 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/EnablePayLimitByGradeEntity.java
  50. 105 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/FeedbackMsgEntity.java
  51. 65 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayItem.java
  52. 26 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayItemDetail.java
  53. 46 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayMethodSettingEntity.java
  54. 183 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayOrderEntity.java
  55. 170 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayableInfoEntity.java
  56. 154 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayableInfoWaterEntity.java
  57. 21 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/enume/FeedbackMsgStatus.java
  58. 22 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/enume/PayMethod.java
  59. 29 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/enume/PayStatus.java
  60. 74 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/listener/aliexcel/MyPayableInfoImportListener.java
  61. 72 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/listener/aliexcel/MyPayableInfoWaterImportListener.java
  62. 36 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/listener/aliexcel/MyStudentNoImportListener.java
  63. 22 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/AdminInfoService.java
  64. 16 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/EnablePayLimitByGradeService.java
  65. 33 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/FeedbackMsgService.java
  66. 14 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayItemDetailService.java
  67. 13 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayItemService.java
  68. 9 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayMethodSettingService.java
  69. 60 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayOrderService.java
  70. 23 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayService.java
  71. 44 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayableInfoService.java
  72. 40 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayableInfoWaterService.java
  73. 68 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/AdminInfoServiceImpl.java
  74. 31 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/EnablePayLimitByGradeServiceImpl.java
  75. 134 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/FeedbackMsgServiceImpl.java
  76. 22 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayItemDetailServiceImpl.java
  77. 19 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayItemServiceImpl.java
  78. 30 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayMethodSettingServiceImpl.java
  79. 696 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayOrderServiceImpl.java
  80. 530 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayServiceImpl.java
  81. 348 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayableInfoServiceImpl.java
  82. 292 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayableInfoWaterServiceImpl.java
  83. 73 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/to/DeletePayableInfoTO.java
  84. 45 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/to/FeedbackMsgCreateTO.java
  85. 57 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/to/PayOrderQueryTO.java
  86. 11 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/to/PayableInfoQueryTO.java
  87. 95 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/CCBRSASig.java
  88. 34 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/FileUtilss.java
  89. 164 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/JXNXSPayUtil.java
  90. 122 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/ListPageUtil.java
  91. 110 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/MyAES.java
  92. 96 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/MySignatureUtil.java
  93. 64 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/MyUtil.java
  94. 179 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/OutputTxt.java
  95. 34 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/CreateOrderResultVO.java
  96. 20 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/CurrentPayMethodVO.java
  97. 39 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/FeedbackMsgQueryVO.java
  98. 20 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/OrderReceiveVO.java
  99. 26 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/OrderStatusVO.java
  100. 0 0
      src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/OutputTxtVO.java

+ 5 - 0
.travis.yml

@@ -0,0 +1,5 @@
+language: node_js
+node_js: 10
+script: npm run test
+notifications:
+  email: false

BIN
netpay-0.0.1.jar


+ 66 - 0
package.json

@@ -0,0 +1,66 @@
+{
+  "name": "vue-admin-template",
+  "version": "4.4.0",
+  "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
+  "author": "1452635110@qq.com 小新",
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "build:prod": "vue-cli-service build",
+    "build:stage": "vue-cli-service build --mode staging",
+    "preview": "node build/index.js --preview",
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
+    "lint": "eslint --ext .js,.vue src",
+    "test:unit": "jest --clearCache && vue-cli-service test:unit",
+    "test:ci": "npm run lint && npm run test:unit"
+  },
+  "dependencies": {
+    "axios": "0.18.1",
+    "core-js": "3.6.5",
+    "element-ui": "2.13.2",
+    "file-saver": "^2.0.5",
+    "js-cookie": "2.2.0",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "path-to-regexp": "2.4.0",
+    "vue": "2.6.10",
+    "vue-quill-editor": "^3.0.6",
+    "vue-router": "3.0.6",
+    "vuex": "3.1.0",
+    "xlsx": "^0.18.5"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "4.4.4",
+    "@vue/cli-plugin-eslint": "4.4.4",
+    "@vue/cli-plugin-unit-jest": "4.4.4",
+    "@vue/cli-service": "4.4.4",
+    "@vue/test-utils": "1.0.0-beta.29",
+    "autoprefixer": "9.5.1",
+    "babel-eslint": "10.1.0",
+    "babel-jest": "23.6.0",
+    "babel-plugin-dynamic-import-node": "2.3.3",
+    "chalk": "2.4.2",
+    "connect": "3.6.6",
+    "eslint": "6.7.2",
+    "eslint-plugin-vue": "6.2.2",
+    "html-webpack-plugin": "3.2.0",
+    "mockjs": "1.0.1-beta3",
+    "runjs": "4.3.2",
+    "sass": "1.26.8",
+    "sass-loader": "8.0.2",
+    "script-ext-html-webpack-plugin": "2.1.3",
+    "script-loader": "^0.7.2",
+    "serve-static": "1.13.2",
+    "svg-sprite-loader": "4.1.3",
+    "svgo": "1.2.2",
+    "vue-template-compiler": "2.6.10"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ],
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "license": "MIT"
+}

+ 186 - 0
pom.xml

@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.5.3</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.chuanghai.smartschool</groupId>
+    <artifactId>tuition_payment</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>tuition_payment</name>
+    <description>学费以及杂费缴费项目</description>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- mybatis plus -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+
+<!--        &lt;!&ndash;    集成easypoi组件 .导出excel http://easypoi.mydoc.io/ &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>cn.afterturn</groupId>-->
+<!--            <artifactId>easypoi-base</artifactId>-->
+<!--            <version>3.2.0</version>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>cn.afterturn</groupId>-->
+<!--            <artifactId>easypoi-web</artifactId>-->
+<!--            <version>3.2.0</version>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>cn.afterturn</groupId>-->
+<!--            <artifactId>easypoi-annotation</artifactId>-->
+<!--            <version>3.2.0</version>-->
+<!--        </dependency>-->
+
+        <!-- jwt -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-api</artifactId>
+            <version>0.10.7</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>0.10.7</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-jackson</artifactId>
+            <version>0.10.7</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>3.16.1</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <!-- 数据校验 -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>6.1.5.Final</version>
+        </dependency>
+
+        <!-- aop -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!-- excel操作 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>2.2.10</version>
+        </dependency>
+
+        <!-- 建行支付工具类 -->
+        <dependency>
+            <groupId>com.ccb.pay</groupId>
+            <artifactId>netpay</artifactId>
+            <version>0.0.1</version>
+        </dependency>
+
+        <!-- 密码加密 -->
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-crypto</artifactId>
+            <version>5.4.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.57</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <!-- smart doc -->
+            <plugin>
+                <groupId>com.github.shalousun</groupId>
+                <artifactId>smart-doc-maven-plugin</artifactId>
+                <version>2.1.4</version>
+                <configuration>
+                    <!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
+                    <configFile>./src/main/resources/smart-doc.json</configFile>
+                    <!--指定项目名称-->
+                    <projectName>学费缴纳项目</projectName>
+                </configuration>
+                <executions>
+                    <execution>
+                        <!--如果不需要在执行编译时启动smart-doc,则将phase注释掉-->
+                        <phase>compile</phase>
+                        <goals>
+                            <!--smart-doc提供了html、openapi、markdown等goal,可按需配置-->
+                            <goal>html</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 24 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/TuitionPaymentApplication.java

@@ -0,0 +1,24 @@
+package com.chuanghai.smartschool.tuitionpayment;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableScheduling //设置定时任务
+public class TuitionPaymentApplication{
+
+    public static void main(String[] args) {
+        SpringApplication.run(TuitionPaymentApplication.class, args);
+    }
+
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
+        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
+        return paginationInterceptor;
+    }
+}

+ 14 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/anno/AdminLoginCheck.java

@@ -0,0 +1,14 @@
+package com.chuanghai.smartschool.tuitionpayment.anno;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * @Author: codingliang
+ * @Description: 管理员登录检查
+ * @Date: 2021-05-14 17:26
+ * @Version: V1.0
+ **/
+@Target(ElementType.METHOD)
+public @interface AdminLoginCheck {
+}

+ 60 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/aop/LoginCheckAspect.java

@@ -0,0 +1,60 @@
+package com.chuanghai.smartschool.tuitionpayment.aop;
+
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.JwtOperator;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @Author: codingliang
+ * @Description: 登录拦截
+ * @Date: 2021-04-29 15:57
+ * @Version: V1.0
+ **/
+@Aspect
+@Component
+public class LoginCheckAspect {
+
+    @Autowired
+    private JwtOperator jwtOperator;
+
+    /**
+     * 管理员登录拦截
+     * @param point
+     * @return
+     * @throws Throwable
+     */
+    @Around("@annotation(com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck)")
+    public Object userLoginCheck(ProceedingJoinPoint point) throws Throwable {
+        validateToken("admin_token");
+        return point.proceed();
+    }
+
+
+    // 检验token
+    private String validateToken(String headName) {
+        HttpServletRequest request = getHttpServletRequest();
+        String token = request.getHeader(headName);
+        if (!StringUtils.hasText(token) || !jwtOperator.validateToken(token)) {
+            throw new RRException(BizCodeEnume.TOKET_INVALID);
+        }
+        return token;
+    }
+
+    // 获取request
+    private HttpServletRequest getHttpServletRequest() {
+        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
+        return attributes.getRequest();
+    }
+}

+ 56 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/exception/BizCodeEnume.java

@@ -0,0 +1,56 @@
+package com.chuanghai.smartschool.tuitionpayment.common.exception;
+
+/***
+ * 错误码和错误信息定义类
+ * 1. 错误码定义规则为5为数字
+ * 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
+ * 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
+ * 错误码列表:
+ *  10: 通用
+ *      001:参数格式校验
+ *  11: 用户
+ *  12: 权限
+ *  13: 参数异常
+ *  14: 文件
+ *  15: 积分模块
+ *
+ *
+ */
+public enum BizCodeEnume {
+    UNKNOW_EXCEPTION(10000,"系统未知异常"),
+    VAILD_EXCEPTION(10001,"参数格式校验失败"),
+    BODY_IS_EMPTY(10002, "body为空"),
+    METHOD_NOT_SUPPORT(10003, "请求方法不支持"),
+    DATA_IS_EXIST(10004, "数据已存在"),
+    DATA_IS_NOT_EXIST(10005, "数据不存在"),
+    TOKET_INVALID(10006, "无效的token"),
+    PARAMETER_ERROR(10007, "参数异常"),
+    NO_PERMISSION(10008, "没有操作权限"),
+    ADMIN_LOGIN_FAIL(10009, "管理员登录失败"),
+    REQUEST_HEADER_MISSING(10012, "缺少必要的请求头"),
+    PAYABLE_INFO_IS_NOT_EXIT(10013, "缴费信息不存在"),
+    ORDER_IS_NOT_EXIT(10014, "订单不存在"),
+    GET_JSAPI_PAY_PARAM_ERROR(10015, "获取微信jsapi支付参数失败"),
+    CCB_ORDER_QUERY_ERROR(10016, "建行订单状态查询失败"),
+    NOT_CCB_PAY_ORDER(10017, "非建行支付订单"),
+    JXNXS_ORDER_QUERY_ERROR(10018, "农商行订单状态查询失败"),
+    PAY_GRADE_IS_NOT_EXIT(10019, "缴费年级不存在"),
+    FILE_IMPORT_ERROR(10020, "文件导入失败"),
+    BATCH_EXECUTOR_ERROR(10100, "批量操作数据库失败"),
+    PAY_AMOUNT_ERROR(10021,"付款金额错误");
+
+    private int code;
+    private String msg;
+    BizCodeEnume(int code,String msg){
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 124 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/exception/MyExceptionHandler.java

@@ -0,0 +1,124 @@
+package com.chuanghai.smartschool.tuitionpayment.common.exception;
+
+import com.alibaba.excel.exception.ExcelAnalysisException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.util.StringUtils;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingRequestHeaderException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: codingliang
+ * @Description: 统一异常处理
+ * @Date: 2021-01-06 10:07
+ * @Version: V1.0
+ **/
+@RestControllerAdvice
+public class MyExceptionHandler {
+
+    /**
+     * 处理参数校验异常
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public CommonResult handleValidException(MethodArgumentNotValidException e) {
+        Map<String, String> map = new HashMap<>();
+        e.getBindingResult().getFieldErrors().forEach(item -> {
+            String errMessage = item.getDefaultMessage();
+            String errField = item.getField();
+            map.put(errField, errMessage);
+        });
+        return CommonResult.fail(Integer.toString(BizCodeEnume.VAILD_EXCEPTION.getCode()), BizCodeEnume.VAILD_EXCEPTION.getMsg()).setResult(map);
+    }
+
+    /**
+     * 数据库索引重复
+     * @return
+     */
+    @ExceptionHandler(DuplicateKeyException.class)
+    public CommonResult handleSQLIntegrityConstraintViolationException() {
+        return CommonResult.fail(Integer.toString(BizCodeEnume.DATA_IS_EXIST.getCode()), BizCodeEnume.DATA_IS_EXIST.getMsg());
+    }
+
+    /**
+     * 请求方法不支持
+     * @return
+     */
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public CommonResult handleRequestMethodNotSupported() {
+        return CommonResult.fail(Integer.toString(BizCodeEnume.METHOD_NOT_SUPPORT.getCode()), BizCodeEnume.METHOD_NOT_SUPPORT.getMsg());
+    }
+
+    /**
+     * 缺少请求头
+     * @return
+     */
+    @ExceptionHandler(MissingRequestHeaderException.class)
+    public CommonResult handleRequestHeaderMissing() {
+        return CommonResult.fail(Integer.toString(BizCodeEnume.REQUEST_HEADER_MISSING.getCode()), BizCodeEnume.REQUEST_HEADER_MISSING.getMsg());
+    }
+
+    /**
+     * 参数缺失
+     * @return
+     */
+    @ExceptionHandler(MissingServletRequestParameterException.class)
+    public CommonResult handleMissingServletRequestParameterException() {
+        return CommonResult.fail(Integer.toString(BizCodeEnume.PARAMETER_ERROR.getCode()), BizCodeEnume.PARAMETER_ERROR.getMsg());
+    }
+
+    /**
+     * body为空
+     * @return
+     */
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public CommonResult handleMessageNotReadableException() {
+        return CommonResult.fail(Integer.toString(BizCodeEnume.BODY_IS_EMPTY.getCode()), BizCodeEnume.BODY_IS_EMPTY.getMsg());
+    }
+
+    /**
+     * easyExcel 文件读取失败
+     * @return
+     */
+    @ExceptionHandler(ExcelAnalysisException.class)
+    public CommonResult handleExcelAnalysisException(ExcelAnalysisException e) {
+        String errorMessage = e.getMessage();
+        String errMsg = "文件导入失败";
+        if (StringUtils.hasText(errorMessage) && errorMessage.contains("doesn't have a default value")) {
+            errMsg =  "文件导入失败,请检查模板header是否正确";
+        } else if (StringUtils.hasText(errorMessage) && errorMessage.contains("Duplicate entry")) {
+            errMsg = "文件导入失败,含有重复数据";
+        }
+        return CommonResult.fail(Integer.toString(BizCodeEnume.FILE_IMPORT_ERROR.getCode()), errMsg);
+    }
+
+    /**
+     * 自定义异常
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(RRException.class)
+    public CommonResult handleRRException(RRException e) {
+        return CommonResult.fail(Integer.toString(e.getCode()), e.getMsg());
+    }
+
+    /**
+     * 未知异常
+     * @param throwable
+     * @return
+     */
+    @ExceptionHandler(Throwable.class)
+    public CommonResult handleException(Throwable throwable) {
+        throwable.printStackTrace();
+        return CommonResult.fail(Integer.toString(BizCodeEnume.UNKNOW_EXCEPTION.getCode()), BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
+    }
+}

+ 65 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/exception/RRException.java

@@ -0,0 +1,65 @@
+package com.chuanghai.smartschool.tuitionpayment.common.exception;
+
+/**
+ * 自定义异常
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public class RRException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+	
+    private String msg;
+    private int code = 500;
+
+    public RRException(String msg) {
+		super(msg);
+		this.msg = msg;
+	}
+	
+	public RRException(String msg, Throwable e) {
+		super(msg, e);
+		this.msg = msg;
+	}
+	
+	public RRException(String msg, int code) {
+		super(msg);
+		this.msg = msg;
+		this.code = code;
+	}
+
+	public RRException(BizCodeEnume bizCodeEnume) {
+		super(bizCodeEnume.getMsg());
+		this.msg = bizCodeEnume.getMsg();
+		this.code = bizCodeEnume.getCode();
+	}
+
+	public RRException(BizCodeEnume bizCodeEnume, String msg) {
+		super(bizCodeEnume.getMsg());
+		this.msg = msg;
+		this.code = bizCodeEnume.getCode();
+	}
+	
+	public RRException(String msg, int code, Throwable e) {
+		super(msg, e);
+		this.msg = msg;
+		this.code = code;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	public int getCode() {
+		return code;
+	}
+
+	public void setCode(int code) {
+		this.code = code;
+	}
+	
+	
+}

+ 35 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/BaseResult.java

@@ -0,0 +1,35 @@
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @Author: codingliang
+ * @Description: 接口统一返回基类
+ * @Date: 2021-04-29 12:09
+ * @Version: V1.0
+ **/
+@Data
+public abstract class BaseResult<T> implements Serializable {
+
+    /**
+     * 接口调用结果标识
+     */
+    private boolean success = false;
+
+    /**
+     * 接口调用结果信息
+     */
+    private String message;
+
+    /**
+     * 接口调用业务码
+     */
+    private String code;
+
+    /**
+     * 接口调用返回数据
+     */
+    private T data;
+}

+ 47 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/CommonResult.java

@@ -0,0 +1,47 @@
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+import java.io.Serializable;
+
+/**
+ * @Author: codingliang
+ * @Description: 接口统一返回
+ * @Date: 2021-04-29 12:10
+ * @Version: V1.0
+ **/
+public class CommonResult<T> extends BaseResult implements Serializable {
+
+    private static final long serialVersionUID = 3616484754899974346L;
+
+    public static CommonResult ok() {
+        return ok("1", "执行成功");
+    }
+
+    public static <T> CommonResult<T> ok(String code, String msg) {
+        return baseCreate(code, msg, true);
+    }
+
+    public static CommonResult fail() {
+        return fail("-1", "执行失败");
+    }
+
+    public static CommonResult fail(String code, String msg) {
+        return baseCreate(code, msg, false);
+    }
+
+    private static <T> CommonResult<T> baseCreate(String code, String msg, boolean success) {
+        CommonResult result = new CommonResult();
+        result.setCode(code);
+        result.setSuccess(success);
+        result.setMessage(msg);
+        return result;
+    }
+
+    public CommonResult<T> setResult(T data) {
+        this.setData(data);
+        return this;
+    }
+
+    public T getData() {
+        return (T) super.getData();
+    }
+}

+ 127 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/Constant.java

@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+/**
+ * 常量
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public class Constant {
+	/** 超级管理员ID */
+	public static final int SUPER_ADMIN = 1;
+    /**
+     * 当前页码
+     */
+    public static final String PAGE = "page";
+    /**
+     * 每页显示记录数
+     */
+    public static final String LIMIT = "limit";
+    /**
+     * 排序字段
+     */
+    public static final String ORDER_FIELD = "sidx";
+    /**
+     * 排序方式
+     */
+    public static final String ORDER = "order";
+    /**
+     *  升序
+     */
+    public static final String ASC = "asc";
+	/**
+	 * 菜单类型
+	 * 
+	 * @author chenshun
+	 * @email sunlightcs@gmail.com
+	 * @date 2016年11月15日 下午1:24:29
+	 */
+    public enum MenuType {
+        /**
+         * 目录
+         */
+    	CATALOG(0),
+        /**
+         * 菜单
+         */
+        MENU(1),
+        /**
+         * 按钮
+         */
+        BUTTON(2);
+
+        private int value;
+
+        MenuType(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+    
+    /**
+     * 定时任务状态
+     * 
+     * @author chenshun
+     * @email sunlightcs@gmail.com
+     * @date 2016年12月3日 上午12:07:22
+     */
+    public enum ScheduleStatus {
+        /**
+         * 正常
+         */
+    	NORMAL(0),
+        /**
+         * 暂停
+         */
+    	PAUSE(1);
+
+        private int value;
+
+        ScheduleStatus(int value) {
+            this.value = value;
+        }
+        
+        public int getValue() {
+            return value;
+        }
+    }
+
+    /**
+     * 云服务商
+     */
+    public enum CloudService {
+        /**
+         * 七牛云
+         */
+        QINIU(1),
+        /**
+         * 阿里云
+         */
+        ALIYUN(2),
+        /**
+         * 腾讯云
+         */
+        QCLOUD(3);
+
+        private int value;
+
+        CloudService(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+}

+ 141 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/JwtOperator.java

@@ -0,0 +1,141 @@
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.Keys;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.SecretKey;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @Author: codingliang
+ * @Description: JWT操作类
+ * @Date: 2020-06-03 11:54
+ * @Version: V1.0
+ **/
+@Slf4j
+@RequiredArgsConstructor
+@Component
+public class JwtOperator {
+
+    /**
+     * 秘钥
+     * - 默认aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrsssttt
+     */
+    @Value("${jwt.secret:aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrsssttt}")
+    private String secret;
+
+    /**
+     * 有效期,单位秒
+     * - 默认2周
+     */
+    @Value("${jwt.expire-time-in-second:1209600}")
+    private Long expirationTimeInSecond;
+
+    /**
+     * 获取过期时间
+     * @return
+     */
+    public Long getExpirationTimeInSecond() {
+        return this.expirationTimeInSecond;
+    }
+
+    /**
+     * 从token中获取claim
+     *
+     * @param token token
+     * @return claim
+     */
+    public Claims getClaimsFromToken(String token) throws RRException {
+        try {
+            return Jwts.parser()
+                    .setSigningKey(this.secret.getBytes())
+                    .parseClaimsJws(token)
+                    .getBody();
+        } catch (Exception e) {
+            throw new RRException(BizCodeEnume.TOKET_INVALID);
+        }
+    }
+
+    /**
+     * 获取token中的信息
+     * @param token token
+     * @param name 属性名称
+     * @return
+     */
+    public Long getInfoFromToken(String token, String name) {
+        Claims claims = getClaimsFromToken(token);
+        return claims.get(name, Long.class);
+    }
+
+    /**
+     * 获取token的过期时间
+     *
+     * @param token token
+     * @return 过期时间
+     */
+    public Date getExpirationDateFromToken(String token) throws RRException {
+        return getClaimsFromToken(token)
+                .getExpiration();
+    }
+
+    /**
+     * 判断token是否过期
+     *
+     * @param token token
+     * @return 已过期返回true,未过期返回false
+     */
+    private Boolean isTokenExpired(String token) throws RRException {
+        Date expiration = getExpirationDateFromToken(token);
+        return expiration.before(new Date());
+    }
+
+    /**
+     * 计算token的过期时间
+     *
+     * @return 过期时间
+     */
+    private Date getExpirationTime() {
+        return new Date(System.currentTimeMillis() + getExpirationTimeInSecond() * 1000);
+    }
+
+    /**
+     * 为指定用户生成token
+     *
+     * @param claims 用户信息
+     * @return token
+     */
+    public String generateToken(Map<String, Object> claims) {
+        Date createdTime = new Date();
+        Date expirationTime = this.getExpirationTime();
+
+
+        byte[] keyBytes = secret.getBytes();
+        SecretKey key = Keys.hmacShaKeyFor(keyBytes);
+
+        return Jwts.builder()
+                .setClaims(claims)
+                .setIssuedAt(createdTime)
+                .setExpiration(expirationTime)
+                .signWith(key, SignatureAlgorithm.HS256)
+                .compact();
+    }
+
+    /**
+     * 判断token是否非法
+     *
+     * @param token token
+     * @return 未过期返回true,否则返回false
+     */
+    public Boolean validateToken(String token) throws RRException {
+        return !isTokenExpired(token);
+    }
+}

+ 55 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/MyQuery.java

@@ -0,0 +1,55 @@
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.chuanghai.smartschool.tuitionpayment.common.xss.SQLFilter;
+
+/**
+ * @Author: codingliang
+ * @Description: 分页参数设置
+ * @Date: 2021-04-29 12:51
+ * @Version: V1.0
+ **/
+public class MyQuery<T> {
+
+    public IPage<T> getPage(PageParam params) {
+        return this.getPage(params, null, false);
+    }
+
+    public IPage<T> getPage(PageParam params, String defaultOrderField, boolean isAsc) {
+
+        //分页对象
+        Page<T> page = new Page<>(params.getCurPage(), params.getPageSize());
+
+        //排序字段
+        //防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
+        String orderField = SQLFilter.sqlInject(params.getOrderField());
+        String order = params.getOrder();
+
+
+        //前端字段排序
+        if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){
+            if("asc".equalsIgnoreCase(order)) {
+                return  page.addOrder(OrderItem.asc(orderField));
+            }else {
+                return page.addOrder(OrderItem.desc(orderField));
+            }
+        }
+
+        // 没有排序字段,则不排序
+        if(StringUtils.isEmpty(defaultOrderField)){
+            return page;
+        }
+
+        //默认排序
+        if(isAsc) {
+            page.addOrder(OrderItem.asc(defaultOrderField));
+        }else {
+            page.addOrder(OrderItem.desc(defaultOrderField));
+        }
+
+        return page;
+    }
+}

+ 33 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/PageParam.java

@@ -0,0 +1,33 @@
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+import lombok.Data;
+
+/**
+ * @Author: codingliang
+ * @Description: 分页参数
+ * @Date: 2021-04-29 12:41
+ * @Version: V1.0
+ **/
+@Data
+public class PageParam {
+
+    /**
+     * 当前页
+     */
+    private Integer curPage = 1;
+
+    /**
+     * 每页大小
+     */
+    private Integer pageSize = 10;
+
+    /**
+     * 排序字段
+     */
+    private String orderField;
+
+    /**
+     * 排序方式,可选值:asc、desc
+     */
+    private String order;
+}

+ 101 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/utils/PageUtils.java

@@ -0,0 +1,101 @@
+package com.chuanghai.smartschool.tuitionpayment.common.utils;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分页工具类
+ * @author Mark sunlightcs@gmail.com
+ */
+public class PageUtils<T> implements Serializable {
+	private static final long serialVersionUID = 1L;
+	/**
+	 * 总记录数
+	 */
+	private int totalCount;
+	/**
+	 * 每页记录数
+	 */
+	private int pageSize;
+	/**
+	 * 总页数
+	 */
+	private int totalPage;
+	/**
+	 * 当前页数
+	 */
+	private int currPage;
+	/**
+	 * 列表数据
+	 */
+	private List<T> list;
+
+	/**
+	 * 分页
+	 * @param list        列表数据
+	 * @param totalCount  总记录数
+	 * @param pageSize    每页记录数
+	 * @param currPage    当前页数
+	 */
+	public PageUtils(List<T> list, int totalCount, int pageSize, int currPage) {
+		this.list = list;
+		this.totalCount = totalCount;
+		this.pageSize = pageSize;
+		this.currPage = currPage;
+		this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
+	}
+
+	/**
+	 * 分页
+	 */
+	public PageUtils(IPage<T> page) {
+		this.list = page.getRecords();
+		this.totalCount = (int)page.getTotal();
+		this.pageSize = (int)page.getSize();
+		this.currPage = (int)page.getCurrent();
+		this.totalPage = (int)page.getPages();
+	}
+
+	public int getTotalCount() {
+		return totalCount;
+	}
+
+	public void setTotalCount(int totalCount) {
+		this.totalCount = totalCount;
+	}
+
+	public int getPageSize() {
+		return pageSize;
+	}
+
+	public void setPageSize(int pageSize) {
+		this.pageSize = pageSize;
+	}
+
+	public int getTotalPage() {
+		return totalPage;
+	}
+
+	public void setTotalPage(int totalPage) {
+		this.totalPage = totalPage;
+	}
+
+	public int getCurrPage() {
+		return currPage;
+	}
+
+	public void setCurrPage(int currPage) {
+		this.currPage = currPage;
+	}
+
+	public List<?> getList() {
+		return list;
+	}
+
+	public void setList(List<T> list) {
+		this.list = list;
+	}
+	
+}

+ 51 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/common/xss/SQLFilter.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.chuanghai.smartschool.tuitionpayment.common.xss;
+
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import org.springframework.util.StringUtils;
+
+/**
+ * SQL过滤
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public class SQLFilter {
+
+    /**
+     * SQL注入过滤
+     * @param str  待验证的字符串
+     */
+    public static String sqlInject(String str){
+        if (StringUtils.hasText(str)) {
+            //去掉'|"|;|\字符
+            str = StringUtils.replace(str, "'", "");
+            str = StringUtils.replace(str, "\"", "");
+            str = StringUtils.replace(str, ";", "");
+            str = StringUtils.replace(str, "\\", "");
+
+            //转换成小写
+            str = str.toLowerCase();
+
+            //非法字符
+            String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};
+
+            //判断是否包含非法字符
+            for(String keyword : keywords){
+                if(str.indexOf(keyword) != -1){
+                    throw new RRException("包含非法字符");
+                }
+            }
+
+            return str;
+        } else {
+            return null;
+        }
+    }
+}

+ 25 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/config/CCBPayConfig.java

@@ -0,0 +1,25 @@
+package com.chuanghai.smartschool.tuitionpayment.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author: codingliang
+ * @Description: 建行支付配置
+ * @Date: 2021-08-03 17:57
+ * @Version: V1.0
+ **/
+@Configuration
+@ConfigurationProperties(prefix = "ccb")
+@Data
+public class CCBPayConfig {
+
+    private String merchantid;
+    private String posid;
+    private String branchid;
+    private String qupwd;
+    private String pubShort;
+    private String pub;
+    private String wxAppId;
+}

+ 31 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/config/CorsConfig.java

@@ -0,0 +1,31 @@
+package com.chuanghai.smartschool.tuitionpayment.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @Author: codingliang
+ * @Description: 解决跨域问题
+ * @Date: 2021-08-12 16:02
+ * @Version: V1.0
+ **/
+@Configuration
+public class CorsConfig {
+
+    @Bean
+    public WebMvcConfigurer corsConfigurer() {
+        return new WebMvcConfigurer() {
+            @Override
+            public void addCorsMappings(CorsRegistry registry) {
+                registry.addMapping("/**")
+                        .allowedMethods("*")
+                        .allowedOriginPatterns("*")
+                        .allowedHeaders("*")
+                        .allowCredentials(true)
+                        .maxAge(3600);
+            }
+        };
+    }
+}

+ 20 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/config/JXNXSPayConfig.java

@@ -0,0 +1,20 @@
+package com.chuanghai.smartschool.tuitionpayment.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author: codingliang
+ * @Description: 江西农商行支付配置
+ * @Date: 2021-08-18 10:55
+ * @Version: V1.0
+ **/
+@Configuration
+@ConfigurationProperties(prefix = "jxnxs")
+@Data
+public class JXNXSPayConfig {
+
+    private String openId;
+    private String openKey;
+}

+ 21 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/config/WechatConfig.java

@@ -0,0 +1,21 @@
+package com.chuanghai.smartschool.tuitionpayment.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author: codingliang
+ * @Description: 微信配置
+ * @Date: 2021-08-12 16:05
+ * @Version: V1.0
+ **/
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "wechat")
+public class WechatConfig {
+
+    private String appid;
+    private String secret;
+    private String fontendUrl;
+}

+ 22 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/config/WeixiaoConfig.java

@@ -0,0 +1,22 @@
+package com.chuanghai.smartschool.tuitionpayment.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author: codingliang
+ * @Description: 微校相关配置
+ * @Date: 2021-06-21 15:26
+ * @Version: V1.0
+ **/
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "weixiao")
+public class WeixiaoConfig {
+
+    private String appKey;
+    private String appSecret;
+    private String fontendUrl;
+
+}

+ 133 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/AdminInfoController.java

@@ -0,0 +1,133 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.entity.AdminInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.AdminInfoService;
+import com.chuanghai.smartschool.tuitionpayment.vo.UserTokenVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.util.StringUtils;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+/**
+ * 管理员
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@RestController
+@RequestMapping("tuitionpayment/admininfo")
+public class AdminInfoController {
+
+    @Autowired
+    private AdminInfoService adminInfoService;
+
+    /**
+     * 管理员登录
+     * @param userName 用户名
+     * @param password 密码
+     * @apiNote 测试管理员账号密码:admin/12345
+     * @return
+     */
+    @PostMapping("login")
+    public CommonResult<UserTokenVO> login(@RequestParam String userName,
+                                           @RequestParam String password) {
+        UserTokenVO tokenVO =  adminInfoService.login(userName, password);
+        return CommonResult.ok().setResult(tokenVO);
+    }
+
+    /**
+     * 管理员列表
+     * @param adminToken 管理员token
+     * @param pageParam 分页参数
+     * @return
+     */
+    @AdminLoginCheck
+    @GetMapping("/list")
+    public CommonResult<PageUtils<AdminInfoEntity>> list(@RequestHeader("admin_token") String adminToken,
+                                                         PageParam pageParam){
+        PageUtils page = adminInfoService.queryPage(pageParam);
+
+        return CommonResult.ok().setResult(page);
+    }
+
+    /**
+     * 新增管理员
+     * @param adminToken 管理员token
+     * @return
+     */
+    @AdminLoginCheck
+    @PostMapping("/save")
+    public CommonResult<String> save(@RequestHeader("admin-token") String adminToken,
+                                     @RequestBody @Valid AdminInfoEntity adminInfo,
+                                     BindingResult result){
+        if (result.hasErrors()) {
+            ObjectError error = result.getAllErrors().get(0);
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, error.getDefaultMessage());
+        }
+        String password = adminInfo.getPassword();
+        if (!StringUtils.hasText(password)) {
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, "密码不能为空");
+        }
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        adminInfo.setPassword(passwordEncoder.encode(password));
+        adminInfoService.save(adminInfo);
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * 修改管理员
+     * @param adminToken 管理员token
+     */
+    @AdminLoginCheck
+    @PutMapping("/update")
+    public CommonResult<String> update(@RequestHeader("admin-token") String adminToken,
+                                       @RequestBody @Valid AdminInfoEntity adminInfo,
+                                       BindingResult result){
+        if (result.hasErrors()) {
+            ObjectError error = result.getAllErrors().get(0);
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, error.getDefaultMessage());
+        }
+        adminInfo.setPassword(null);
+        adminInfoService.updateById(adminInfo);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 删除管理员
+     * @param adminToken 管理员token
+     * @param id 管理员id
+     */
+    @AdminLoginCheck
+    @DeleteMapping("/delete/{id}")
+    public CommonResult<String> delete(@RequestHeader("admin-token") String adminToken,
+                                       @PathVariable("id") Long id){
+        AdminInfoEntity adminInfoEntity = adminInfoService.getById(id);
+        if ("0".equals(adminInfoEntity.getStatus())) {
+            throw new RRException(BizCodeEnume.NO_PERMISSION);
+        }
+        adminInfoService.removeById(id);
+        return CommonResult.ok();
+    }
+
+}

+ 75 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/EnablePayLimitByGradeController.java

@@ -0,0 +1,75 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.entity.EnablePayLimitByGradeEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.EnablePayLimitByGradeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 年级可支付限制设置
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-20 10:02:41
+ * @since 0.1.1
+ */
+@RestController
+@RequestMapping("enablePayLimit")
+public class EnablePayLimitByGradeController {
+
+    @Autowired
+    private EnablePayLimitByGradeService enablePayLimitByGradeService;
+
+    /**
+     * 支付限制列表
+     * @param adminToken 管理员token
+     * @since 0.1.1
+     * @return
+     */
+    @GetMapping("list")
+    @AdminLoginCheck
+    public CommonResult<List<EnablePayLimitByGradeEntity>> list(@RequestHeader("admin_token") String adminToken) {
+        List<EnablePayLimitByGradeEntity> list = enablePayLimitByGradeService.list();
+        return CommonResult.ok().setResult(list);
+    }
+
+    /**
+     * 支付限制设置
+     * @param adminToken 管理员token
+     * @param id 设置id
+     * @param enablePay 是否能支付 1能、2不能
+     * @since 0.1.1
+     * @return
+     */
+    @PutMapping("setting/{settingId}/{enablePay}")
+    @AdminLoginCheck
+    public CommonResult<String> setting(@RequestHeader("admin_token") String adminToken,
+                                        @PathVariable("settingId") Long id,
+                                        @PathVariable("enablePay") String enablePay) {
+        if ("1".equals(enablePay) || "2".equals(enablePay)) {
+            EnablePayLimitByGradeEntity enablePayLimitByGradeEntity = enablePayLimitByGradeService.getById(id);
+            if (enablePayLimitByGradeEntity == null) {
+                throw new RRException(BizCodeEnume.ORDER_IS_NOT_EXIT, "支付限制设置不存在");
+            }
+
+            if (!enablePayLimitByGradeEntity.getEnablePay().equals(enablePay)) {
+                enablePayLimitByGradeEntity.setEnablePay(enablePay);
+                enablePayLimitByGradeService.updateById(enablePayLimitByGradeEntity);
+            }
+            return CommonResult.ok();
+        } else {
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, "enablePay字段只能为1或2");
+        }
+    }
+}

+ 184 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/FeedbackMsgController.java

@@ -0,0 +1,184 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.entity.FeedbackMsgEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.FeedbackMsgService;
+import com.chuanghai.smartschool.tuitionpayment.to.FeedbackMsgCreateTO;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.FeedbackMsgQueryVO;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.time.LocalDateTime;
+
+/**
+ * 反馈信息
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@RestController
+@RequestMapping("tuitionpayment/feedbackmsg")
+public class FeedbackMsgController {
+
+    @Autowired
+    private FeedbackMsgService feedbackMsgService;
+
+    /**
+     * 新增反馈信息
+     *
+     * @param cardNumber          当前登录者学号
+     * @param feedbackMsgCreateTO 反馈信息to
+     * @param result              数据校验异常绑定结果
+     * @return
+     */
+    @PostMapping("/save")
+    public CommonResult<String> save(@RequestHeader("card_number") String cardNumber,
+                                     @Valid @RequestBody FeedbackMsgCreateTO feedbackMsgCreateTO,
+                                     BindingResult result) {
+        if (result.hasErrors()) {
+            ObjectError error = result.getAllErrors().get(0);
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, error.getDefaultMessage());
+        }
+        feedbackMsgCreateTO.setFeedbackNoticeType("1");
+
+        feedbackMsgService.save(cardNumber, feedbackMsgCreateTO);
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * 反馈列表【当前用户】
+     *
+     * @param cardNumber
+     * @param pageParam
+     * @return
+     */
+    @GetMapping("/listOfCurrentUser")
+    public CommonResult<PageUtils<FeedbackMsgEntity>> listOfCurrentUser(@RequestHeader("card_number") String cardNumber,
+                                                                        PageParam pageParam) {
+        PageUtils page = feedbackMsgService.queryPage(cardNumber, pageParam);
+
+        return CommonResult.ok().setResult(page);
+    }
+
+    /**
+     * 反馈信息删除
+     *
+     * @param cardNumber 当前登录者学号
+     * @param id         反馈信息id
+     * @return
+     */
+    @DeleteMapping("/delete/{id}")
+    public CommonResult<String> delete(@RequestHeader("card_number") String cardNumber,
+                                       @PathVariable("id") Long id) {
+        FeedbackMsgEntity entity = feedbackMsgService.getById(id);
+        if (entity == null) {
+            throw new RRException(BizCodeEnume.DATA_IS_NOT_EXIST, "反馈信息不存在");
+        }
+
+        if (!entity.getFeedbackPersonIdentify().equals(cardNumber)) {
+            throw new RRException(BizCodeEnume.NO_PERMISSION);
+        }
+        feedbackMsgService.removeById(id);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 反馈列表【管理员】
+     * //    * @param adminToken 管理员token
+     *
+     * @return
+     * @apiNote 0.1.0新增keyword关键字查询
+     * @since 0.0.1
+     */
+    // @AdminLoginCheck
+//    @GetMapping("/list")
+//    public CommonResult<PageUtils<FeedbackMsgEntity>> listOfAdmin(//@RequestHeader("admin_token") String adminToken,
+//                                                                  String status,
+//                                                                  String keyword,
+//                                                                  PageParam pageParam){
+//        PageUtils page = feedbackMsgService.queryPageByStatus(status, keyword, pageParam);
+//
+//        return CommonResult.ok().setResult(page);
+//    }
+    // @AdminLoginCheck
+    @PostMapping("/list")
+    public CommonResult<PageUtils<FeedbackMsgEntity>> listOfAdmin( //@RequestHeader("admin_token") String adminToken,
+                                                                   @RequestBody JSONObject jsonObject) {
+        FeedbackMsgQueryVO feedbackMsgQueryVO = JSONObject.toJavaObject(jsonObject, FeedbackMsgQueryVO.class);
+        PageUtils page = feedbackMsgService.queryPageVO(feedbackMsgQueryVO);
+        return CommonResult.ok().setResult(page);
+    }
+
+    /**
+     * 反馈详细信息
+     *
+     * @param adminToken 管理员token
+     * @param id         反馈id
+     * @return
+     */
+    @AdminLoginCheck
+    @GetMapping("/info/{id}")
+    public CommonResult<FeedbackMsgEntity> info(@RequestHeader("admin_token") String adminToken,
+                                                @PathVariable("id") Long id) {
+        FeedbackMsgEntity feedbackMsg = feedbackMsgService.getById(id);
+
+        return CommonResult.ok().setResult(feedbackMsg);
+    }
+
+    /**
+     * 反馈信息处理
+     *
+     * @param id      反馈id
+     * @param content 反馈内容
+     * @return
+     * @apiNote 将反馈信息从未处理状态改变为已处理状态
+     */
+    @PutMapping("/info/{id}")
+    public CommonResult<String> handleFeedbackMsg(@PathVariable("id") Long id,
+                                                  @RequestParam("content") String content) {
+        FeedbackMsgEntity feedbackMsg = feedbackMsgService.getById(id);
+        feedbackMsg.setStatu("2");
+        feedbackMsg.setFeedbackDispose(content);
+        feedbackMsg.setHandleTime(LocalDateTime.now());
+        feedbackMsgService.updateById(feedbackMsg);
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * 下载完成缴费的学生名单
+     * <p>
+     * //  * @param adminToken 管理员token
+     *
+     * @param response
+     * @apiNote 0.1.0新增按照支付方式下载字段
+     */
+    @RequestMapping("downloadResultMsg")
+    public void downloadResultMsg(FeedbackMsgQueryVO feedbackMsgQueryVO,
+                                  HttpServletResponse response) throws IOException {
+
+        try {
+            feedbackMsgService.downloadResultMsg(response, feedbackMsgQueryVO);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+}

+ 119 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayController.java

@@ -0,0 +1,119 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.service.PayService;
+import com.chuanghai.smartschool.tuitionpayment.vo.WechatJsApiPayParamVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 支付接口
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Controller
+@RequestMapping({"pay","tuitionpayment/pay"})
+public class PayController {
+
+    @Autowired
+    private PayService payService;
+
+    /**
+     * 【建行】获取拉起微信支付的参数
+ //    * @param cardNumber 当前登录用户标识
+     * @param orderNo 订单号
+     * @param openId 支付者唯一标识
+     * @return
+     * @throws Exception
+     */
+    @ResponseBody
+    @GetMapping("ccb/getJsApiParam")
+    public CommonResult<WechatJsApiPayParamVO> getCCBJsApiParam( @RequestHeader("card_number")String cardNumber,
+                                                             @RequestParam String orderNo,
+                                                             @RequestParam String openId) {
+        WechatJsApiPayParamVO jsApiPayParam = payService.getCCBJsApiParam(openId, orderNo);
+        return CommonResult.ok().setResult(jsApiPayParam);
+    }
+
+    /**
+     * 【建行】支付结果异步通知
+     * @param request 请求原始数据
+     * @return
+     */
+    @ResponseBody
+    @PostMapping("ccb/notify")
+    public CommonResult<String> ccbNotify(HttpServletRequest request) {
+        payService.ccbNotify(request);
+
+        return CommonResult.ok().setResult("处理成功");
+    }
+
+    /**
+     * 【建行】支付成功回跳页面
+     * @param request
+     * @apiNote 支付成功后,建行服务器会调用该接口
+     *          该接口监听到建行回调后,会以【fontendUrl + pages/paySuccess/paySuccess?orderNo=123】的形式跳回到前端页面
+     *          <strong>注意:</strong>
+     *          fontendUrl + pages/paySuccess/paySuccess是前端支付成功之后的页面,需要前端开发人员与后台开发人员协调好
+     * @return
+     */
+    @GetMapping("ccb/success")
+    public String ccbSuccess(HttpServletRequest request) {
+        String url = payService.ccbSuccess(request);
+
+        return "redirect:" + url;
+    }
+
+    /**
+     * 【农商行】发起支付
+     * @since 0.1.0
+     * @apiNote 页面直接跳转链接【https://q.jxnxs.com/newpay?O=&out_no=&amount=&appoint_notify=】发起支付
+     *          O:固定传5494ec3310685daa218382619dd20e27
+     *          out_no:订单号,下单接口获取
+     *          amount:支付金额,单位元,下单接口获取
+     *          appoint_notify:异步通知地址,测试地址:http://7n9xr5.natappfree.cc/pay/jxnxs/notify、正式地址:https://jtishfw.ncjti.edu.cn/jiaofei/backendApi/pay/jxnxs/notify/
+     * @return
+     */
+    @GetMapping("spec001")
+    public String spec001() {
+        return "";
+    }
+
+    /**
+     * 【农商行】支付结果异步通知
+     * @param request
+     * @since 0.1.0
+     * @return
+     */
+    @ResponseBody
+    @GetMapping("jxnxs/notify")
+    public String jxnxsNotify(HttpServletRequest request) {
+        boolean isSuccess = payService.jxnxsNotify(request);
+        if (isSuccess) {
+            return "notify_success";
+        } else {
+            return "notify_fail";
+        }
+    }
+
+    /**
+     * 【农商行】支付成功跳转地址
+     * @param orderNo 订单号
+     * @since 0.1.0
+     * @return
+     */
+    @GetMapping("jxnxs/success")
+    public String jxnxsSuccess(@RequestParam("ord_no") String orderNo) {
+        String url = payService.jxnxsSuccess(orderNo);
+        return "redirect:" + url;
+    }
+}

+ 131 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayItemController.java

@@ -0,0 +1,131 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemService;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:36
+ * @Description: com.chuanghai.smartschool.tuitionpayment.controller
+ * @version: 1.0
+ */
+@RestController
+@RequestMapping("tuitionpayment/payitem")
+public class PayItemController {
+
+    @Autowired
+    private PayItemService payItemService;
+
+    /**
+     * 用于缴费项目的新增
+     *
+     * @param adminToken 管理员token
+     * @param jsonParam
+     * @return
+     */
+    @AdminLoginCheck
+    @PostMapping("/insertPayItem")
+    public CommonResult<PayItem> insertPayItem(@RequestHeader("admin_token") String adminToken,
+                                               @RequestBody JSONObject jsonParam) {
+        try {
+            PayItem payItem = JSONObject.toJavaObject(jsonParam, PayItem.class);
+            payItem.setItemAsk(Boolean.FALSE);
+            payItem.setItemExcept(Boolean.FALSE);
+            payItem.setItemAskDay("7");
+            payItem.setItemAskCount("2");
+            payItem.setRequestCount("0");
+            payItemService.saveOrUpdate(payItem);
+            return CommonResult.ok();
+        } catch (NullPointerException n) {
+            n.printStackTrace();
+        }
+        return CommonResult.fail();
+    }
+
+
+    /**
+     * 查询所有缴费项目
+     *
+     * @return
+     */
+    @PostMapping("/queryPayItem")
+    public CommonResult<PayItem> queryPayItem() {
+        try {
+            QueryWrapper<PayItem> wapper = new QueryWrapper<>();
+            wapper.eq("item_status", "1");
+            List<PayItem> payItemList = payItemService.list(wapper);
+            return CommonResult.ok().setResult(payItemList);
+        } catch (NullPointerException n) {
+            n.printStackTrace();
+        }
+        return CommonResult.fail();
+    }
+
+    /**
+     * 查询所有缴费项目
+     *
+     * @return
+     */
+    @PostMapping("/queryPayItemByName")
+    public String queryPayItemByName(String name) {
+        QueryWrapper<PayItem> wapper = new QueryWrapper<>();
+        wapper.eq("item_name", name);
+        List<PayItem> list = payItemService.list(wapper);
+        String itemAccount = "";
+        if (list.size() > 0) {
+            PayItem payItem = list.get(0);
+            itemAccount = payItem.getItemAccount();
+            String start = itemAccount.substring(0, 3);
+            String end = itemAccount.substring(itemAccount.length() - 4);
+            itemAccount = payItem.getItemBank() + " (" + start + "****" + end + ")";
+        }
+        return itemAccount;
+    }
+
+
+    /**
+     * 更新项目缴费配置
+     * adminToken  管理员token
+     *
+     * @param jsonObject 封装的缴费项目对象参数
+     * @return
+     */
+    @AdminLoginCheck
+    @PutMapping("/updatePayItem")
+    public CommonResult<T> updatePayItem(@RequestHeader("admin_token") String adminToken,
+                                         @RequestBody JSONObject jsonObject) {
+        PayItem payItem = JSONObject.toJavaObject(jsonObject, PayItem.class);
+        //将催缴发送请求计数器归零
+        payItem.setRequestCount("0");
+        boolean b = payItemService.updateById(payItem);
+        return CommonResult.ok().setResult(b);
+    }
+
+
+    /**
+     * 通过itemName 查询缴费项目的设置
+     *
+     * @param itemName   缴费项目名称
+     * @return
+     */
+    @GetMapping("/queryByItemNameSetting")
+    public CommonResult<PayItem> queryByItemNameSetting( @RequestParam("itemName") String itemName) {
+        QueryWrapper<PayItem> wrapper = new QueryWrapper<>();
+        wrapper.eq("item_name", itemName);
+        PayItem payItem = payItemService.getOne(wrapper);
+        return CommonResult.ok().setResult(payItem);
+    }
+
+
+
+
+}

+ 57 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayItemDetailController.java

@@ -0,0 +1,57 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItemDetail;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemDetailService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.util.List;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/29 星期三 16:47
+ * @Description: com.chuanghai.smartschool.tuitionpayment.controller
+ * @version: 1.0
+ */
+@RestController
+@RequestMapping("tuitionpayment/payItemDetail")
+public class PayItemDetailController {
+
+    @Autowired
+    private PayItemDetailService payItemDetailService;
+
+    /**
+     * 查询项目细节的信息
+     *
+     * @return
+     */
+    public String queryAllItemDetail(String detailNameStr) {
+        String[] split = detailNameStr.split("/");
+        //返回项目细节的编码
+        String code = "";
+        if (split.length > 0) {
+            for (int i = 0; i < split.length; i++) {
+                String[] splitDetail = split[i].split(":");
+                QueryWrapper<PayItemDetail> wrapper = new QueryWrapper<>();
+                wrapper.eq(StringUtils.hasText(splitDetail[0]), "detail_name", splitDetail[0]);
+                BigDecimal money = new BigDecimal(splitDetail[1]).setScale(2, RoundingMode.HALF_UP);
+                DecimalFormat decimalFormat = new DecimalFormat("###,###.00");
+                String formatMoney = decimalFormat.format(money);
+                PayItemDetail one = payItemDetailService.getOne(wrapper);
+                if (one != null) {
+                    code += one.getDetailCode()+":"+ formatMoney + "/";
+                }
+            }
+        }
+        if (code.length() > 0){
+            return  code.substring(0, code.length()-1);
+        }
+        return code;
+    }
+}

+ 94 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayMethodSettingController.java

@@ -0,0 +1,94 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.baomidou.mybatisplus.annotation.Version;
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayMethodSettingEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.PayMethodSettingService;
+import com.chuanghai.smartschool.tuitionpayment.vo.CurrentPayMethodVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 支付方式设置
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-17 15:52:41
+ * @since 0.1.0
+ */
+@RestController
+@RequestMapping("payMethodSetting")
+public class PayMethodSettingController {
+
+    @Autowired
+    private PayMethodSettingService payMethodSettingService;
+
+    /**
+     * 支付方式列表
+     *
+     * @param adminToken 管理员token
+     * @return
+     */
+    @AdminLoginCheck
+    @GetMapping("/list")
+    public CommonResult<List<PayMethodSettingEntity>> list(@RequestHeader("admin_token") String adminToken){
+        List<PayMethodSettingEntity> list = payMethodSettingService.list();
+        return CommonResult.ok().setResult(list);
+    }
+
+    /**
+     * 设置 payMethodId 为当前支付方式
+     *
+     * @param adminToken 管理员token
+     * @param payMethodId 支付方式id
+     * @return
+     */
+    @AdminLoginCheck
+    @PutMapping("{id}/currentPay")
+    public CommonResult<String> changeCurrentPayMethod(@RequestHeader("admin_token") String adminToken,
+                                                       @PathVariable("id") Long payMethodId) {
+        AtomicBoolean notHandle = new AtomicBoolean(true);
+        List<PayMethodSettingEntity> list = payMethodSettingService.list();
+        list.stream().forEach(payMethod -> {
+            if (payMethod.getId().longValue() == payMethodId.longValue()) {
+                payMethod.setIsCurrentPay("1");
+                notHandle.set(false);
+            } else {
+                payMethod.setIsCurrentPay("2");
+            }
+        });
+
+        if (notHandle.get()) {
+            throw new RRException(BizCodeEnume.DATA_IS_NOT_EXIST, "支付方式id不存在");
+        }
+
+        payMethodSettingService.updateBatchById(list);
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * 获取当前支付方式
+     *
+     * @return
+     */
+    @GetMapping("currentPay")
+    public CommonResult<CurrentPayMethodVO> getCurrentPayMethod() {
+        String currentPayMethod = payMethodSettingService.getCurrentPayMethod();
+        return CommonResult.ok().setResult(CurrentPayMethodVO
+                                                        .builder()
+                                                        .currentPayMethod(currentPayMethod)
+                                                        .build());
+    }
+}

+ 346 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayOrderController.java

@@ -0,0 +1,346 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayOrderService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoWaterService;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.*;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import net.sf.jsqlparser.statement.execute.Execute;
+import org.apache.poi.ss.formula.functions.T;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.xmlbeans.impl.xb.xsdschema.Public;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.configurationprocessor.json.JSONException;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 缴费订单
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@RestController
+@RequestMapping("tuitionpayment/payorder")
+public class PayOrderController {
+    @Autowired
+    private PayOrderService payOrderService;
+    @Autowired
+    private PayableInfoService payableInfoService;
+    @Autowired
+    private PayableInfoWaterService payableInfoWaterService;
+
+    @Autowired
+    private PayItemController payItemController;
+
+    /**
+     * 创建支付订单
+     *
+     * @param cardNumber 当前登录用户cardNumber
+     * @return
+     */
+    @PostMapping("/{studentNo}/create")
+    public CommonResult<CreateOrderResultVO> createPayOrder(@RequestHeader("card_number") String cardNumber,
+                                                            @RequestBody JSONObject jsonObject) {
+
+        PayOrderReceiveVO payOrderReceiveVO = JSONObject.toJavaObject(jsonObject, PayOrderReceiveVO.class);
+
+        CreateOrderResultVO resultVO = payOrderService.createOrder(cardNumber,payOrderReceiveVO);
+
+        return CommonResult.ok().setResult(resultVO);
+    }
+
+    /**
+     * 订单列表【当前用户】
+     *
+     * @param cardNumber 当前登录用户cardNumber
+     * @param status     订单状态  1 失败订单   2 成功订单
+     * @param pageParam  分页参数
+     * @return
+     */
+    @GetMapping("currentUserList")
+    public CommonResult<PageUtils<PayOrderEntity>> currentUserList(@RequestHeader("card_number") String cardNumber,
+                                                                   @RequestParam("status") String status,
+                                                                   PageParam pageParam) {
+        PageUtils page = payOrderService.queryPage(pageParam, cardNumber, status);
+
+        return CommonResult.ok().setResult(page);
+    }
+
+    /**
+     * 查询订单状态【用户端】
+     *
+     * @param cardNumber 当前登录用户cardNumber
+     * @param orderNo    订单号
+     * @return
+     */
+    @GetMapping("{orderNo}/orderStatu")
+    public CommonResult<OrderStatusVO> queryOrderStatus(@RequestHeader("card_number") String cardNumber,
+                                                        @PathVariable("orderNo") String orderNo) {
+        OrderStatusVO orderStatusVO = payOrderService.queryOrderStatus(cardNumber, orderNo);
+        return CommonResult.ok().setResult(orderStatusVO);
+    }
+
+    /**
+     * 订单列表【管理端】
+     * <p>
+     * //   * @param adminToken 管理员token
+     *
+     * @param queryTO   查询条件
+     * @param pageParam 分页参数
+     * @return
+     * @apiNote 0.1.0 新增按照支付方式查询
+     */
+    @AdminLoginCheck
+    @GetMapping("/list")
+    public CommonResult<PayOrderListVO> list(@RequestHeader("admin_token") String adminToken,
+                                             PayOrderQueryTO queryTO,
+                                             PageParam pageParam) {
+
+        String flag = queryTO.getFlag();
+        String createDateStr = queryTO.getCreateDateStr();
+        String payDateStr = queryTO.getPayDateStr();
+        if (!("1".equals(flag) || "2".equals(flag) || "3".equals(flag))) {
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, "flag只允许传1、2、3");
+        }
+        if (!"1".equals(flag)) {
+            if (!(StringUtils.hasText(payDateStr) || StringUtils.hasText(createDateStr))) {
+                throw new RRException(BizCodeEnume.PARAMETER_ERROR, "查询时间不能为空");
+            }
+        }
+        PageUtils page = payOrderService.queryPage(queryTO, pageParam);
+
+        page.getList().forEach(payOrder -> {
+            PayOrderEntity payOrderEntity = (PayOrderEntity) payOrder;
+            String payItem = payOrderEntity.getPayItem();
+            String payBank = payItemController.queryPayItemByName(payItem);
+            payOrderEntity.setPayBank(payBank);
+            this.payOrderService.updateById(payOrderEntity);
+
+        });
+
+        String amountCount = payOrderService.queryPayOrderAmount(queryTO);
+//        // 计算总金额
+//        BigDecimal bigDecimal = payOrderService.queryCurrentPayedAmount(queryTO);
+//        // 计算当前完成支付记录数量
+//        Integer recordNums = payOrderService.queryCurrentPayedRecordNum(queryTO);
+
+        PayOrderListVO payOrderListVO = new PayOrderListVO();
+        payOrderListVO.setTotal(new BigDecimal(amountCount.split("-")[0]).setScale(2, RoundingMode.HALF_UP));
+        payOrderListVO.setPage(page);
+        payOrderListVO.setRecordsNum(Integer.parseInt(amountCount.split("-")[1]));
+
+        return CommonResult.ok().setResult(payOrderListVO);
+    }
+
+
+    /**
+     * 查询所有项目的记录
+     *
+     * @return
+     */
+    @GetMapping("/queryAllAmount")
+    public CommonResult<T> queryAllItemNameAmount() {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("status", "2");
+        List<PayOrderEntity> orderlist = payOrderService.list(wrapper);
+        BigDecimal totalAmount = BigDecimal.ZERO;
+        if (orderlist.size() > 0) {
+            for (int i = 0; i < orderlist.size(); i++) {
+                totalAmount = totalAmount.add(orderlist.get(i).getRealPayAmount());
+            }
+        }
+        Integer totalCount = orderlist.size();
+        return CommonResult.ok().setResult(totalCount + "-" + totalAmount);
+    }
+
+    /**
+     * 查询相应项目的所有订单数及金额
+     *
+     * @param itemName 缴费项目
+     * @return
+     */
+    @GetMapping("/queryAmount")
+    public CommonResult<T> queryAmountByItemName(@RequestParam("itemName") String itemName) {
+        String s = payOrderService.queryAmount(itemName);
+        return CommonResult.ok().setResult(s);
+    }
+
+
+    /**
+     * 查询订单状态【管理端】
+     *
+     * @param orderNo 订单号
+     * @return
+     */
+    @GetMapping("queryOrderStatu")
+    public CommonResult<OrderStatusVO> queryOrderStatusByAdmin(@RequestHeader("admin_token") String adminToken,
+                                                               @RequestParam String orderNo) {
+        OrderStatusVO orderStatusVO = payOrderService.queryOrderStatus(orderNo);
+        return CommonResult.ok().setResult(orderStatusVO);
+    }
+
+
+    /**
+     * 下载缴费的学生名单
+     * <p>
+     *
+     * @param response
+     * @apiNote 0.1.0新增按照支付方式下载字段
+     */
+    @RequestMapping("downloadResult")
+    public void downloadResult(PayOrderQueryTO queryTO,
+                               HttpServletResponse response) throws IOException {
+        try {
+            String flag = queryTO.getFlag();
+            String createDateStr = queryTO.getCreateDateStr();
+            String payDateStr = queryTO.getPayDateStr();
+            if (!("1".equals(flag) || "2".equals(flag) || "3".equals(flag))) {
+                throw new RRException(BizCodeEnume.PARAMETER_ERROR, "flag只允许传1、2、3");
+            }
+            if (!"1".equals(flag)) {
+                if (!(StringUtils.hasText(payDateStr) || StringUtils.hasText(createDateStr))) {
+                    throw new RRException(BizCodeEnume.PARAMETER_ERROR, "查询时间不能为空");
+                }
+            }
+            payOrderService.downloadResult(response, queryTO);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * 下载缴费名单的txt
+     *
+     * @param queryTO  查询参数
+     * @param response
+     * @throws IOException
+     */
+    @RequestMapping("exportOrderTxt")
+    @AdminLoginCheck
+    public void exportTxt(@RequestHeader("admin_token") String adminToken,
+                          PayOrderQueryTO queryTO,
+                          HttpServletResponse response) throws IOException {
+        payOrderService.exportOrderTxt(response, queryTO);
+
+    }
+
+
+    /**
+     * 通过订单编号查询缴费订单详情
+     *
+     * @param orderNo 订单编号
+     * @return
+     */
+    @GetMapping("/queryOrderDetail")
+    public CommonResult<PayOrderEntity> queryPayOrderDetail(@RequestParam("orderNo") String orderNo) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StringUtils.hasText(orderNo), "order_no", orderNo);
+        PayOrderEntity one = payOrderService.getOne(wrapper);
+        return CommonResult.ok().setResult(one);
+    }
+
+
+    /**
+     * 根据父查看全部订单的详情
+     * @param orderNo
+     * @param pageParam
+     * @return
+     */
+    @GetMapping("/queryAllOrderByParent")
+    public CommonResult<PageUtils<PayOrderEntity>>  queryAllOrderByParent(@RequestParam("orderNo") String orderNo, PageParam pageParam){
+
+        PageUtils page = payOrderService.queryAllOrderByParent(orderNo, pageParam);
+
+        return CommonResult.ok().setResult(page);
+    }
+
+    @GetMapping("/updateOrderDetail")
+    public void updateOrderDetail(String orderNo){
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("order_no",orderNo);
+        PayOrderEntity payOrderEntity = this.payOrderService.getOne(wrapper);
+        String payItem = payOrderEntity.getPayItem();
+        BigDecimal notPayAmount = BigDecimal.ZERO;
+        BigDecimal payAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        if (payItem.equals("水费缴纳")){
+            QueryWrapper<PayableInfoWaterEntity> wrapper1 = new QueryWrapper<>();
+            wrapper1.eq("student_no",payOrderEntity.getPayForIdentify())
+                    .eq("student_name", payOrderEntity.getStudentName())
+                    .eq("pay_month", payOrderEntity.getPayYear());
+            PayableInfoWaterEntity payableInfoWaterEntity = payableInfoWaterService.getOne(wrapper1);
+            payOrderEntity.setRealPayAmount(payableInfoWaterEntity.getRealPayAmount());
+            payOrderEntity.setPayDetail(payableInfoWaterEntity.getPayAmountDetail());
+            payOrderEntity.setNowPayAmount(payableInfoWaterEntity.getRealPayAmount());
+        }else {
+            QueryWrapper<PayableInfoEntity> wrapper1 = new QueryWrapper<>();
+            wrapper1.eq("student_no",payOrderEntity.getPayForIdentify())
+                    .eq("student_name", payOrderEntity.getStudentName())
+                    .eq("years", payOrderEntity.getPayYear());
+            PayableInfoEntity payableInfoEntity = payableInfoService.getOne(wrapper1);
+            if (payableInfoEntity == null) {
+                throw new RRException(BizCodeEnume.DATA_IS_EXIST, "暂无该缴费订单。");
+            }
+
+            if (!payableInfoEntity.getNotPayDetail().isEmpty()) {
+                payOrderEntity.setNotPayDetail(payableInfoEntity.getNotPayDetail());
+                String[] notPayDetail = payableInfoEntity.getNotPayDetail().split("/");
+
+                for (int i=0; i< notPayDetail.length; i++) {
+                    notPayAmount = notPayAmount.add(new BigDecimal(notPayDetail[i].split(":")[1]));
+                }
+            }
+            if (!payableInfoEntity.getPayDetail().isEmpty()) {
+                payOrderEntity.setPayDetail(payableInfoEntity.getPayDetail());
+                String[] payDetail = payableInfoEntity.getPayDetail().split("/");
+                for (int i=0; i< payDetail.length; i++) {
+                    payAmount = payAmount.add(new BigDecimal(payDetail[i].split(":")[1]));
+                }
+            }
+
+        }
+
+
+
+
+        payOrderEntity.setRealPayAmount(payAmount.setScale(2, RoundingMode.HALF_UP));
+        System.out.println(payOrderEntity);
+        System.out.println( notPayAmount);
+    }
+
+}
+
+
+
+
+

+ 735 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayableInfoController.java

@@ -0,0 +1,735 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.listener.aliexcel.MyStudentNoImportListener;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemDetailService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayOrderService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoWaterService;
+import com.chuanghai.smartschool.tuitionpayment.to.DeletePayableInfoTO;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.utils.ListPageUtil;
+import com.chuanghai.smartschool.tuitionpayment.vo.*;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import jdk.nashorn.internal.scripts.JS;
+import org.apache.poi.ss.formula.functions.T;
+import org.ehcache.impl.internal.classes.commonslang.ArrayUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.multipart.MultipartFile;
+//import cn.afterturn.easypoi.excel.ExcelExportUtil;
+//import cn.afterturn.easypoi.excel.ExcelImportUtil;
+//import cn.afterturn.easypoi.excel.entity.ExportParams;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+/**
+ * 学生应缴数据
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@RestController
+@RequestMapping("tuitionpayment/payableinfo")
+public class PayableInfoController {
+
+    @Autowired
+    private PayableInfoService payableInfoService;
+    @Autowired
+    private PayableInfoWaterService payableInfoWaterService;
+    @Autowired
+    private PayOrderService payOrderService;
+    @Autowired
+    private PayItemDetailController payItemDetailController;
+    @Autowired
+    private WechatController wechatController;
+
+    /**
+     * 根据card_number获取缴费信息 整合各缴费项目的集合
+     *
+     * @param cardNumber 当前登录用户cardNumber
+     * @return
+     * @Param currPage  当前页
+     * @pageSize pageSize 每页记录数
+     */
+    @GetMapping("payableInfo")
+    public CommonResult<PayableInfoWaterListVO> getPayableInfoByCardNumber(@RequestHeader("card_number") String cardNumber, String studentName,
+                                                                           Integer currPage, Integer pageSize) {
+        currPage = currPage == null ? 1 : currPage;
+        pageSize = pageSize == null ? 10 : pageSize;
+        try {
+            List<PayableInfoEntity> payableInfo = payableInfoService.getPayableInfoByCardNumber(cardNumber, studentName);
+            List<PayableInfoWaterListVO> objectList = new ArrayList<>();
+            payableInfo.forEach(payable -> {
+                PayableInfoWaterListVO payableInfoWaterListVO = new PayableInfoWaterListVO();
+                BeanUtils.copyProperties(payable, payableInfoWaterListVO);
+                objectList.add(payableInfoWaterListVO);
+            });
+
+            List<PayableInfoWaterEntity> payableWater = payableInfoWaterService.getPayableInfoWaterByCardNumber(cardNumber, studentName);
+            payableWater.forEach(payableInfoWater -> {
+                PayableInfoWaterListVO payableInfoWaterListVO = new PayableInfoWaterListVO();
+                BeanUtils.copyProperties(payableInfoWater, payableInfoWaterListVO);
+                objectList.add(payableInfoWaterListVO);
+            });
+
+            //将得到的payableInfoWaterListVOs集合数据按照payCreateTime进行
+            List<PayableInfoWaterListVO> payableInfoWaterListVOs = objectList.stream().sorted(Comparator.comparing(PayableInfoWaterListVO::getPayCreateTime).reversed()).collect(Collectors.toList());
+            payableInfoWaterListVOs.forEach(payableInfoWaterListVO -> {
+                payableInfoWaterListVO.setPayerIdentify(payableInfoWaterListVO.getStudentNo());
+                payableInfoWaterListVO.setPayForIdentify(payableInfoWaterListVO.getCardNumber());
+                payableInfoWaterListVO.setPayYear(payableInfoWaterListVO.getYears());
+            });
+            //判断是否传入分页信息
+            if (currPage != null && pageSize != null) {
+                ListPageUtil<PayableInfoWaterListVO> listPageUtil = new ListPageUtil<PayableInfoWaterListVO>(payableInfoWaterListVOs, currPage, pageSize);
+                payableInfoWaterListVOs = listPageUtil.getPagedList();
+                int totalCount = listPageUtil.getTotalCount();
+                int pageSize1 = listPageUtil.getPageSize();
+                int nowPage1 = listPageUtil.getNowPage();
+                PageUtils<PayableInfoWaterListVO> page = new PageUtils<PayableInfoWaterListVO>(payableInfoWaterListVOs, totalCount, pageSize1, nowPage1);
+                return CommonResult.ok().setResult(page);
+            }
+        } catch (Exception e) {
+            return CommonResult.fail("0000", "该用户暂无缴费信息!");
+        }
+        return CommonResult.fail();
+    }
+//
+//    /**
+//     * 根据学号和学生姓名获取缴费信息
+//     *
+//     * @param cardNumber  当前登录用户cardNumber
+//     * @param studentNo   学号,新生可用身份证号码代替学号
+//     * @param studentName 学生姓名
+//     * @return
+//     */
+//    @GetMapping("payableInfo/{studentNo}/{studentName}")
+//    public CommonResult< List<PayableInfoEntity>> getPayableInfoByCardNumberAndName(@RequestHeader("card_number") String cardNumber,
+//                                                                                @PathVariable("studentNo") String studentNo,
+//                                                                                @PathVariable("studentName") String studentName) {
+//        List<PayableInfoEntity> info = payableInfoService.getPayableInfoByStudentNoAndName(studentNo, studentName);
+//        return CommonResult.ok().setResult(info);
+//    }
+
+    /**
+     * 学生应缴列表
+     *
+     * @param adminToken //     * @param keyword     搜索关键字
+     *                   //     * @param payStatus   订单状态
+     *                   //     * @param createTime  创建时间
+     *                   //     * @param payTime     支付时间
+     *                   //     * @param pageParam   分页参数
+     *                   //     * @param payItemType 缴费项目支付状态
+     *                   //     * @param itemName    缴费项目名
+     * @return
+     */
+    @AdminLoginCheck
+    @GetMapping("/list")
+    public CommonResult<PageUtils<PayableInfoEntity>> list(@RequestHeader("admin_token") String adminToken,
+//                                                           String keyword, String payStatus, String createTime,
+//                                                           String payTime, PageParam pageParam,
+//                                                           String payItemType,
+//                                                           @RequestParam("itemName") String itemName
+                                                           PayOrderQueryTO queryTO, PageParam pageParam) {
+        PageUtils page = null;
+        BigDecimal totalAmount = BigDecimal.ZERO;
+        int totalCount = 0;
+        if (queryTO.getItemName().equals("水费缴纳")) {
+            page = payableInfoWaterService.queryPage(queryTO, pageParam);
+            totalCount = page.getTotalCount();
+
+            List list = page.getList();
+            for (int i = 0; i < list.size(); i++) {
+                PayableInfoWaterEntity payableInfoWaterEntity = (PayableInfoWaterEntity) list.get(i);
+                totalAmount = totalAmount.add(payableInfoWaterEntity.getRealPayAmount());
+            }
+
+        } else {
+            page = payableInfoService.queryPage(queryTO, pageParam);
+            totalCount = page.getTotalCount();
+            List list = page.getList();
+            for (int i = 0; i < list.size(); i++) {
+                PayableInfoEntity payableInfoEntity = (PayableInfoEntity) list.get(i);
+                totalAmount = totalAmount.add(payableInfoEntity.getRealPayAmount());
+            }
+        }
+
+        PayableInfoListVO payableInfoListVO = new PayableInfoListVO();
+        payableInfoListVO.setPage(page);
+        payableInfoListVO.setTotalCount(totalCount);
+        payableInfoListVO.setTotalAmount(totalAmount);
+        //如果选择支付状态查询对应状态的金额
+        if (StringUtils.hasText(queryTO.getPayStatus())) {
+            String amount = payableInfoService.queryAmount(queryTO);
+            payableInfoListVO.setTotalCount(Integer.parseInt(amount.split("-")[1]));
+            payableInfoListVO.setTotalAmount(new BigDecimal(amount.split("-")[0]).setScale(2, RoundingMode.HALF_UP));
+        }
+        return CommonResult.ok().setResult(payableInfoListVO);
+    }
+
+    /**
+     * 下载缴费名单的txt
+     *
+     * @param queryTO  查询参数
+     * @param response
+     * @throws IOException
+     */
+    @RequestMapping("exportTxt")
+    //@AdminLoginCheck
+    public void exportTxt(PayOrderQueryTO queryTO,
+                          HttpServletResponse response) throws IOException {
+        if (queryTO.getItemName().equals("水费缴纳")) {
+            payableInfoWaterService.exportTxt(response, queryTO);
+        } else {
+            payableInfoService.exportTxt(response, queryTO);
+        }
+    }
+
+    /**
+     * 下载缴费的学生名单
+     *
+     * @param queryTO  封装参数
+     * @param response
+     * @throws IOException
+     */
+    @RequestMapping("downloadResult")
+    public void downloadResult(PayOrderQueryTO queryTO,
+                               HttpServletResponse response) throws IOException {
+
+        if (queryTO.getItemName().equals("水费缴纳")) {
+            payableInfoWaterService.downloadResult(response, queryTO);
+        } else {
+            payableInfoService.downloadResult(response, queryTO);
+        }
+
+    }
+
+    /**
+     * 学生应缴信息删除
+     *
+     * @param adminToken 管理员token
+     * @param ids        需要删除记录的id集合
+     * @return
+     */
+    @AdminLoginCheck
+    @DeleteMapping("/delete")
+    public CommonResult<String> delete(@RequestHeader("admin_token") String adminToken,
+                                       @RequestBody Long[] ids) {
+
+        payableInfoService.removeByIds(Arrays.asList(ids));
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * excel 导入学生学费相关原始数据
+     *
+     * @param adminToken 管理员token
+     * @param file       文件,文件格式注意需要符合要求
+     * @return
+     * @apiNote 导入学生学费相关原始数据
+     * <strong>注意:</strong>
+     * 1.需要提示用户上传的excel文件需要符合规定的格式;
+     * 2.上传新文件将会导致所有的旧数据被删除,学费缴纳开始后不建议再上传新数据。
+     */
+    @PostMapping("importByExcel")
+    @AdminLoginCheck
+    public CommonResult<String> importByExcel(@RequestHeader("admin_token") String adminToken,
+                                              @RequestParam MultipartFile file) throws IOException {
+        if (file.isEmpty()) {
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, "文件不能为空");
+        }
+        payableInfoService.importByExcel(file);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 更新缴费订单的时间参数
+     */
+    @PutMapping("updatePayInfo")
+    public CommonResult<T> updatePayInfo(String itemName) {
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("payMent_item", itemName);
+        //更新时间等参数
+        List<PayableInfoEntity> infoEntityList = payableInfoService.list(wrapper);
+
+        List<PayableInfoEntity> objectList = new ArrayList<>();
+        infoEntityList.forEach(payableInfoEntity -> {
+            String cardNumber = getCardNumberByIdCard(payableInfoEntity.getStudentNo(), null, null, null);
+            payableInfoEntity.setCardNumber(cardNumber);
+            payableInfoEntity.setPayCreateTime(LocalDateTime.now());
+            payableInfoEntity.setPayItemType("1");
+            payableInfoEntity.setPayNoticeType("1");
+
+            if (StringUtils.hasText(payableInfoEntity.getNotMustMoney())) {
+                payableInfoEntity.setNotPayDetail(payableInfoEntity.getMustMoney() + "/" + payableInfoEntity.getNotMustMoney());
+            } else {
+                payableInfoEntity.setNotPayDetail(payableInfoEntity.getMustMoney());
+            }
+            String[] split = payableInfoEntity.getNotPayDetail().split("/");
+            payableInfoEntity.setNotPaySize(split.length);
+            payableInfoEntity.setPayableAccount(payableInfoService.queryPayItemByName(payableInfoEntity.getPaymentItem()));
+            objectList.add(payableInfoEntity);
+        });
+        payableInfoService.updateBatchById(objectList);
+        return CommonResult.ok();
+    }
+
+
+    /**
+     * 通过身份证调用活动管理平台数据库换取 微笑的cardNumber信息
+     *
+     * @param idCard
+     * @return
+     */
+    public String getCardNumberByIdCard(String idCard, String inputType, String inputStr, String outPutType) {
+        //表示输入的参数为身份证
+        inputType = inputType == null ? "1" : inputType;
+        //输入的参数
+        inputStr = idCard;
+        // 返回微校的cardNumber
+        outPutType = outPutType == null ? "2" : outPutType;
+
+        String url = "https://chtech.ncjti.edu.cn/lamp/recordApi/consume/getUserInfo";
+        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
+        map.add("inputType", inputType);
+        map.add("inputStr", inputStr);
+        map.add("outPutType", outPutType);
+
+
+        RestTemplate restTemplate = new RestTemplate();
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
+        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
+        JSONObject jsonObj = JSON.parseObject(responseEntity.getBody());
+        String cardNumber = "";
+        try {
+            cardNumber = jsonObj.get("result").toString();
+        } catch (NullPointerException e) {
+            throw new NullPointerException("未匹配到该用户!");
+        }
+        return cardNumber == null ? idCard : cardNumber;
+    }
+
+
+    /**
+     * 删除缴费信息
+     *
+     * @param adminToken 管理员token
+     * @param file       文件
+     * @return
+     * @apiNote 删除缴费信息
+     * <strong>注意:</strong>
+     * 文件需要符合规定的格式
+     * 不会删除已经在线缴费的学生。如果有没有删除的学生,会在接口返回没有被删除学生的列表。
+     * @since 0.1.0
+     */
+    @PostMapping("/deletePayableExecl")
+    @AdminLoginCheck
+    public CommonResult<DeletePayableInfoTO> deletePayableInfo(@RequestHeader("admin_token") String adminToken,
+                                                               @RequestParam MultipartFile file) throws IOException {
+
+        if (file.isEmpty()) {
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, "文件不能为空");
+        }
+
+        MyStudentNoImportListener studentNoImportListener = new MyStudentNoImportListener();
+        EasyExcel.read(file.getInputStream(), StudentNoVO.class, studentNoImportListener).sheet().doRead();
+        List<StudentNoVO> studentNos = studentNoImportListener.getStudentNoList();
+
+        List<DeletePayableInfoTO> alreadyPayList = new ArrayList<>();
+        studentNos.forEach(studentNo -> {
+            StudentNoVO student = studentNo;
+            if (student.getPaymentItem().equals("水费缴纳")) {
+                QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+                wrapper.eq(student.getStudentNo() != null, "student_no", student.getStudentNo());
+                wrapper.eq(student.getPaymentItem() != null, "payment_item", student.getPaymentItem());
+
+                PayableInfoWaterEntity one = payableInfoWaterService.getOne(wrapper);
+                if (one != null) {
+                    boolean alreadyPay = payOrderService.isAlreadyPay(one.getStudentNo(), one.getPaymentItem(), one.getPayMonth(), null);
+                    if (alreadyPay) {
+                        DeletePayableInfoTO to = new DeletePayableInfoTO();
+                        BeanUtils.copyProperties(one, to);
+                        to.setMsg("学生已缴费,删除失败!");
+                        alreadyPayList.add(to);
+                    }
+                    payableInfoWaterService.removeById(one);
+                }
+            } else {
+                QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+                wrapper.eq(student.getStudentNo() != null, "student_no", student.getStudentNo());
+                wrapper.eq(student.getPaymentItem() != null, "payment_item", student.getPaymentItem());
+
+                PayableInfoEntity one = payableInfoService.getOne(wrapper);
+                if (one != null) {
+                    boolean alreadyPay = payOrderService.isAlreadyPay(one.getStudentNo(), one.getPaymentItem(), one.getYears(), one.getNotPaySize());
+                    if (alreadyPay) {
+                        DeletePayableInfoTO to = new DeletePayableInfoTO();
+                        BeanUtils.copyProperties(one, to);
+                        to.setMsg("学生已缴费,删除失败!");
+                        alreadyPayList.add(to);
+                    }
+                    payableInfoService.removeById(one);
+                }
+            }
+
+        });
+
+        return CommonResult.ok().setResult(alreadyPayList);
+    }
+
+
+    /**
+     * 查询缴费名单的缴费详情
+     *
+     * @param id
+     * @return
+     */
+//    @GetMapping("/queryPayInfoDetail")
+//    public CommonResult queryPayInfoDetail(@RequestParam String id, @RequestParam("itemName") String itemName, String realPayDetail) {
+//        PayInfoDetailVO payInfoDetailVO = new PayInfoDetailVO();
+//        if (itemName.equals("水费缴纳")) {
+//            QueryWrapper<PayableInfoWaterEntity> wrapperWater = new QueryWrapper<>();
+//            wrapperWater.eq("id", id)
+//                    .eq("payment_item", itemName);
+//            PayableInfoWaterEntity water = payableInfoWaterService.getOne(wrapperWater);
+//
+//            if (water.getPayAmountDetail() != null) {
+//                payInfoDetailVO.setPayAmountDetail(water.getPayAmountDetail());
+//            }
+//            payInfoDetailVO.setRealPayAmount(water.getRealPayAmount());
+//        } else {
+//            QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+//            wrapper.eq("id", id)
+//                    .eq("payment_item", itemName);
+//            PayableInfoEntity payableInfoEntity = payableInfoService.getOne(wrapper);
+//
+//            if (payableInfoEntity.getMustMoney() != null) {
+//                payInfoDetailVO.setMustMoney(payableInfoEntity.getMustMoney());
+//            }
+//            if (payableInfoEntity.getNotMustMoney() != null) {
+//                payInfoDetailVO.setNotMustMoney(payableInfoEntity.getNotMustMoney());
+//            }
+//            if (StringUtils.hasText(realPayDetail)){
+//
+//            }
+//            String[] realPayDetailStr = realPayDetail.split("/");
+//            BigDecimal realMount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+//            for (int i = 0; i < realPayDetailStr.length; i++) {
+//                String detail = realPayDetailStr[i];
+//                String[] detailAMount = detail.split(":");
+//                realMount = realMount.add(new BigDecimal(detailAMount[1]).setScale(2, RoundingMode.HALF_UP));
+//            }
+//            String notPayDetail = payableInfoEntity.getMustMoney() + "/" + payableInfoEntity.getNotMustMoney();
+//            payInfoDetailVO.setRealPayAmount(realMount);
+//
+//
+//            int notPayDetailCount = 0;
+//            String notPayDetailStr = "";
+//            String[] realPayDetailArray;
+//            String[] notPayDetailArray;
+//            ArrayList<String> listA;
+//            ArrayList<String> listB;
+//            if (StringUtils.hasText(payableInfoEntity.getPayDetail())) {
+//                payInfoDetailVO.setRealPayDetail(payableInfoEntity.getPayDetail() + "/" + realPayDetail);
+//            } else {
+//                payInfoDetailVO.setRealPayDetail(realPayDetail);
+//            }
+//            realPayDetailArray = payInfoDetailVO.getRealPayDetail().split("/");
+//            notPayDetailArray = notPayDetail.split("/");
+//            listA = new ArrayList<>(Arrays.asList(realPayDetailArray));
+//            listB = new ArrayList<>(Arrays.asList(notPayDetailArray));
+//            listB.removeAll(listA);
+//
+//            if (listB.size() == 1) {
+//                payInfoDetailVO.setNotPayDetail(listB.get(0));
+//                notPayDetailCount = 1;
+//            } else if (listB.size() > 1) {
+//                for (int i = 0; i < listB.size(); i++) {
+//                    notPayDetailStr += listB.get(i) + "/";
+//                    notPayDetailCount++;
+//                }
+//                payInfoDetailVO.setNotPayDetail(notPayDetailStr.substring(0, notPayDetailStr.length() - 1));
+//            } else {
+//                payInfoDetailVO.setNotPayDetail(notPayDetailStr);
+//            }
+//            payInfoDetailVO.setNotPaySize(notPayDetailCount);
+//
+//        }
+//
+//        return CommonResult.ok().setResult(payInfoDetailVO);
+//    }
+    @GetMapping("/queryPayInfoDetail")
+    public CommonResult queryPayInfoDetail(@RequestParam String id, @RequestParam("itemName") String itemName, String realPayDetail) {
+        PayInfoDetailVO payInfoDetailVO = new PayInfoDetailVO();
+        //未缴费明细金额
+        BigDecimal realMount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+
+        if (itemName.equals("水费缴纳")) {
+            QueryWrapper<PayableInfoWaterEntity> wrapperWater = new QueryWrapper<>();
+            wrapperWater.eq("id", id)
+                    .eq("payment_item", itemName);
+            PayableInfoWaterEntity water = payableInfoWaterService.getOne(wrapperWater);
+
+            if (water.getPayAmountDetail() != null) {
+                payInfoDetailVO.setPayAmountDetail(water.getPayAmountDetail());
+            }
+            payInfoDetailVO.setRealPayAmount(water.getRealPayAmount());
+            payInfoDetailVO.setNotPayDetailAmount(water.getRealPayAmount());
+        } else {
+            QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+            wrapper.eq("id", id)
+                    .eq("payment_item", itemName);
+            PayableInfoEntity payableInfoEntity = payableInfoService.getOne(wrapper);
+            if (payableInfoEntity == null) {
+                throw new RRException(BizCodeEnume.DATA_IS_EXIST, "该缴费订单不存在。");
+            }
+            if (payableInfoEntity.getMustMoney() != null) {
+                payInfoDetailVO.setMustMoney(payableInfoEntity.getMustMoney());
+            }
+            if (payableInfoEntity.getNotMustMoney() != null) {
+                payInfoDetailVO.setNotMustMoney(payableInfoEntity.getNotMustMoney());
+            }
+
+            String[] realPayDetailStr;
+            String realPayDetail1= "";
+            // 缴费订单的已缴费明细不为null
+            if (StringUtils.hasText(payableInfoEntity.getPayDetail())) {
+                if (StringUtils.hasText(realPayDetail)) {
+                    //缴费订单所有已交的项目明细
+                    realPayDetail1 = payableInfoEntity.getPayDetail() + "/" + realPayDetail;
+                } else {
+                    realPayDetail1 = payableInfoEntity.getPayDetail();
+                }
+            }
+            // 本次缴费明细不为空
+            if (StringUtils.hasText(realPayDetail)) {
+                //缴费订单所有已交的项目明细
+                if (StringUtils.hasText(payableInfoEntity.getPayDetail())) {
+                    realPayDetail1 = payableInfoEntity.getPayDetail() + "/" + realPayDetail;
+                }else {
+                    realPayDetail1 = realPayDetail;
+                }
+            }
+            // 本次缴费明细为空和缴费订单所有已交的项目明细为空
+//            if (StringUtils.hasText(realPayDetail) && StringUtils.hasText(payableInfoEntity.getPayDetail())) {
+//                System.out.println(realPayDetail1);
+//                realPayDetail1 =  realPayDetail1.substring(0,realPayDetail1.length()/2);
+//            }
+
+System.out.println(realPayDetail1);
+            String notPayDetail = "";
+            if (StringUtils.hasText(payableInfoEntity.getNotMustMoney())) {
+
+                notPayDetail = payableInfoEntity.getMustMoney() + "/" + payableInfoEntity.getNotMustMoney();
+            } else {
+                notPayDetail = payableInfoEntity.getMustMoney();
+            }
+
+            int notPayDetailCount = 0;
+            String notPayDetailStr = "";
+            String[] realPayDetailArray;
+            String[] notPayDetailArray;
+            ArrayList<String> listA;
+            ArrayList<String> listB;
+//            if (StringUtils.hasText(realPayDetail)) {
+//                if (StringUtils.hasText(payableInfoEntity.getPayDetail())) {
+//                    payInfoDetailVO.setRealPayDetail(payableInfoEntity.getPayDetail() + "/" + realPayDetail);
+//                } else {
+//                    payInfoDetailVO.setRealPayDetail(realPayDetail);
+//                }
+//            } else {
+//                if (StringUtils.hasText(payableInfoEntity.getPayDetail())) {
+//                    payInfoDetailVO.setRealPayDetail(payableInfoEntity.getPayDetail());
+//                } else {
+//                    payInfoDetailVO.setRealPayDetail(realPayDetail == null ? "" : realPayDetail);
+//                }
+//            }
+            payInfoDetailVO.setRealPayDetail(realPayDetail1);
+            realPayDetailArray = payInfoDetailVO.getRealPayDetail().split("/");
+            notPayDetailArray = notPayDetail.split("/");
+            listA = new ArrayList<>(Arrays.asList(realPayDetailArray));
+            String[] splitRealPayDetail = new String[listA.size()];
+            for (int j = 0; j < listA.size(); j++) {
+                splitRealPayDetail = listA.get(j).split("/");
+                String detail = splitRealPayDetail[0];
+                if (StringUtils.hasText(detail)) {
+                    String[] detailAMount = detail.split(":");
+                    realMount = realMount.add(new BigDecimal(detailAMount[1]).setScale(2, RoundingMode.HALF_UP));
+                }
+            }
+
+            listB = new ArrayList<>(Arrays.asList(notPayDetailArray));
+            listB.removeAll(listA);
+
+            if (listB.size() == 1) {
+                payInfoDetailVO.setNotPayDetail(listB.get(0));
+                notPayDetailCount = 1;
+            } else if (listB.size() > 1) {
+                for (int i = 0; i < listB.size(); i++) {
+                    notPayDetailStr += listB.get(i) + "/";
+                    notPayDetailCount++;
+                }
+                payInfoDetailVO.setNotPayDetail(notPayDetailStr.substring(0, notPayDetailStr.length() - 1));
+            } else {
+                payInfoDetailVO.setNotPayDetail(notPayDetailStr);
+            }
+            payInfoDetailVO.setNotPaySize(notPayDetailCount);
+
+
+            //已支付明细金额
+            payInfoDetailVO.setPayDetailAmount(realMount);
+            //订单总金额
+            payInfoDetailVO.setRealPayAmount(payableInfoEntity.getRealPayAmount().setScale(2, RoundingMode.HALF_UP));
+            // 未支付明细金额
+            payInfoDetailVO.setNotPayDetailAmount((payableInfoEntity.getRealPayAmount().subtract(realMount)).setScale(2, RoundingMode.HALF_UP));
+
+        }
+
+        return CommonResult.ok().setResult(payInfoDetailVO);
+    }
+
+//    /**
+//     * 查询缴费名单的缴费详情
+//     *
+//     * @param id
+//     * @return
+//     */
+//    @GetMapping("/queryPayDetail")
+//    public CommonResult<T> queryPayDetail(@RequestParam String id, @RequestParam("itemName") String
+//            itemName, String realPayDetail) {
+//        PayInfoDetailVO payInfoDetailVO = new PayInfoDetailVO();
+//        if (itemName.equals("水费缴纳")) {
+//            QueryWrapper<PayableInfoWaterEntity> wrapperWater = new QueryWrapper<>();
+//            wrapperWater.eq("id", id)
+//                    .eq("payment_item", itemName);
+//            PayableInfoWaterEntity water = payableInfoWaterService.getOne(wrapperWater);
+//
+//            if (water.getPayAmountDetail() != null) {
+//                payInfoDetailVO.setPayAmountDetail(water.getPayAmountDetail());
+//            }
+//            payInfoDetailVO.setRealPayAmount(water.getRealPayAmount());
+//        } else {
+//            QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+//            wrapper.eq("id", id)
+//                    .eq("payment_item", itemName);
+//            PayableInfoEntity payableInfoEntity = payableInfoService.getOne(wrapper);
+//
+//            payInfoDetailVO.setRealPayDetail(realPayDetail);
+//
+//            if (payableInfoEntity.getNotPayDetail() != null) {
+//                payInfoDetailVO.setNotPayDetail(payableInfoEntity.getNotPayDetail());
+//            }
+//            String detail = "";
+//            if (StringUtils.hasText(payableInfoEntity.getNotPayDetail())) {
+//                detail = payableInfoEntity.getNotPayDetail();
+//            }
+//
+//            String notPayDetail = "";
+//            if (StringUtils.hasText(realPayDetail)) {
+//                String[] realPayDetailArray = realPayDetail.split("/");
+//
+//                String[] payDetailArray = detail.split("/");
+//                ArrayList<String> listA = new ArrayList<>(Arrays.asList(realPayDetailArray));
+//                ArrayList<String> listB = new ArrayList<>(Arrays.asList(payDetailArray));
+//                listB.removeAll(listA);
+//                if (listB.size() == 1) {
+//                    payInfoDetailVO.setNotPayDetail(listB.get(0));
+//                } else if (listB.size() > 1) {
+//                    for (int i = 0; i < listB.size(); i++) {
+//                        notPayDetail += listB.get(i) + "/";
+//                    }
+//                    payInfoDetailVO.setNotPayDetail(notPayDetail.substring(0, notPayDetail.length() - 1));
+//                } else {
+//                    payInfoDetailVO.setNotPayDetail(notPayDetail);
+//                }
+//
+//            } else {
+//                detail = detail.endsWith("/") == true ? detail.substring(0, detail.length() - 1) : detail;
+//                payInfoDetailVO.setNotPayDetail(detail);
+//            }
+//
+//            String[] split = payInfoDetailVO.getNotPayDetail().split("/");
+//
+//            BigDecimal realMount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+//            for (int i = 0; i < split.length; i++) {
+//                String detail1 = split[i];
+//                String[] detailAMount = detail1.split(":");
+//                realMount = realMount.add(new BigDecimal(detailAMount[1]).setScale(2, RoundingMode.HALF_UP));
+//            }
+//            payInfoDetailVO.setRealPayAmount(realMount);
+//        }
+//
+//        return CommonResult.ok().setResult(payInfoDetailVO);
+//    }
+
+
+    /**
+     * 查询学生的基本信息
+     *
+     * @return
+     */
+    @GetMapping("/queryStudentInfo")
+    public CommonResult<PayableInfoStudentResultVO> queryStudentInfo(String cardNumber) {
+        PayableInfoStudentResultVO payableInfoStudentResultVO;
+
+        try {
+            String url = "https://chtech.ncjti.edu.cn/lamp/recordApi/consume/queryByIdCard";
+            MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
+            map.add("idCard", cardNumber);
+
+            RestTemplate restTemplate = new RestTemplate();
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+            HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
+            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
+            JSONObject jsonObj = JSON.parseObject(responseEntity.getBody());
+            JSONObject jsonResult = JSONObject.parseObject(jsonObj.get("result").toString());
+            payableInfoStudentResultVO = JSONObject.toJavaObject(jsonResult, PayableInfoStudentResultVO.class);
+
+        } catch (Exception e) {
+            return CommonResult.fail("0000", "信息获取失败!");
+        }
+
+        return CommonResult.ok().setResult(payableInfoStudentResultVO);
+    }
+}

+ 153 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/PayableInfoWaterController.java

@@ -0,0 +1,153 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.anno.AdminLoginCheck;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.listener.aliexcel.MyStudentNoImportListener;
+import com.chuanghai.smartschool.tuitionpayment.service.PayOrderService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoWaterService;
+import com.chuanghai.smartschool.tuitionpayment.to.DeletePayableInfoTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.StudentNoVO;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/28 星期二 15:30
+ * @Description: com.chuanghai.smartschool.tuitionpayment.controller
+ * @version: 1.0
+ */
+@RestController
+@RequestMapping("tuitionpayment/payableinfowater")
+public class PayableInfoWaterController {
+    @Autowired
+    private PayableInfoWaterService payableInfoWaterService;
+    @Autowired
+    private PayableInfoService payableInfoService;
+    @Autowired
+    private PayOrderService payOrderService;
+    @Autowired
+    private PayableInfoController payableInfoController;
+
+    /**
+     * excel 导入学生学费相关原始数据
+     *
+     * @param adminToken 管理员token
+     * @param file       文件,文件格式注意需要符合要求
+     * @return
+     * @apiNote 导入学生学费相关原始数据
+     * <strong>注意:</strong>
+     * 1.需要提示用户上传的excel文件需要符合规定的格式;
+     * 2.上传新文件将会导致所有的旧数据被删除,学费缴纳开始后不建议再上传新数据。
+     */
+    @PostMapping("importWaterByExcel")
+    @AdminLoginCheck
+    public CommonResult<String> importWaterByExcel(@RequestHeader("admin_token") String adminToken,
+                                              @RequestParam MultipartFile file) throws IOException {
+        if (file.isEmpty()) {
+            throw new RRException(BizCodeEnume.PARAMETER_ERROR, "文件不能为空");
+        }
+        payableInfoWaterService.importByExcel(file);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 更新缴费订单的时间参数
+     */
+    @PutMapping("updatePayInfoWater")
+    public CommonResult<T> updatePayInfoWater() {
+
+        //更新时间等参数
+        List<PayableInfoWaterEntity> InfoEntityList = payableInfoWaterService.list();
+        List<PayableInfoWaterEntity> objectList = new ArrayList<>();
+        InfoEntityList.forEach(payableInfoWaterEntity -> {
+            String cardNumber = payableInfoController.getCardNumberByIdCard(payableInfoWaterEntity.getStudentNo(),null,null,null);
+            payableInfoWaterEntity.setCardNumber(cardNumber);
+            payableInfoWaterEntity.setPayCreateTime(LocalDateTime.now());
+            payableInfoWaterEntity.setPayItemType("1");
+            payableInfoWaterEntity.setPayNoticeType("1");
+            payableInfoWaterEntity.setPayableAccount(payableInfoService.queryPayItemByName(payableInfoWaterEntity.getPaymentItem()));
+            objectList.add(payableInfoWaterEntity);
+        });
+        payableInfoWaterService.updateBatchById(objectList);
+        return CommonResult.ok();
+    }
+
+//    /**
+//     * 删除缴费信息
+//     *
+//     * @param adminToken 管理员token
+//     * @param file       文件
+//     * @return
+//     * @apiNote 删除缴费信息
+//     * <strong>注意:</strong>
+//     * 文件需要符合规定的格式
+//     * 不会删除已经在线缴费的学生。如果有没有删除的学生,会在接口返回没有被删除学生的列表。
+//     * @since 0.1.0
+//     */
+//    @DeleteMapping("/deletePayWaterExecl")
+//    @AdminLoginCheck
+//    public CommonResult<DeletePayableInfoTO> deletePayableInfo(@RequestHeader("admin_token") String adminToken,
+//                                                               @RequestParam MultipartFile file) throws IOException {
+//
+//        MyStudentNoImportListener studentNoImportListener = new MyStudentNoImportListener();
+//        EasyExcel.read(file.getInputStream(), StudentNoVO.class, studentNoImportListener).sheet().doRead();
+//        List<StudentNoVO> studentNos = studentNoImportListener.getStudentNoList();
+//
+//        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+//        wrapper.in(studentNos != null && studentNos.size() > 0, "student_no", studentNos);
+//        List<PayableInfoWaterEntity> list = payableInfoWaterService.list(wrapper);
+//
+//        List<DeletePayableInfoTO> alreadyPayList = new ArrayList<>();
+//
+//        List<Long> collect = list.stream().filter(payableInfo -> {
+//            boolean alreadyPay = payOrderService.isAlreadyPay(payableInfo.getStudentNo());
+//            if (alreadyPay) {
+//                DeletePayableInfoTO to = new DeletePayableInfoTO();
+//                BeanUtils.copyProperties(payableInfo, to);
+//                to.setMsg("学生已缴费,删除失败!");
+//                alreadyPayList.add(to);
+//            }
+//            return !alreadyPay;
+//        }).map(payableInfo -> payableInfo.getId())
+//                .collect(Collectors.toList());
+//
+//        if (collect.size() > 0) {
+//            payableInfoWaterService.removeByIds(collect);
+//        }
+//
+//        return CommonResult.ok().setResult(alreadyPayList);
+//    }
+
+
+    /**
+     * 根据card_number获取缴费信息
+     *
+     * @param cardNumber 当前登录用户cardNumber
+     * @return
+     */
+
+    public List<PayableInfoWaterEntity> getPayableInfoByCardNumber(@RequestHeader("card_number") String cardNumber,
+                                                                   String studentName) {
+        List<PayableInfoWaterEntity> payableInfoWaterByCardNumber = payableInfoWaterService.getPayableInfoWaterByCardNumber(cardNumber, studentName);
+        return payableInfoWaterByCardNumber;
+    }
+}

+ 54 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/TestController.java

@@ -0,0 +1,54 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @Author: codingliang
+ * @Description: TODO
+ * @Date: 2021-08-24 18:07
+ * @Version: V1.0
+ **/
+@RestController
+@RequestMapping("test")
+public class TestController {
+
+    @PostMapping("test1")
+    public String test(HttpServletRequest request) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        BufferedReader bufferedReader = null;
+        try {
+            InputStream inputStream = request.getInputStream();
+            if (inputStream != null) {
+                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+                char[] charBuffer = new char[128];
+                int bytesRead;
+                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+                    stringBuilder.append(charBuffer, 0, bytesRead);
+                }
+            }
+        } catch (IOException ex) {
+            throw ex;
+        } finally {
+            if (bufferedReader != null) {
+                try {
+                    bufferedReader.close();
+                } catch (IOException ex) {
+                    throw ex;
+                }
+            }
+        }
+        System.out.println("body:" + stringBuilder.toString());
+
+        return "code=1111";
+    }
+}

+ 404 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/controller/WechatController.java

@@ -0,0 +1,404 @@
+package com.chuanghai.smartschool.tuitionpayment.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.config.WechatConfig;
+import com.chuanghai.smartschool.tuitionpayment.config.WeixiaoConfig;
+import com.chuanghai.smartschool.tuitionpayment.entity.*;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayOrderService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoWaterService;
+import com.chuanghai.smartschool.tuitionpayment.vo.PayableInfoStudentResultVO;
+import com.chuanghai.smartschool.tuitionpayment.vo.WeixiaoVO;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 微信相关接口
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 16:04
+ */
+@Controller
+@RequestMapping("tuitionpayment/wechat")
+public class WechatController {
+
+    @Autowired
+    private WechatConfig wechatConfig;
+    @Autowired
+    private WeixiaoConfig weixiaoConfig;
+
+    /**
+     * 用于记录用户的access_token
+     */
+    private String accessTokenPublic = "OXRrZfi9Xx1271KACzUUWOCsOogvk6Jv";
+
+    /**
+     * 用于记录催缴的次数   计时器
+     */
+    private Integer askCount = 0;
+
+    @Autowired
+    private PayableInfoService payableInfoService;
+    @Autowired
+    private PayableInfoWaterService payableInfoWaterService;
+
+    @Autowired
+    private PayOrderService payOrderService;
+
+    @Autowired
+    private FeedbackMsgController feedbackMsgController;
+    @Autowired
+    private PayItemService payItemService;
+
+    /**
+     * 微信授权回调地址
+     *
+     * @param code 微信code
+     * @apiNote 用户跳转到微信授权链接上,微信服务器接收用户授权后会携带code回调到该接口上,该接口使用code获取到用户的openId信息。
+     * 如果openId获取成功,该接口会以 【fontendUrl + 路由地址 + ?openId=wx123456】 的形式跳回到前端应用页面;
+     * 如果openId获取失败,该接口会以 【fontendUrl + /error/?errorMsg=获取用户openId失败】 的形式跳回到前端应用页面。
+     * <strong>注意:</strong>
+     * fontendUrl + 路由地址:前端项目地址+页面路由地址,用于前端页面接收用户的信息或错误信息,该地址需要前端人员与后台开发人员协调好。
+     */
+    @GetMapping("pub/auth")
+    public String pubAuth(String code, String state) {
+
+        // code换取access_token
+        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
+                "appid=" + wechatConfig.getAppid() +
+                "&secret=" + wechatConfig.getSecret() +
+                "&code=" + code +
+                "&grant_type=authorization_code";
+
+        try {
+            RestTemplate restTemplate = new RestTemplate();
+            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); // 解决回参中文乱码
+            String response = restTemplate.getForObject(url, String.class);
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode jsonNode = mapper.readTree(response);
+            String openid = jsonNode.get("openid").asText();
+
+            // System.out.println("redirect:" + wechatConfig.getFontendUrl() + "/#/pages/Pay/pay/?openId=" + openid);
+            return "redirect:" + wechatConfig.getFontendUrl() + "/#/" + state + "/?openId=" + openid;
+        } catch (Exception e) {
+            return "redirect:" + wechatConfig.getFontendUrl() + "/error/?errorMsg=获取用户openId失败";
+        }
+    }
+
+    /**
+     * 微校授权回调地址
+     *
+     * @param wxcode 微校code
+     * @param state  透传数据
+     * @return
+     * @apiNote 用户跳转到微校授权链接上,微校服务器接收用户授权后会携带wxcode回调到该接口上,该接口使用wxcode获取到用户的信息。
+     * 如果用户信息获取成功,该接口会以 【fontendUrl + /?cardNumber=wx123456&name=测试用户】 的形式跳回到前端应用页面;
+     * 如果用户信息获取失败,该接口会以 【fontendUrl + /error/?errorMsg=获取用户信息失败】 的形式跳回到前端应用页面。
+     * <strong>注意:</strong>
+     * fontendUrl + 路由地址:前端项目地址+页面路由地址,用于前端页面接收用户的信息或错误信息,该地址需要前端人员与后台开发人员协调好。
+     * </p>
+     */
+    @GetMapping("weixiao/auth")
+    public String weixiaoAuth(String wxcode, String state) {
+        String tokenUrl = "https://open.wecard.qq.com/connect/oauth2/token";
+        Map<String, String> tokenParams = new HashMap<>();
+        tokenParams.put("wxcode", wxcode);
+        tokenParams.put("app_key", weixiaoConfig.getAppKey());
+        tokenParams.put("app_secret", weixiaoConfig.getAppSecret());
+        tokenParams.put("grant_type", "authorization_code");
+        tokenParams.put("redirect_uri", state); // 该地址需要与发起授权地址保持一直
+
+        try {
+            // wecode换取token
+            RestTemplate client = new RestTemplate();
+            ResponseEntity<String> tokenResponse = client.postForEntity(tokenUrl, tokenParams, String.class);
+
+            ObjectMapper mapper = new ObjectMapper();
+            Map<String, Object> jsonMap = mapper.readValue(tokenResponse.getBody(), new TypeReference<Map<String, Object>>() {
+            });
+            String accessToken = (String) jsonMap.get("access_token");
+            accessTokenPublic = accessToken;
+
+            // token换取用户信息
+            String userInfoUrl = "https://open.wecard.qq.com/connect/oauth/get-user-info";
+            Map<String, String> userInfoParam = new HashMap<>();
+            userInfoParam.put("access_token", accessToken);
+            ResponseEntity<String> userInfoResponse = client.postForEntity(userInfoUrl, userInfoParam, String.class);
+
+            Map<String, Object> userInfoMap = mapper.readValue(userInfoResponse.getBody(), new TypeReference<Map<String, Object>>() {
+            });
+            String cardNumber = userInfoMap.get("card_number").toString();
+            String encodeName = URLEncoder.encode(userInfoMap.get("name").toString(), "utf-8");
+
+            return "redirect:" + weixiaoConfig.getFontendUrl() + "/#/pages/blankIndex/blankIndex/?cardNumber=" + cardNumber + "&name=" + encodeName;
+        } catch (Exception e) {
+            return "redirect:" + weixiaoConfig.getFontendUrl() + "/#/error/";
+        }
+    }
+
+
+    public PayableInfoStudentResultVO queryStudent() {
+        PayableInfoStudentResultVO payableInfoStudentResultVO = new PayableInfoStudentResultVO();
+        try {
+            // token换取用户信息
+            RestTemplate client = new RestTemplate();
+            ObjectMapper mapper = new ObjectMapper();
+            String userInfoUrl = "https://open.wecard.qq.com/connect/oauth/get-user-info";
+            Map<String, String> userInfoParam = new HashMap<>();
+            userInfoParam.put("access_token", accessTokenPublic);
+            ResponseEntity<String> userInfoResponse = client.postForEntity(userInfoUrl, userInfoParam, String.class);
+
+            Map<String, Object> userInfoMap = mapper.readValue(userInfoResponse.getBody(), new TypeReference<Map<String, Object>>() {
+            });
+            String name = userInfoMap.get("name").toString();
+            String card_number = userInfoMap.get("card_number").toString();
+            String grade = userInfoMap.get("grade").toString();
+            grade = grade.substring(2, grade.length());
+            String clazz = userInfoMap.get("class").toString();
+            payableInfoStudentResultVO.setIdCard(card_number);
+            payableInfoStudentResultVO.setStudentName(name);
+            payableInfoStudentResultVO.setMajor(grade + clazz);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return payableInfoStudentResultVO;
+    }
+
+    /**
+     * 实现一键通知下发缴费订单功能
+     *
+     * @param itemName
+     * @return
+     */
+    @PostMapping("/oneKey")
+    @ResponseBody
+    public CommonResult<T> oneKey(String itemName) {
+        WeixiaoVO weixiaoVO = new WeixiaoVO();
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("pay_notice_type", "1")
+                .eq("payment_item", itemName);
+        List<PayableInfoEntity> payableInfoEntityList = payableInfoService.list(wrapper);
+
+        List<String> cardNumberList = new ArrayList<>();
+        if (payableInfoEntityList.size() > 0) {
+            payableInfoEntityList.forEach(payableInfoEntity -> {
+                payableInfoEntity.setPayNoticeType("2");
+                cardNumberList.add(payableInfoEntity.getCardNumber());
+                payableInfoService.updateById(payableInfoEntity);
+            });
+        }
+        weixiaoVO.setCardNumberList(cardNumberList);
+        weixiaoVO.setTitle(itemName + "缴纳通知");
+        weixiaoVO.setSender("财务办公室");
+        weixiaoVO.setContent("同学你好," + weixiaoVO.getTitle() + "缴费已经开始,请尽快查看缴费详情完成缴费,谢谢合作!");
+        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(weixiaoVO);
+        return notice(jsonObject);
+    }
+
+    /**
+     * @param jsonObject 封装了发送微校通知的参数信息
+     * @return
+     */
+    @PostMapping("weixiao/notice")
+    @ResponseBody
+    public CommonResult<T> notice(@RequestBody JSONObject jsonObject) {
+        WeixiaoVO weixiaoVO = JSONObject.toJavaObject(jsonObject, WeixiaoVO.class);
+
+        Map<String, String> param = new HashMap<>();
+        param.put("title", weixiaoVO.getTitle());
+        String s = JSON.parseArray(weixiaoVO.getCardNumberList().toString()).toJSONString();
+        param.put("cards", s);
+        param.put("content", weixiaoVO.getContent());
+        param.put("sender", weixiaoVO.getSender());
+        String url = "https://open.wecard.qq.com/cgi-bin/notice/send?access_token=" + accessTokenPublic;
+
+        RestTemplate restTemplate = new RestTemplate();
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        HttpEntity<Map<String, String>> request = new HttpEntity<>(param, headers);
+        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
+        return CommonResult.ok();
+    }
+
+
+    /**
+     * 缴费异常订单自动发送微校通知
+     * itemName 缴费项目
+     *
+     * @return
+     */
+    @ResponseBody
+    public CommonResult<T> sendException(String itemName) {
+        QueryWrapper<PayItem> wrapper1 = new QueryWrapper<>();
+        wrapper1.eq("item_name", itemName);
+        PayItem payItem = payItemService.getOne(wrapper1);
+        //查询微校通知数据  isSend 2 表示开启推送
+        if (payItem.getItemExcept()) {
+            QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+            wrapper.eq("status", "1");
+            wrapper.eq("except_type", "1");
+            wrapper.eq("pay_item", itemName);
+            List<PayOrderEntity> payOrderList = payOrderService.list(wrapper);
+            List<String> cardNumberList = new ArrayList<>();
+            WeixiaoVO weixiaoVO = new WeixiaoVO();
+            if (payOrderList.size() > 0) {
+                payOrderList.forEach(payOrderEntity -> {
+                    payOrderEntity.setExceptType("2");
+                    String cardNumber = payOrderEntity.getPayerIdentify();
+                    cardNumberList.add(cardNumber);
+                    weixiaoVO.setTitle(payOrderEntity.getPayItem() + "缴纳异常通知");
+                });
+            }
+            weixiaoVO.setCardNumberList(cardNumberList);
+            weixiaoVO.setContent("同学你好,你的" + weixiaoVO.getTitle() + "缴费订单异常缴费失败,请尽快查看缴费详情,并再次缴费。若为系统原因,请及时反馈!");
+            weixiaoVO.setSender("财务办公室");
+            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(weixiaoVO);
+            notice(jsonObject);
+            //更新订单异常推送的状态
+            payOrderService.updateBatchById(payOrderList);
+        }
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * 每天执行一次催缴
+     */
+//    @Scheduled(fixedDelay = 20000)
+    @Scheduled(cron = "0 0 15 * * ?")
+    public void autoTiming() {
+
+        List<PayItem> payItemList = payItemService.list();
+        for (int i = 0; i < payItemList.size(); i++) {
+            PayItem payItem = (PayItem) payItemList.get(i);
+            String itemName = payItem.getItemName();
+            Boolean itemAsk = payItem.getItemAsk();
+            Integer itemAskDay = Integer.parseInt(payItem.getItemAskDay());
+            //获取设置的请求次数
+            Integer itemAskCount = Integer.parseInt(payItem.getItemAskCount());
+            //获取本请求成功的次数
+            Integer count = Integer.parseInt(payItem.getRequestCount());
+            if (itemAsk) {
+                if ((count < itemAskCount) && (askCount % itemAskDay == 0)) {
+                    askPay(itemName);
+                    count += 1;
+                    payItem.setRequestCount(String.valueOf(count));
+                    payItemService.updateById(payItem);
+                }
+            }
+        }
+        //催缴计数器累加
+        askCount += 1;
+    }
+
+
+    /**
+     * 是否催缴,发送微校通知
+     *
+     * @return
+     */
+    public CommonResult<T> askPay(String itemName) {
+        QueryWrapper<PayItem> wrapper1 = new QueryWrapper<>();
+        wrapper1.eq("item_name", itemName);
+        PayItem payItem = payItemService.getOne(wrapper1);
+
+        if (!itemName.equals("水费缴纳")) {
+            WeixiaoVO weixiaoVO = new WeixiaoVO();
+            List<String> cardNumberList = new ArrayList<>();
+            //查询微校通知数据  isSend 2 表示开启推送
+            QueryWrapper<PayableInfoEntity> wapper = new QueryWrapper<>();
+            wapper.eq("pay_notice_type", "2")
+                    .eq("pay_item_type", "1")
+                    .eq("payment_item", itemName);
+            List<PayableInfoEntity> list = payableInfoService.list(wapper);
+            //催缴的人员编号
+            if (list.size() > 0) {
+                list.forEach(payableInfoEntity -> {
+                    String cardNumber = payableInfoEntity.getCardNumber();
+                    cardNumberList.add(cardNumber);
+                    weixiaoVO.setTitle(payableInfoEntity.getPaymentItem() + "缴纳通知");
+                });
+            }
+            weixiaoVO.setCardNumberList(cardNumberList);
+            weixiaoVO.setContent("同学你好," + itemName + "缴费详情已经下发,请尽快查看缴费项目并完成缴费,谢谢配合!");
+            weixiaoVO.setSender("财务办公室");
+            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(weixiaoVO);
+            return notice(jsonObject);
+        } else {
+            WeixiaoVO weixiaoVO = new WeixiaoVO();
+            List<String> cardNumberList = new ArrayList<>();
+            //查询微校通知数据  isSend 2 表示开启推送
+            QueryWrapper<PayableInfoWaterEntity> wapper1 = new QueryWrapper<>();
+            wapper1.eq("pay_notice_type", "2")
+                    .eq("pay_item_type", "1")
+                    .eq("payment_item", itemName);
+            List<PayableInfoWaterEntity> list1 = payableInfoWaterService.list(wapper1);
+            //催缴的人员编号
+            if (list1.size() > 0) {
+                list1.forEach(payableInfoEntity -> {
+                    String cardNumber = payableInfoEntity.getCardNumber();
+                    cardNumberList.add(cardNumber);
+                    weixiaoVO.setTitle(payableInfoEntity.getPaymentItem() + "缴纳通知");
+                });
+                weixiaoVO.setCardNumberList(cardNumberList);
+                weixiaoVO.setContent("同学你好," + itemName + "缴费详情已经下发,请尽快查看缴费项目并完成缴费,谢谢配合!");
+                weixiaoVO.setSender("财务办公室");
+                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(weixiaoVO);
+                return notice(jsonObject);
+            }
+
+        }
+
+        return CommonResult.ok();
+    }
+
+    /**
+     * 处理反馈后开启反馈通知功能
+     *
+     * @param cardNumber 反馈通知对象的微校账号 card_number
+     * @param content    处理内容
+     * @return
+     */
+    @GetMapping("/disposeSend")
+    @ResponseBody
+    public CommonResult<T> disposeSend(@RequestParam("cardNumber") String cardNumber,
+                                       @RequestParam("content") String content,
+                                       @RequestParam("id") Long id) {
+        List<String> cardNumberList = new ArrayList<>();
+        cardNumberList.add(cardNumber);
+        WeixiaoVO weixiaoVO = new WeixiaoVO();
+        weixiaoVO.setTitle("缴费反馈处理通知");
+        weixiaoVO.setCardNumberList(cardNumberList);
+        weixiaoVO.setContent(content);
+        weixiaoVO.setSender("财务办公室");
+        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(weixiaoVO);
+        feedbackMsgController.handleFeedbackMsg(id, content);
+        return notice(jsonObject);
+
+    }
+}
+

+ 44 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/conver/aliexcel/CustomPayMethodConverter.java

@@ -0,0 +1,44 @@
+package com.chuanghai.smartschool.tuitionpayment.conver.aliexcel;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.chuanghai.smartschool.tuitionpayment.enume.PayMethod;
+
+/**
+ * @Author: codingliang
+ * @Description: 支付方式转化器
+ * @Date: 2021-08-24 15:00
+ * @Version: V1.0
+ **/
+public class CustomPayMethodConverter implements Converter<String> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return String.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return cellData.getStringValue();
+    }
+
+    @Override
+    public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        String payMethod;
+        if (PayMethod.CCB_PAY.getCode().equals(value)) {
+            payMethod = PayMethod.CCB_PAY.getMsg();
+        } else if (PayMethod.JXNXS_PAY.getCode().equals(value)) {
+            payMethod = PayMethod.JXNXS_PAY.getMsg();
+        } else {
+            payMethod = "未知支付方式";
+        }
+        return new CellData<>(payMethod);
+    }
+}

+ 38 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/conver/aliexcel/LocalDateTimeConverter.java

@@ -0,0 +1,38 @@
+package com.chuanghai.smartschool.tuitionpayment.conver.aliexcel;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @Author: codingliang
+ * @Description: LocalDateTime 转发器
+ * @Date: 2021-08-13 12:38
+ * @Version: V1.0
+ **/
+public class LocalDateTimeConverter implements Converter<LocalDateTime> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return LocalDateTime.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+    }
+
+    @Override
+    public CellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return new CellData<>(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+    }
+}

+ 46 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/conver/aliexcel/MsgStatuConverter.java

@@ -0,0 +1,46 @@
+package com.chuanghai.smartschool.tuitionpayment.conver.aliexcel;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.chuanghai.smartschool.tuitionpayment.enume.FeedbackMsgStatus;
+import com.chuanghai.smartschool.tuitionpayment.enume.PayMethod;
+import com.chuanghai.smartschool.tuitionpayment.enume.FeedbackMsgStatus;
+
+/**
+ * @Author: codingliang
+ * @Description: 反馈状态转化器
+ * @Date: 2021-08-24 15:00
+ * @Version: V1.0
+ **/
+public class MsgStatuConverter implements Converter<String> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return String.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return cellData.getStringValue();
+    }
+
+    @Override
+    public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        String statu;
+        if (FeedbackMsgStatus.NON_HANDLE.getCode().equals(value)) {
+            statu = FeedbackMsgStatus.NON_HANDLE.getMsg();
+        } else if (FeedbackMsgStatus.ALREADY_HANDLE.getCode().equals(value)) {
+            statu = FeedbackMsgStatus.ALREADY_HANDLE.getMsg();
+        } else {
+            statu = "未知处理结果";
+        }
+        return new CellData<>(statu);
+    }
+}

+ 17 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/AdminInfoDao.java

@@ -0,0 +1,17 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.chuanghai.smartschool.tuitionpayment.entity.AdminInfoEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 管理员信息 
+ * 
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Mapper
+public interface AdminInfoDao extends BaseMapper<AdminInfoEntity> {
+	
+}

+ 16 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/EnablePayLimitByGradeDao.java

@@ -0,0 +1,16 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.EnablePayLimitByGradeEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 年级可支付限制
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Mapper
+public interface EnablePayLimitByGradeDao extends BaseMapper<EnablePayLimitByGradeEntity> {
+}

+ 17 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/FeedbackMsgDao.java

@@ -0,0 +1,17 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.chuanghai.smartschool.tuitionpayment.entity.FeedbackMsgEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 反馈信息表 
+ * 
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Mapper
+public interface FeedbackMsgDao extends BaseMapper<FeedbackMsgEntity> {
+	
+}

+ 15 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayItemDao.java

@@ -0,0 +1,15 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:29
+ * @Description: 缴费项目
+ * @version: 1.0
+ */
+@Mapper
+public interface PayItemDao extends BaseMapper<PayItem> {
+}

+ 16 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayItemDetailDao.java

@@ -0,0 +1,16 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItemDetail;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:29
+ * @Description: 缴费项目明细
+ * @version: 1.0
+ */
+@Mapper
+public interface PayItemDetailDao extends BaseMapper<PayItemDetail> {
+}

+ 9 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayMethodSettingDao.java

@@ -0,0 +1,9 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayMethodSettingEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface PayMethodSettingDao extends BaseMapper<PayMethodSettingEntity> {
+}

+ 17 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayOrderDao.java

@@ -0,0 +1,17 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 缴费订单 
+ * 
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Mapper
+public interface PayOrderDao extends BaseMapper<PayOrderEntity> {
+	
+}

+ 17 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayableInfoDao.java

@@ -0,0 +1,17 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 学生应缴数据 
+ * 
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Mapper
+public interface PayableInfoDao extends BaseMapper<PayableInfoEntity> {
+    void truncateTable();
+}

+ 18 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/dao/PayableInfoWaterDao.java

@@ -0,0 +1,18 @@
+package com.chuanghai.smartschool.tuitionpayment.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 学生应缴数据
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Mapper
+public interface PayableInfoWaterDao extends BaseMapper<PayableInfoWaterEntity> {
+
+}

+ 54 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/AdminInfoEntity.java

@@ -0,0 +1,54 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+/**
+ * 管理员信息 
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("admin_info")
+public class AdminInfoEntity implements Serializable {
+	private static final long serialVersionUID = -8936652337177903377L;
+
+	/**
+	 * 管理员id,新增时不用传
+	 */
+	@TableId
+	private Long id;
+	/**
+	 * 用户名
+	 */
+	@NotBlank(message = "用户名不能为空")
+	private String userName;
+	/**
+	 * 登录密码, 新增时不能为空
+	 */
+	@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+	private String password;
+	/**
+	 * 管理员类型 0超级管理员、1其他管理员
+	 */
+	@NotBlank(message = "用户类别不能为空")
+	@Pattern(regexp = "^[1-9]*$", message = "管理员类别不能为0")
+	private String adminType;
+	/**
+	 * 管理员状态 0冻结、1正常
+	 */
+	@NotBlank(message = "状态不能为空")
+	@Pattern(regexp = "^[0-1]*$", message = "状态只能为0或1")
+	private String status;
+
+}

+ 31 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/EnablePayLimitByGradeEntity.java

@@ -0,0 +1,31 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 年级可支付限制
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("enable_pay_limit_by_grade")
+public class EnablePayLimitByGradeEntity {
+
+    @TableId
+    private Long id;
+    /**
+     * 年级名称
+     */
+    private String gradeName;
+    /**
+     * 年级
+     */
+    private String grade;
+    /**
+     * 是否可支付 1能、2不能
+     */
+    private String enablePay;
+}

+ 105 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/FeedbackMsgEntity.java

@@ -0,0 +1,105 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+import com.chuanghai.smartschool.tuitionpayment.conver.aliexcel.CustomPayMethodConverter;
+import com.chuanghai.smartschool.tuitionpayment.conver.aliexcel.LocalDateTimeConverter;
+import com.chuanghai.smartschool.tuitionpayment.conver.aliexcel.MsgStatuConverter;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import net.sf.cglib.core.Local;
+
+/**
+ * 反馈信息表
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("feedback_msg")
+public class FeedbackMsgEntity implements Serializable {
+	private static final long serialVersionUID = 1540570041000020629L;
+
+	/**
+	 * id
+	 */
+	@TableId
+	@ExcelIgnore
+	private Long id;
+	/**
+	 * 反馈者身份标识 使用用户的card_number标识
+	 */
+	@ColumnWidth(30)
+	@ExcelProperty("身份证号")
+	private String feedbackPersonIdentify;
+	/**
+	 * 反馈者姓名
+	 */
+	@ColumnWidth(15)
+	@ExcelProperty("姓名")
+	private String feedbackPersonName;
+	/**
+	 * 反馈者电话
+	 */
+	@ExcelIgnore
+	private String feedbackPersonPhone;
+	/**
+	 * 反馈类别
+	 */
+//	@ColumnWidth(15)
+//	@ExcelProperty("反馈类别")
+//	private String feedbackType;
+	/**
+	 * 反馈问题
+	 */
+	@ColumnWidth(35)
+	@ExcelProperty("反馈问题")
+	private String feedbackInfo;
+	/**
+	 * 反馈状态 1未处理、2已处理
+	 */
+	@ColumnWidth(10)
+	@ExcelProperty(value = "反馈状态", converter= MsgStatuConverter.class)
+	private String statu;
+
+	/**
+	 * 反馈项目类别
+	 */
+	@ColumnWidth(15)
+	@ExcelProperty("反馈类别")
+	private String feedbackItemName;
+
+	/**
+	 * 反馈处理内容
+	 */
+	@ColumnWidth(35)
+	@ExcelProperty("反馈处理内容")
+	private String feedbackDispose;
+
+	/**
+	 * 反馈发布时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@ColumnWidth(35)
+	@ExcelProperty(value = "反馈发布时间", converter = LocalDateTimeConverter.class)
+	private LocalDateTime publishTime;
+
+	/**
+	 * 反馈处理时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@ColumnWidth(35)
+	@ExcelProperty(value = "反馈处理时间", converter = LocalDateTimeConverter.class)
+	private LocalDateTime handleTime;
+
+
+}

+ 65 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayItem.java

@@ -0,0 +1,65 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Arrays;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:22
+ * @Description: 用于操作财务缴费项目
+ * @version: 1.0
+ */
+@Data
+public class PayItem {
+    /**
+     * 项目编号
+     */
+    @TableId
+    private Integer itemId;
+    /**
+     * 项目名称
+     */
+    private String itemName;
+    /**
+     * 项目状态
+     */
+    private String itemStatus;
+    /**
+     * 项目缴费银行
+     */
+    private String itemBank;
+    /**
+     * 项目缴费账户
+     */
+    private String itemAccount;
+
+    /**
+     * 可缴费年级 [1,2,3,4,5]
+     */
+    private String itemGrade;
+    /**
+     * 项目是否催缴  true false
+     */
+    private Boolean itemAsk;
+    /**
+     * 异常订单是否发送推送   true  false
+     */
+    private Boolean itemExcept;
+    /**
+     * 催缴间隔天数
+     */
+    private String itemAskDay;
+    /**
+     * 催缴次数
+     */
+    private String itemAskCount;
+    /**
+     * 催缴请求次数
+     */
+    private String requestCount;
+
+
+}

+ 26 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayItemDetail.java

@@ -0,0 +1,26 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import lombok.Data;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/29 星期三 16:40
+ * @Description: 缴费明细类
+ * @version: 1.0
+ */
+@Data
+public class PayItemDetail {
+    /**
+     * 缴费明细ID
+     */
+    private Integer id;
+    /**
+     * 缴费明细名称
+     */
+    private String detailName;
+    /**
+     * 缴费明细比编码
+     */
+    private String detailCode;
+
+}

+ 46 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayMethodSettingEntity.java

@@ -0,0 +1,46 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 支付方式设置
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("pay_method_setting")
+public class PayMethodSettingEntity implements Serializable {
+
+    private static final long serialVersionUID = -6744523575143914281L;
+
+    /**
+     * 支付方式id
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 支付方式名称
+     */
+    private String payMethodName;
+
+    /**
+     * 支付方式 1建行支付、2农商行支付
+     */
+    private String payMethod;
+
+    /**
+     * 是否为当前支付方式 1是,2否
+     */
+    @JsonProperty("currentPay")
+    private String isCurrentPay;
+
+
+}

+ 183 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayOrderEntity.java

@@ -0,0 +1,183 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.chuanghai.smartschool.tuitionpayment.conver.aliexcel.CustomPayMethodConverter;
+import com.chuanghai.smartschool.tuitionpayment.conver.aliexcel.LocalDateTimeConverter;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 缴费订单
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("pay_order")
+public class PayOrderEntity implements Serializable {
+	private static final long serialVersionUID = -3368168683789891484L;
+
+	/**
+	 * id
+	 */
+	@TableId
+	@ExcelIgnore
+	private Long id;
+	/**
+	 * 订单号
+	 */
+	@ExcelProperty("订单号")
+	@ColumnWidth(25)
+	private String orderNo;
+	/**
+	 * 付款者id 付款人的card_number
+	 */
+	@ExcelIgnore
+	private String payerIdentify;
+	/**
+	 * 学生id 被付款人的card_number
+	 */
+	@ExcelProperty("学号")
+	@ColumnWidth(25)
+	private String payForIdentify;
+	/**
+	 * 学生姓名
+	 */
+	@ExcelProperty("姓名")
+	@ColumnWidth(15)
+	private String studentName;
+	/**
+	 * 学生班级名称
+	 */
+	@ExcelProperty("班级名称")
+	@ColumnWidth(15)
+	private String className;
+	/**
+	 * 订单应付金额
+	 */
+	@ExcelIgnore
+	private BigDecimal realPayAmount;
+	/**
+	 * 订单本次支付金额
+	 */
+	@ExcelProperty("支付金额")
+	@ColumnWidth(15)
+	private BigDecimal nowPayAmount;
+
+
+	/**
+	 * 记录二次支付的订单号
+	 */
+	@ExcelProperty("助学贷款金额")
+	@ColumnWidth(20)
+	private BigDecimal payOrderLoan;
+
+	/**
+	 * 订单状态 1未支付、2支付成功 3部分支付
+	 */
+	@ExcelIgnore
+	private String status;
+
+	/**
+	 * 支付方式 1建行支付、2农商行支付
+	 * @since 0.1.0
+	 */
+	@ExcelProperty(value = "支付方式", converter= CustomPayMethodConverter.class)
+	@ColumnWidth(15)
+	private String payMethod;
+
+	/**
+	 * 缴费项目
+	 */
+	@ExcelIgnore
+	private String payItem;
+
+	/**
+	 * 创建时间
+	 */
+	@ExcelIgnore
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private LocalDateTime createTime;
+	/**
+	 * 完成时间
+	 */
+	@ExcelProperty(value = "支付完成时间", converter = LocalDateTimeConverter.class)
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@ColumnWidth(25)
+	private LocalDateTime finishTime;
+
+	/**
+	 * 订单备注
+	 */
+	@ExcelProperty("订单备注")
+	@ColumnWidth(35)
+	private String orderNotice;
+
+	/**
+	 * 支付银行账户
+	 */
+	@ExcelProperty("支付银行账户")
+	@ColumnWidth(25)
+	private String payBank;
+
+	/**
+	 * 缴费年度
+	 */
+	@ExcelProperty("缴费时间")
+	@ColumnWidth(15)
+	private String payYear;
+
+	/**
+	 * 已缴费明细
+	 */
+	@ExcelProperty("缴费明细")
+	@ColumnWidth(45)
+	private String payDetail;
+
+	/**
+	 * 未缴费明细
+	 */
+	@ExcelIgnore
+	private String notPayDetail;
+
+	/**
+	 * 未缴费明细数量
+	 */
+	@ExcelIgnore
+	private Integer notPaySize;
+	/**
+	 * 记录父订单号
+	 */
+	@ExcelIgnore
+	private String parentOrder ;
+	/**
+	 * 是否为父订单  ture false
+	 */
+	@ExcelIgnore
+	private Boolean isParent ;
+
+	/**
+	 * 异常推送状态  1 未发送  2已发送
+	 */
+	@ExcelIgnore
+	private String exceptType ;
+
+
+	/**
+	 * 水费缴纳的宿舍
+	 */
+	@ExcelProperty("宿舍")
+	@ColumnWidth(15)
+	private String drom ;
+
+
+}

+ 170 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayableInfoEntity.java

@@ -0,0 +1,170 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.math.BigDecimal;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+/**
+ * 学生应缴数据
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("payable_info")
+public class PayableInfoEntity implements Serializable {
+	private static final long serialVersionUID = -8945955742877200423L;
+
+	/**
+	 * 应缴信息id
+	 */
+	@ExcelIgnore
+	@TableId
+	private Long id;
+	/**
+	 * 学号
+	 */
+	@ColumnWidth(25)
+	@ExcelProperty("身份证号")
+	private String studentNo;
+	/**
+	 * 姓名
+	 */
+	@ColumnWidth(15)
+	@ExcelProperty("姓名")
+	private String studentName;
+	/**
+	 * 年级
+	 */
+	@ColumnWidth(10)
+	@ExcelProperty("年级")
+	private String grade;
+	/**
+	 * 收费年度
+	 */
+	@ColumnWidth(15)
+	@ExcelProperty("收费年度")
+	private String years;
+	/**
+	 * 学院名称
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("学院名称")
+	private String collegeName;
+	/**
+	 * 专业名称
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("专业名称")
+	private String majorName;
+	/**
+	 * 班级名称
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("班级名称")
+	private String className;
+	/**
+	 * 应付金额
+	 */
+	@ColumnWidth(15)
+	@ExcelProperty("应付金额")
+	private BigDecimal realPayAmount;
+	/**
+	 * 必交费用 格式:教材费:1000\学费:18000\住宿费:1800
+	 */
+	@ColumnWidth(50)
+	@ExcelProperty("必交费用")
+	private String mustMoney;
+	/**
+	 * 非必交费用 格式:教学设备费:100.00\管理费:100.00
+	 */
+	@ColumnWidth(50)
+	@ExcelProperty("非必交费用")
+	private String notMustMoney;
+	/**
+	 * 备注
+	 */
+	@ColumnWidth(50)
+	@ExcelProperty("备注")
+	private String orderNotice;
+	/**
+	 * 校区
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("校区")
+	private String studentCampus;
+	/**
+	 * 缴费项目
+	 */
+	@ColumnWidth(15)
+	@ExcelProperty("缴费项目")
+	private String paymentItem;
+
+	/**
+	 * 订单状态    1 未支付  2已支付
+	 */
+	@ExcelIgnore
+	private String payItemType ;
+
+	/**
+	 * 缴费名单创建时间
+	 */
+	@ExcelIgnore
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private LocalDateTime payCreateTime;
+
+	/**
+	 * 缴费完成时间
+	 */
+	@ExcelIgnore
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private LocalDateTime payFinishTime;
+
+	/**
+	 * 支付银行账户
+	 */
+	@ColumnWidth(25)
+	@ExcelProperty("银行账户")
+	private String payableAccount ;
+
+	/**
+	 * 缴费通知状态   1 未通知   2 已通知
+	 */
+	@ExcelIgnore
+	private String payNoticeType ;
+
+	/**
+	 * 微校账号
+	 */
+	@ExcelIgnore
+	private String cardNumber ;
+	/**
+	 * 已缴费明细
+	 */
+	@ExcelIgnore
+	private String PayDetail ;
+	/**
+	 * 未缴费明细
+	 */
+	@ExcelIgnore
+	private String notPayDetail ;
+
+	/**
+	 * 未缴费明细数量
+	 */
+	@ExcelIgnore
+	private Integer notPaySize;
+
+}

+ 154 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/entity/PayableInfoWaterEntity.java

@@ -0,0 +1,154 @@
+package com.chuanghai.smartschool.tuitionpayment.entity;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 学生应缴数据水费
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+@Data
+@TableName("payable_info_water")
+public class PayableInfoWaterEntity implements Serializable {
+
+
+	/**
+	 * 应缴信息id
+	 */
+	@ExcelIgnore
+	@TableId
+	private Long id;
+	/**
+	 * 学号
+	 */
+	@ColumnWidth(35)
+	@ExcelProperty("身份证号")
+	private String studentNo;
+	/**
+	 * 姓名
+	 */
+	@ColumnWidth(10)
+	@ExcelProperty("姓名")
+	private String studentName;
+	/**
+	 * 年级
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("年级")
+	private String grade;
+	/**
+	 * 宿舍号
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("宿舍号")
+	private String dorm;
+	/**
+	 * 学院名称
+	 */
+	@ColumnWidth(30)
+	@ExcelProperty("学院名称")
+	private String collegeName;
+	/**
+	 * 专业名称
+	 */
+	@ColumnWidth(30)
+	@ExcelProperty("专业名称")
+	private String majorName;
+	/**
+	 * 班级名称
+	 */
+	@ColumnWidth(30)
+	@ExcelProperty("班级名称")
+	private String className;
+	/**
+	 * 应付金额
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("应付金额")
+	private BigDecimal realPayAmount;
+	/**
+	 * 必交费用 格式:教材费:1000\学费:18000\住宿费:1800
+	 */
+	@ColumnWidth(50)
+	@ExcelProperty("费用详情")
+	private String payAmountDetail;
+
+	/**
+	 * 备注
+	 */
+	@ColumnWidth(50)
+	@ExcelProperty("备注")
+	private String orderNotice;
+	/**
+	 * 校区
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("校区")
+	private String studentCampus;
+	/**
+	 * 缴费项目
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("缴费项目")
+	private String paymentItem;
+	/**
+	 * 缴费月度
+	 */
+	@ColumnWidth(20)
+	@ExcelProperty("缴费月度")
+	private String payMonth;
+
+
+
+	/**
+	 * 订单状态    1 未支付  2已支付
+	 */
+	@ExcelIgnore
+	private String payItemType ;
+
+	/**
+	 * 缴费名单创建时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@ExcelIgnore
+	private LocalDateTime payCreateTime;
+
+	/**
+	 * 缴费完成时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@ExcelIgnore
+	private LocalDateTime payFinishTime;
+
+	/**
+	 * 支付银行账户
+	 */
+	@ColumnWidth(35)
+	@ExcelProperty("银行账户")
+	private String payableAccount ;
+
+	/**
+	 * 缴费通知状态   1 未通知   2 已通知
+	 */
+	@ExcelIgnore
+	private String payNoticeType ;
+
+	/**
+	 * 微校账号
+	 */
+	@ExcelIgnore
+	private String cardNumber ;
+
+}

+ 21 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/enume/FeedbackMsgStatus.java

@@ -0,0 +1,21 @@
+package com.chuanghai.smartschool.tuitionpayment.enume;
+
+public enum  FeedbackMsgStatus {
+    ALREADY_HANDLE("2", "已处理"),
+    NON_HANDLE("1", "未处理");
+
+    private String code;
+    private String msg;
+    FeedbackMsgStatus(String code,String msg){
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 22 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/enume/PayMethod.java

@@ -0,0 +1,22 @@
+package com.chuanghai.smartschool.tuitionpayment.enume;
+
+public enum PayMethod {
+
+    CCB_PAY("1", "建行支付"),
+    JXNXS_PAY("2", "江西农商行支付");
+
+    private String code;
+    private String msg;
+    PayMethod(String code,String msg){
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 29 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/enume/PayStatus.java

@@ -0,0 +1,29 @@
+package com.chuanghai.smartschool.tuitionpayment.enume;
+
+/**
+ * @Author: codingliang
+ * @Description: 支付状态
+ * @Date: 2021-08-12 16:58
+ * @Version: V1.0
+ **/
+public enum PayStatus {
+
+    ALREADY_PAY("2", "已支付"),
+    PART_PAY("3","部分支付"),
+    NON_PAY("1", "未支付");
+
+    private String code;
+    private String msg;
+    PayStatus(String code,String msg){
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 74 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/listener/aliexcel/MyPayableInfoImportListener.java

@@ -0,0 +1,74 @@
+package com.chuanghai.smartschool.tuitionpayment.listener.aliexcel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoWaterService;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: codingliang
+ * @Description: 学生应缴数据导入
+ * @Date: 2021-08-13 11:46
+ * @Version: V1.0
+ **/
+public class MyPayableInfoImportListener extends AnalysisEventListener<PayableInfoEntity> {
+
+    private static final int BATCH_COUNT = 100;
+    private List<PayableInfoEntity> list = new ArrayList<>();
+    private PayableInfoService payableInfoService;
+
+    public MyPayableInfoImportListener(PayableInfoService payableInfoService) {
+        this.payableInfoService = payableInfoService;
+    }
+
+
+    @Transactional
+    @Override
+    public void invoke(PayableInfoEntity data, AnalysisContext context) {
+        list.add(data);
+        if (list.size() >= BATCH_COUNT) {
+            inertData();
+        }
+    }
+
+    @Transactional
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        inertData();
+    }
+
+    private void inertData() {
+        if (list.size() > 0) {
+            drop(list.get(0).getPaymentItem());
+        }
+        payableInfoService.saveBatch(list);
+
+        list.clear();
+    }
+
+    /**
+     *  清除之前的表数据
+     *
+     * @param itemName 缴费项目
+     */
+    public void drop(String itemName) {
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("payment_item", itemName);
+        List<PayableInfoEntity> infoEntityList = payableInfoService.list(wrapper);
+        if (infoEntityList.size() >0){
+            List<Long> idList = infoEntityList.stream().map(PayableInfoEntity::getId).collect(Collectors.toList());
+            payableInfoService.removeByIds(idList);
+        }
+
+    }
+
+
+
+}

+ 72 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/listener/aliexcel/MyPayableInfoWaterImportListener.java

@@ -0,0 +1,72 @@
+package com.chuanghai.smartschool.tuitionpayment.listener.aliexcel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoWaterService;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: codingliang
+ * @Description: 学生应缴数据导入
+ * @Date: 2021-08-13 11:46
+ * @Version: V1.0
+ **/
+public class MyPayableInfoWaterImportListener extends AnalysisEventListener<PayableInfoWaterEntity> {
+
+    private static final int BATCH_COUNT = 100;
+    private List<PayableInfoWaterEntity> list = new ArrayList<>();
+    private PayableInfoWaterService payableInfoWaterService;
+
+    public MyPayableInfoWaterImportListener(PayableInfoWaterService payableInfoWaterService) {
+        this.payableInfoWaterService = payableInfoWaterService;
+    }
+
+
+
+    @Transactional
+    @Override
+    public void invoke(PayableInfoWaterEntity data, AnalysisContext context) {
+        list.add(data);
+        if (list.size() >= BATCH_COUNT) {
+            inertData();
+        }
+    }
+
+    @Transactional
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        inertData();
+    }
+
+    private void inertData() {
+        if (list.size() > 0) {
+            drop(list.get(0).getPaymentItem());
+        }
+        payableInfoWaterService.saveBatch(list);
+        list.clear();
+    }
+
+    /**
+     *  清除之前的表数据
+     *
+     * @param itemName 缴费项目
+     */
+    public void drop(String itemName) {
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("payment_item", itemName);
+        List<PayableInfoWaterEntity> infoEntityList = payableInfoWaterService.list(wrapper);
+        if (infoEntityList.size() >0){
+            List<Long> idList = infoEntityList.stream().map(PayableInfoWaterEntity::getId).collect(Collectors.toList());
+            payableInfoWaterService.removeByIds(idList);
+        }
+
+    }
+}

+ 36 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/listener/aliexcel/MyStudentNoImportListener.java

@@ -0,0 +1,36 @@
+package com.chuanghai.smartschool.tuitionpayment.listener.aliexcel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.chuanghai.smartschool.tuitionpayment.to.DeletePayableInfoTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.StudentNoVO;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: codingliang
+ * @Description: 学生学号导入
+ * @Date: 2021-08-20 11:45
+ * @Version: V1.0
+ **/
+public class MyStudentNoImportListener extends AnalysisEventListener<StudentNoVO> {
+
+    @Getter
+    private List<StudentNoVO> studentNoList = new ArrayList<>();
+
+
+
+
+    @Override
+    public void invoke(StudentNoVO studentNo, AnalysisContext context) {
+        studentNoList.add(studentNo);
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+    }
+
+
+}

+ 22 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/AdminInfoService.java

@@ -0,0 +1,22 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.entity.AdminInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.vo.UserTokenVO;
+
+/**
+ * 管理员信息 
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+public interface AdminInfoService extends IService<AdminInfoEntity> {
+
+    PageUtils queryPage(PageParam pageParam);
+
+    UserTokenVO login(String userName, String password);
+}
+

+ 16 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/EnablePayLimitByGradeService.java

@@ -0,0 +1,16 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.entity.EnablePayLimitByGradeEntity;
+
+/**
+ * 年级可支付限制
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+public interface EnablePayLimitByGradeService extends IService<EnablePayLimitByGradeEntity> {
+
+    boolean getCurrentGradeEnablePay(Integer grade);
+}

+ 33 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/FeedbackMsgService.java

@@ -0,0 +1,33 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.entity.FeedbackMsgEntity;
+import com.chuanghai.smartschool.tuitionpayment.to.FeedbackMsgCreateTO;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.FeedbackMsgQueryVO;
+import com.sun.deploy.nativesandbox.comm.Response;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 反馈信息表
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+public interface FeedbackMsgService extends IService<FeedbackMsgEntity> {
+
+    PageUtils queryPageByStatus(String status, String keyword, PageParam pageParam);
+    PageUtils queryPageVO(FeedbackMsgQueryVO feedbackMsgQueryVO);
+
+    PageUtils queryPage(String cardNumber, PageParam pageParam);
+
+    void save(String cardNumber, FeedbackMsgCreateTO feedbackMsgCreateTO);
+
+    void downloadResultMsg(HttpServletResponse response, FeedbackMsgQueryVO feedbackMsgQueryVO)throws IOException;
+}
+

+ 14 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayItemDetailService.java

@@ -0,0 +1,14 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItemDetail;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:30
+ * @Description: com.chuanghai.smartschool.tuitionpayment.service
+ * @version: 1.0
+ */
+public interface PayItemDetailService extends IService<PayItemDetail> {
+}

+ 13 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayItemService.java

@@ -0,0 +1,13 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:30
+ * @Description: com.chuanghai.smartschool.tuitionpayment.service
+ * @version: 1.0
+ */
+public interface PayItemService extends IService<PayItem> {
+}

+ 9 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayMethodSettingService.java

@@ -0,0 +1,9 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayMethodSettingEntity;
+
+public interface PayMethodSettingService extends IService<PayMethodSettingEntity> {
+
+    String getCurrentPayMethod();
+}

+ 60 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayOrderService.java

@@ -0,0 +1,60 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.CreateOrderResultVO;
+import com.chuanghai.smartschool.tuitionpayment.vo.OrderStatusVO;
+import com.chuanghai.smartschool.tuitionpayment.vo.PayOrderReceiveVO;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 缴费订单
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+public interface PayOrderService extends IService<PayOrderEntity> {
+
+    PageUtils queryPage(PayOrderQueryTO queryTO, PageParam pageParam);
+    String queryPayOrderAmount(PayOrderQueryTO queryTO);
+    PageUtils queryOrderPage(String keyword, String createTime, PageParam pageParam);
+
+    PageUtils queryPage(PageParam pageParam, String cardNumber, String status);
+
+    String queryAmount(String itemName);
+
+    /**
+     * 获取用户是否缴费
+     * @param studentNo 学号
+     * @return
+     */
+    boolean isAlreadyPay(String studentNo, String itemName, String payYears, Integer notPaySize);
+
+    CreateOrderResultVO createOrder(String cardNumber, PayOrderReceiveVO payOrderReceiveVO);
+
+    PayOrderEntity getByOrderNo(String orderNo);
+
+    OrderStatusVO queryOrderStatus(String cardNumber, String orderNo);
+
+    OrderStatusVO queryOrderStatus(String orderNo);
+
+    OrderStatusVO queryOrderStatus(PayOrderEntity payOrder);
+
+    BigDecimal queryCurrentPayedAmount(PayOrderQueryTO queryTO);
+
+    void downloadResult(HttpServletResponse response,PayOrderQueryTO queryTO) throws IOException;
+
+    void exportOrderTxt(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException;
+
+    Integer queryCurrentPayedRecordNum(PayOrderQueryTO queryTO);
+
+    PageUtils queryAllOrderByParent(String orderNo, PageParam pageParam);
+}
+

+ 23 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayService.java

@@ -0,0 +1,23 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.chuanghai.smartschool.tuitionpayment.vo.WechatJsApiPayParamVO;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+public interface PayService {
+
+    WechatJsApiPayParamVO getCCBJsApiParam(String openId, String orderNo);
+
+    void ccbNotify(HttpServletRequest request);
+
+    Map<String, String> queryCCBOrderStatus(String orderNo);
+
+    String ccbSuccess(HttpServletRequest request);
+
+    boolean jxnxsNotify(HttpServletRequest request);
+
+    String jxnxsSuccess(String orderNo);
+
+    Map<String, String> queryJXNXSOrderStatus(String orderNo);
+}

+ 44 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayableInfoService.java

@@ -0,0 +1,44 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.StudentPayableInfoVO;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 学生应缴数据
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+public interface PayableInfoService extends IService<PayableInfoEntity> {
+
+    PageUtils queryPage(PayOrderQueryTO queryTO, PageParam pageParam);
+    String queryAmount( PayOrderQueryTO queryTO);
+   // PageUtils queryPage(PayOrderQueryTO queryTO, PageParam pageParam);
+
+    String queryPayItemByName(String itemName);
+
+    List<PayableInfoEntity> getPayableInfoByCardNumber(String cardNumber, String studentName);
+
+  //  List<PayableInfoEntity> getPayableInfoByStudentNoAndName(String studentNo, String studentName);
+
+    PayableInfoEntity getByStudentNo(String studentNo ,String itemName, String payYears);
+
+    void importByExcel(MultipartFile file) throws IOException;
+
+    void downloadResult(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException;
+    void truncateTable();
+    void exportTxt(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException;
+
+}
+

+ 40 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/PayableInfoWaterService.java

@@ -0,0 +1,40 @@
+package com.chuanghai.smartschool.tuitionpayment.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.StudentPayableInfoVO;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 学生应缴数据
+ *
+ * @author codingliang
+ * @email codingliang@gmail.com
+ * @date 2021-08-12 15:52:41
+ */
+public interface PayableInfoWaterService extends IService<PayableInfoWaterEntity> {
+
+    void importByExcel(MultipartFile file) throws IOException;
+
+    PageUtils queryPage(PayOrderQueryTO queryTO,PageParam pageParam);
+
+    String queryAmount(String itemName, String payItemType, String keyword,  String payStatus, String createTime, String payTime);
+
+    void downloadResult(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException;
+
+    void exportTxt(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException;
+
+    List<PayableInfoWaterEntity> getPayableInfoWaterByCardNumber(String cardNumber, String studentName);
+
+    PayableInfoWaterEntity getByStudentNo(String studentNo,String itemName,String payYear);
+
+}
+

+ 68 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/AdminInfoServiceImpl.java

@@ -0,0 +1,68 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.JwtOperator;
+import com.chuanghai.smartschool.tuitionpayment.vo.UserTokenVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.MyQuery;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+
+import com.chuanghai.smartschool.tuitionpayment.dao.AdminInfoDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.AdminInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.AdminInfoService;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.HashMap;
+import java.util.Map;
+
+
+@Service("adminInfoService")
+public class AdminInfoServiceImpl extends ServiceImpl<AdminInfoDao, AdminInfoEntity> implements AdminInfoService {
+
+    @Autowired
+    private JwtOperator jwtOperator;
+
+    @Override
+    public PageUtils queryPage(PageParam pageParam) {
+        IPage<AdminInfoEntity> page = this.page(
+                new MyQuery<AdminInfoEntity>().getPage(pageParam),
+                new QueryWrapper<>()
+        );
+
+        return new PageUtils(page);
+    }
+
+    @Override
+    public UserTokenVO login(String userName, String password) {
+        QueryWrapper<AdminInfoEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("user_name", userName);
+        AdminInfoEntity entity = this.getOne(wrapper);
+        if (entity == null) {
+            throw new RRException(BizCodeEnume.ADMIN_LOGIN_FAIL);
+        }
+
+        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+        if (!encoder.matches(password, entity.getPassword())) {
+            throw new RRException(BizCodeEnume.ADMIN_LOGIN_FAIL);
+        }
+
+        // 登录成功,生成token
+        Map<String, Object> map = new HashMap<>();
+        map.put("userId", entity.getId());
+        String token = jwtOperator.generateToken(map);
+
+        return UserTokenVO.builder()
+                .userName(userName)
+                .token(token)
+                .expireTime(LocalDateTime.now().plusSeconds(jwtOperator.getExpirationTimeInSecond() - 30).toInstant(ZoneOffset.of("+8")).toEpochMilli())
+                .build();
+    }
+}

+ 31 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/EnablePayLimitByGradeServiceImpl.java

@@ -0,0 +1,31 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.dao.EnablePayLimitByGradeDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.EnablePayLimitByGradeEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.EnablePayLimitByGradeService;
+import org.springframework.stereotype.Service;
+
+@Service("enablePayLimitByGradeService")
+public class EnablePayLimitByGradeServiceImpl extends ServiceImpl<EnablePayLimitByGradeDao, EnablePayLimitByGradeEntity> implements EnablePayLimitByGradeService {
+
+    /**
+     * 当前年级是否可缴费
+     * @param grade 1 =》 表示大一
+     * @return
+     */
+    public boolean getCurrentGradeEnablePay(Integer grade) {
+        QueryWrapper<EnablePayLimitByGradeEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("grade", grade);
+
+        EnablePayLimitByGradeEntity entity = this.getOne(wrapper);
+        if (entity == null) {
+            throw new RRException(BizCodeEnume.PAY_GRADE_IS_NOT_EXIT);
+        }
+
+        return "1".equals(entity.getEnablePay())? true : false;
+    }
+}

+ 134 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/FeedbackMsgServiceImpl.java

@@ -0,0 +1,134 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.chuanghai.smartschool.tuitionpayment.enume.FeedbackMsgStatus;
+import com.chuanghai.smartschool.tuitionpayment.to.FeedbackMsgCreateTO;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.vo.FeedbackMsgQueryVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.MyQuery;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+
+import com.chuanghai.smartschool.tuitionpayment.dao.FeedbackMsgDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.FeedbackMsgEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.FeedbackMsgService;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+
+@Service("feedbackMsgService")
+public class FeedbackMsgServiceImpl extends ServiceImpl<FeedbackMsgDao, FeedbackMsgEntity> implements FeedbackMsgService {
+
+    @Override
+    public  PageUtils queryPageVO(FeedbackMsgQueryVO feedbackMsgQueryVO){
+        QueryWrapper<FeedbackMsgEntity> wrapper = new QueryWrapper<>();
+        if (StringUtils.hasText(feedbackMsgQueryVO.getKeyword())) {
+            wrapper.eq("feedback_person_name",feedbackMsgQueryVO.getKeyword())
+                    .or()
+                    .eq("feedback_person_identify",feedbackMsgQueryVO.getKeyword());
+        }
+        if (StringUtils.hasText(feedbackMsgQueryVO.getItemName())) {
+            wrapper.eq("feedback_item_name",feedbackMsgQueryVO.getItemName());
+        }
+        if (StringUtils.hasText(feedbackMsgQueryVO.getStatus())) {
+            wrapper.eq("statu",feedbackMsgQueryVO.getStatus());
+        }
+        wrapper.apply(StringUtils.hasText(feedbackMsgQueryVO.getCreateTime()), "date_format(publish_time, '%Y-%m-%d') = {0}", feedbackMsgQueryVO.getCreateTime());
+
+        PageParam pageParam = new PageParam();
+        if (feedbackMsgQueryVO.getPageParam()!= null){
+            pageParam = feedbackMsgQueryVO.getPageParam();
+        }
+        IPage<FeedbackMsgEntity> page = this.page(
+                new MyQuery<FeedbackMsgEntity>().getPage(pageParam),
+                wrapper
+        );
+        return new PageUtils(page);
+    }
+
+
+    @Override
+    public PageUtils queryPageByStatus(String status, String keyword, PageParam pageParam) {
+        QueryWrapper<FeedbackMsgEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StringUtils.hasText(status), "statu", status);
+
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like("feedback_person_name", keyword)
+                    .or()
+                    .like("feedback_person_phone", keyword));
+        }
+
+        IPage<FeedbackMsgEntity> page = this.page(
+                new MyQuery<FeedbackMsgEntity>().getPage(pageParam),
+                wrapper
+        );
+
+        return new PageUtils(page);
+    }
+
+    @Override
+    public PageUtils queryPage(String cardNumber, PageParam pageParam) {
+        IPage<FeedbackMsgEntity> page = this.page(
+                new MyQuery<FeedbackMsgEntity>().getPage(pageParam),
+                new QueryWrapper<FeedbackMsgEntity>().eq("feedback_person_identify", cardNumber)
+        );
+
+        return new PageUtils(page);
+    }
+
+    /**
+     * 新增反馈信息
+     * @param cardNumber 反馈者id
+     * @param feedbackMsgCreateTO 反馈信息to
+     */
+    @Override
+    public void save(String cardNumber, FeedbackMsgCreateTO feedbackMsgCreateTO) {
+        FeedbackMsgEntity feedbackMsgEntity = new FeedbackMsgEntity();
+
+        BeanUtils.copyProperties(feedbackMsgCreateTO, feedbackMsgEntity);
+
+        feedbackMsgEntity.setFeedbackPersonIdentify(cardNumber);
+        feedbackMsgEntity.setPublishTime(LocalDateTime.now());
+        feedbackMsgEntity.setStatu(FeedbackMsgStatus.NON_HANDLE.getCode());
+        this.save(feedbackMsgEntity);
+    }
+
+    @Override
+    public void downloadResultMsg(HttpServletResponse response, FeedbackMsgQueryVO feedbackMsgQueryVO) throws IOException {
+        QueryWrapper<FeedbackMsgEntity> wrapper = new QueryWrapper<>();
+
+        if (StringUtils.hasText(feedbackMsgQueryVO.getKeyword())) {
+            wrapper.eq("feedback_person_name",feedbackMsgQueryVO.getKeyword())
+                    .or()
+                    .eq("feedback_person_identify",feedbackMsgQueryVO.getKeyword());
+        }
+        if (StringUtils.hasText(feedbackMsgQueryVO.getItemName())) {
+            wrapper.eq("feedback_item_name",feedbackMsgQueryVO.getItemName());
+        }
+        if (StringUtils.hasText(feedbackMsgQueryVO.getStatus())) {
+            wrapper.eq("statu",feedbackMsgQueryVO.getStatus());
+        }
+        wrapper.apply(StringUtils.hasText(feedbackMsgQueryVO.getCreateTime()), "date_format(publish_time, '%Y-%m-%d') = {0}", feedbackMsgQueryVO.getCreateTime());
+
+        List<FeedbackMsgEntity> parOrder = this.list(wrapper);
+        String fileName = URLEncoder.encode("学生反馈列表" + new Date().getTime(), "UTF-8");
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+
+        EasyExcel.write(response.getOutputStream(), FeedbackMsgEntity.class).sheet("学生反馈列表").doWrite(parOrder);
+    }
+
+}

+ 22 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayItemDetailServiceImpl.java

@@ -0,0 +1,22 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayItemDao;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayItemDetailDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItemDetail;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemDetailService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:33
+ * @Description: com.chuanghai.smartschool.tuitionpayment.service.impl
+ * @version: 1.0
+ */
+@Slf4j
+@Service("payItemDetailService")
+public class PayItemDetailServiceImpl extends ServiceImpl<PayItemDetailDao, PayItemDetail> implements PayItemDetailService {
+}

+ 19 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayItemServiceImpl.java

@@ -0,0 +1,19 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayItemDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/22 星期三 14:33
+ * @Description: com.chuanghai.smartschool.tuitionpayment.service.impl
+ * @version: 1.0
+ */
+@Slf4j
+@Service("payItemService")
+public class PayItemServiceImpl extends ServiceImpl<PayItemDao, PayItem> implements PayItemService {
+}

+ 30 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayMethodSettingServiceImpl.java

@@ -0,0 +1,30 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayMethodSettingDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayMethodSettingEntity;
+import com.chuanghai.smartschool.tuitionpayment.enume.PayMethod;
+import com.chuanghai.smartschool.tuitionpayment.service.PayMethodSettingService;
+import org.springframework.stereotype.Service;
+
+
+@Service("payMethodSettingService")
+public class PayMethodSettingServiceImpl extends ServiceImpl<PayMethodSettingDao, PayMethodSettingEntity> implements PayMethodSettingService {
+
+    /**
+     * 获取当前支付方式
+     * @return 1建行支付、2农商行支付
+     */
+    @Override
+    public String getCurrentPayMethod() {
+        QueryWrapper<PayMethodSettingEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("is_current_pay", "1");
+        PayMethodSettingEntity methodSettingEntity = this.getOne(wrapper);
+        if (methodSettingEntity == null) {
+            return PayMethod.CCB_PAY.getCode();
+        }
+
+        return methodSettingEntity.getPayMethod();
+    }
+}

+ 696 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayOrderServiceImpl.java

@@ -0,0 +1,696 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.util.CollectionUtils;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.CommonResult;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.MyQuery;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.controller.PayItemController;
+import com.chuanghai.smartschool.tuitionpayment.controller.PayItemDetailController;
+import com.chuanghai.smartschool.tuitionpayment.controller.PayableInfoController;
+import com.chuanghai.smartschool.tuitionpayment.controller.WechatController;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayOrderDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.enume.PayMethod;
+import com.chuanghai.smartschool.tuitionpayment.enume.PayStatus;
+import com.chuanghai.smartschool.tuitionpayment.service.*;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.utils.MyUtil;
+import com.chuanghai.smartschool.tuitionpayment.utils.OutputTxt;
+import com.chuanghai.smartschool.tuitionpayment.vo.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+@Slf4j
+@Service("payOrderService")
+public class PayOrderServiceImpl extends ServiceImpl<PayOrderDao, PayOrderEntity> implements PayOrderService {
+
+    @Autowired
+    private PayableInfoService payableInfoService;
+    @Autowired
+    private PayableInfoWaterService payableInfoWaterService;
+    @Autowired
+    private PayMethodSettingService payMethodSettingService;
+    @Autowired
+    private EnablePayLimitByGradeService enablePayLimitByGradeService;
+    @Autowired
+    private PayService payService;
+    @Autowired
+    private PayOrderService payOrderService;
+    @Autowired
+    private PayItemController payItemController;
+    @Autowired
+    private WechatController wechatController;
+    @Autowired
+    private PayItemDetailController payItemDetailController;
+    @Autowired
+    private PayableInfoController payableInfoController;
+
+    @Override
+    public PageUtils queryPage(PayOrderQueryTO queryTO, PageParam pageParam) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+
+        commonWrapper(wrapper, queryTO);
+
+        wrapper.orderByDesc("finish_time").orderByDesc("create_time").orderByAsc("pay_for_identify");
+
+        IPage<PayOrderEntity> page = this.page(
+                new MyQuery<PayOrderEntity>().getPage(pageParam),
+                wrapper
+        );
+
+        return new PageUtils(page);
+    }
+
+    @Override
+    public PageUtils queryOrderPage(String keyword, String createTime, PageParam pageParam) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("status", "1");
+        if (StringUtils.hasText(keyword)) {
+            wrapper.eq("payer_identify", keyword)
+                    .or()
+                    .eq("student_name", keyword);
+        }
+        wrapper.apply(StringUtils.hasText(createTime), "date_format(create_time, '%Y-%m-%d') = {0}", createTime);
+
+        IPage<PayOrderEntity> page = this.page(
+                new MyQuery<PayOrderEntity>().getPage(pageParam),
+                wrapper
+        );
+        return new PageUtils(page);
+    }
+
+    @Override
+    public PageUtils queryPage(PageParam pageParam, String cardNumber, String status) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        if (status.equals("1")) {
+            wrapper.eq("payer_identify", cardNumber)
+                    .eq("status", status);
+        } else {
+            wrapper.eq("payer_identify", cardNumber)
+                    .in("status", 2, 3)
+                    .eq("is_parent", Boolean.TRUE);
+        }
+
+//        wrapper.eq("payer_identify", cardNumber)
+//                .eq("status", status);
+        IPage<PayOrderEntity> page = this.page(
+                new MyQuery<PayOrderEntity>().getPage(pageParam),
+                wrapper
+        );
+
+        return new PageUtils(page);
+    }
+
+    @Override
+    public String queryAmount(String itemName) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("status", 2)
+                .eq("pay_item", itemName)
+                .select("ifnull(sum(real_pay_amount), 0) as total,count(id) as count");
+
+        Map<String, Object> resultMap = this.getMap(wrapper);
+        String substring = resultMap.get("total").toString().substring(0, resultMap.get("total").toString().length() - 6);
+        return resultMap.get("count") + "-" + substring;
+
+    }
+
+
+    /**
+     * 获取用户是否缴费
+     *
+     * @param studentNo 学号
+     * @return
+     */
+    @Override
+    public boolean isAlreadyPay(String studentNo, String itemName, String payYears, Integer notPaySize) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("pay_for_identify", studentNo);
+        wrapper.eq("pay_item", itemName);
+        wrapper.eq(StringUtils.hasText(payYears), "pay_year", payYears);
+        wrapper.eq("not_pay_size", notPaySize);
+        wrapper.eq("status", PayStatus.ALREADY_PAY.getCode());
+
+        List<PayOrderEntity> payList = this.list(wrapper);
+
+        if (payList != null && payList.size() > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 创建缴费订单
+     *
+     * @param cardNumber 当前用户
+     * @return
+     */
+    @Override
+    public CreateOrderResultVO createOrder(String cardNumber, PayOrderReceiveVO payOrderReceiveVO) {
+        String studentNo = payOrderReceiveVO.getStudentNo();
+        String drom = payOrderReceiveVO.getDrom();
+        String itemName = payOrderReceiveVO.getItemName();
+        String payDetial = payOrderReceiveVO.getPayDetail();
+        String payYear = payOrderReceiveVO.getPayYear();
+        String orderNotice = payOrderReceiveVO.getOrderNotice();
+
+
+        String id = payOrderReceiveVO.getId().toString();
+        //     String payItemType = payOrderReceiveVO.getPayItemType();
+        // 查询用户是否已经缴费
+        boolean alreadyPay = isAlreadyPay(studentNo, itemName, payYear, payOrderReceiveVO.getNotPaySize());
+        if (alreadyPay) {
+            throw new RRException(BizCodeEnume.DATA_IS_EXIST, "学号【" + studentNo + "】已缴费,请勿重复缴费");
+        }
+        PayableInfoEntity payableInfo = null;
+        PayableInfoWaterEntity payableInfoWater = null;
+        String grade = "";
+        //     String notPayDetail = "";
+        //     String totalDetail = "";
+        if (itemName.equals("水费缴纳")) {
+            payableInfoWater = payableInfoWaterService.getByStudentNo(studentNo, itemName, payYear);
+            // 获取学生入学年份
+            grade = payableInfoWater.getGrade();
+            //     totalDetail = payableInfoWater.getPayAmountDetail();
+        } else {
+            // 查询支付金额、被支付用户信息
+            payableInfo = payableInfoService.getByStudentNo(studentNo, itemName, payYear);
+            // 获取学生入学年份
+            grade = payableInfo.getGrade();
+            //     notPayDetail = payableInfo.getNotPayDetail();
+        }
+
+        Integer currentGrade = MyUtil.calcStudentGrade(Integer.valueOf(grade.trim()));
+
+        // 判断当前年级是否可线上缴费
+        //  boolean enablePay = Boolean.FALSE;
+        PayItem payItem = payItemController.queryByItemNameSetting(itemName).getData();
+        String itemGrade = payItem.getItemGrade();
+        String gradeStr = "";
+        JSONArray jsonArray = JSONObject.parseArray(itemGrade);
+        for (int i = 0; i < jsonArray.size(); i++) {
+            gradeStr += jsonArray.get(i);
+        }
+        //  boolean enablePay = enablePayLimitByGradeService.getCurrentGradeEnablePay(currentGrade);
+        if (!(gradeStr.contains(String.valueOf(currentGrade)))) {
+            throw new RRException(BizCodeEnume.PAYABLE_INFO_IS_NOT_EXIT, "当前学生所在年级不允许线上缴费");
+        }
+        // 获取当前支付方式
+        String currentPayMethod = payMethodSettingService.getCurrentPayMethod();
+
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("payer_identify", cardNumber);
+        wrapper.eq("pay_for_identify", studentNo);
+        wrapper.eq("pay_item", itemName);
+        wrapper.eq(StringUtils.hasText(payYear), "pay_year", payYear);
+        wrapper.eq("not_pay_size", payOrderReceiveVO.getNotPaySize());
+        wrapper.orderByDesc("create_time");
+        wrapper.last("limit 1");
+        PayOrderEntity payOrderEntity = this.getOne(wrapper);
+
+        // 订单已经存在超过30分钟没有支付,直接删除该订单
+        if (payOrderEntity != null && PayStatus.NON_PAY.getCode().equals(payOrderEntity.getStatus())) {
+            if (Math.abs(ChronoUnit.MINUTES.between(LocalDateTime.now(), payOrderEntity.getCreateTime())) > 30) {
+                // 再次查询订单状态
+                OrderStatusVO orderStatusVO = queryOrderStatus(payOrderEntity);
+                if (PayStatus.NON_PAY.getCode().equals(orderStatusVO.getStatus())) {
+                    this.removeById(payOrderEntity.getId());
+                    payOrderEntity = null;
+                }
+            }
+        }
+
+        CreateOrderResultVO createOrderResultVO = new CreateOrderResultVO();
+        if (payOrderEntity == null) {
+            createOrderResultVO.setMsg("新创建订单");
+
+            payOrderEntity = new PayOrderEntity();
+
+            //判断该订单是否为多次支付
+            PayInfoDetailVO payInfoDetailVO = new PayInfoDetailVO();
+            int count = Integer.parseInt(payOrderReceiveVO.getPayCount());
+            if (count == 1) {
+                payOrderEntity.setIsParent(Boolean.TRUE);
+                // payInfoDetailVO =  payableInfoController.queryPayDetail(id, itemName, payOrderReceiveVO.getPayDetail());
+            } else {
+                //获取缴费明细
+                // String payDetail = payOrderReceiveVO.getPayDetail();
+
+                //判断是否有未支付的明细
+
+//                if (!itemName.equals("水费缴纳")) {
+//                    if (StringUtils.hasText(payInfoDetailVO.getNotMustMoney())) {
+//                        totalDetail = payInfoDetailVO.getMustMoney() + "/" + payInfoDetailVO.getNotMustMoney();
+//                    }else {
+//                        totalDetail = payInfoDetailVO.getMustMoney();
+//                    }
+//                }
+//                if (totalDetail.equals(payDetail)) {
+//                } else {
+//                    payOrderEntity.setIsParent(Boolean.FALSE);
+//                }
+            }
+            payInfoDetailVO = (PayInfoDetailVO) payableInfoController.queryPayInfoDetail(id, itemName, payOrderReceiveVO.getPayDetail()).getData();
+
+            payOrderEntity.setNotPayDetail(payInfoDetailVO.getNotPayDetail());
+
+            payOrderEntity.setOrderNo(generateOrderNo());
+            payOrderEntity.setPayerIdentify(cardNumber);
+            payOrderEntity.setPayForIdentify(studentNo);
+            payOrderEntity.setStatus(PayStatus.NON_PAY.getCode());
+            payOrderEntity.setPayMethod(currentPayMethod);
+            payOrderEntity.setCreateTime(LocalDateTime.now());
+            payOrderEntity.setNotPaySize(payOrderReceiveVO.getNotPaySize());
+            payOrderEntity.setPayItem(itemName);
+            payOrderEntity.setPayYear(payYear);
+            payOrderEntity.setPayDetail(payDetial);
+
+            payOrderEntity.setOrderNotice(orderNotice);
+            payOrderEntity.setExceptType("1");
+            payOrderEntity.setPayBank(payItemController.queryPayItemByName(itemName));
+            //计算助学贷款相关的费用
+            String payOrderLoan = payOrderReceiveVO.getPayOrderLoan();
+            BigDecimal orderLoan = BigDecimal.ZERO;
+//            if (StringUtils.hasText(payOrderLoan)) {
+//                orderLoan = orderLoan.add(new BigDecimal(payOrderLoan)).setScale(2,BigDecimal.ROUND_HALF_UP);
+//            }
+            if (StringUtils.hasText(payOrderLoan)) {
+                orderLoan = orderLoan.add(new BigDecimal(payOrderLoan)).setScale(2, BigDecimal.ROUND_UP);
+            }
+            payOrderEntity.setPayOrderLoan(orderLoan);
+
+
+            // 支付金额、被支付用户信息
+            if (itemName.equals("水费缴纳")) {
+                //更新对应项目的缴费参数
+
+                payOrderEntity.setDrom(drom.isEmpty() ? "" : drom);
+                payOrderEntity.setRealPayAmount(payableInfoWater.getRealPayAmount());
+                payOrderEntity.setNowPayAmount(payableInfoWater.getRealPayAmount());
+                payOrderEntity.setStudentName(payableInfoWater.getStudentName());
+                payOrderEntity.setClassName(payableInfoWater.getClassName());
+            } else {
+                payOrderEntity.setRealPayAmount(payableInfo.getRealPayAmount().subtract(orderLoan).setScale(2, BigDecimal.ROUND_UP));
+                System.out.println(payInfoDetailVO.getPayDetailAmount());
+                payOrderEntity.setNowPayAmount(payInfoDetailVO.getPayDetailAmount());
+                payOrderEntity.setStudentName(payableInfo.getStudentName());
+                payOrderEntity.setClassName(payableInfo.getClassName());
+                //更新缴费名单的缴费明细
+                if (StringUtils.hasText(payableInfo.getPayDetail())) {
+                    payableInfo.setPayDetail(payableInfo.getPayDetail() + "/" + payDetial);
+                } else {
+                    payableInfo.setPayDetail(payDetial);
+                }
+                payableInfo.setNotPayDetail(payOrderEntity.getNotPayDetail());
+                payableInfo.setNotPaySize(payOrderReceiveVO.getNotPaySize());
+              //  payableInfoService.updateById(payableInfo);
+
+            }
+            BigDecimal parentNowPayDetailAmount = BigDecimal.ZERO;
+            if (count > 1) {
+                QueryWrapper<PayOrderEntity> wrapper1 = new QueryWrapper<>();
+                wrapper1.eq("payer_identify", cardNumber);
+                wrapper1.eq("pay_for_identify", studentNo);
+                wrapper1.eq("pay_item", itemName);
+                wrapper1.eq(StringUtils.hasText(payYear), "pay_year", payYear);
+                wrapper1.eq("status", "3");
+//                wrapper1.orderByAsc("create_time");
+//                wrapper1.last("limit 1");
+                PayOrderEntity one = this.getOne(wrapper1);
+                payOrderEntity.setParentOrder(one.getOrderNo());
+                parentNowPayDetailAmount =  parentNowPayDetailAmount.add(one.getNowPayAmount()).setScale(2,BigDecimal.ROUND_HALF_UP);
+
+            }
+            //校验订单的支付金额是否异常
+            int i = 1;
+            if (itemName.equals("水费缴纳")) {
+                i = payOrderEntity.getNowPayAmount().compareTo(payableInfoWater.getRealPayAmount());
+            }else {
+                i = payOrderEntity.getNowPayAmount().add(payOrderEntity.getPayOrderLoan()).add(payInfoDetailVO.getNotPayDetailAmount()).compareTo(payableInfo.getRealPayAmount());
+
+                //i = payOrderEntity.getNowPayAmount().add(payOrderEntity.getPayOrderLoan()).compareTo(payableInfo.getRealPayAmount());
+            }
+            //前端实付金额
+            BigDecimal realPayAmount = payInfoDetailVO.getRealPayAmount().setScale(2,BigDecimal.ROUND_HALF_UP);
+            if (count > 1){
+                payOrderEntity.setNowPayAmount(payOrderEntity.getNowPayAmount().subtract(parentNowPayDetailAmount).setScale(2,BigDecimal.ROUND_HALF_UP));
+            }
+            if (realPayAmount == payOrderEntity.getNowPayAmount()) {
+                i = 1;
+            }
+
+            if (i != 0) {
+                throw new RRException(BizCodeEnume.PAY_AMOUNT_ERROR, "支付金额异常。");
+                //检测该订单是否异常,订单异常自动发送 订单异常微校通知
+              //  wechatController.sendException(itemName);
+            }
+
+          /*  首次订单支付成功之后如果还有未支付的 状态为 3 无未支付的状态为 2
+              当所有未支付的明细完成缴费之后 首单状态变为 2 状态:支付成功且完成所有缴费
+
+              检测该订单是否异常,订单异常自动发送 订单异常微校通知
+              wechatController.sendException(itemName);
+          */
+            this.save(payOrderEntity);
+
+
+        } else {
+            if (!payOrderEntity.getPayMethod().equals(currentPayMethod)) {
+                payOrderEntity.setPayMethod(currentPayMethod);
+                this.updateById(payOrderEntity);
+            }
+            createOrderResultVO.setMsg("订单早已创建");
+        }
+
+        createOrderResultVO.setAmount(payOrderEntity.getRealPayAmount());
+        createOrderResultVO.setOrderNo(payOrderEntity.getOrderNo());
+        createOrderResultVO.setPayMethod(payOrderEntity.getPayMethod());
+        return createOrderResultVO;
+    }
+
+    /**
+     * 根据订单号查询订单
+     *
+     * @param orderNo
+     * @return
+     */
+    @Override
+    public PayOrderEntity getByOrderNo(String orderNo) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("order_no", orderNo);
+        PayOrderEntity payOrderEntity = this.getOne(wrapper);
+        if (payOrderEntity == null) {
+            throw new RRException(BizCodeEnume.ORDER_IS_NOT_EXIT);
+        }
+
+        return payOrderEntity;
+    }
+
+    /**
+     * 查询订单状态
+     *
+     * @param cardNumber 支付者标识
+     * @param orderNo    订单号
+     * @return
+     */
+    @Override
+    public OrderStatusVO queryOrderStatus(String cardNumber, String orderNo) {
+        OrderStatusVO orderStatusVO = queryOrderStatus(orderNo);
+
+        if (!orderStatusVO.getPayerId().equals(cardNumber)) {
+            throw new RRException(BizCodeEnume.NO_PERMISSION);
+        }
+
+        return orderStatusVO;
+    }
+
+    @Override
+    public OrderStatusVO queryOrderStatus(PayOrderEntity payOrder) {
+        String orderNo = payOrder.getOrderNo();
+        // 订单未支付状态,先查询一下银行订单状态
+        if (PayStatus.NON_PAY.getCode().equalsIgnoreCase(payOrder.getStatus())) {
+            try {
+                if (PayMethod.CCB_PAY.getCode().equals(payOrder.getPayMethod())) {
+                    Map<String, String> map = payService.queryCCBOrderStatus(orderNo);
+                    String orderId = map.get("ORDERID");
+                    String statusCode = map.get("STATUSCODE");
+                    String amount = map.get("AMOUNT"); // ORDERDATE -> 20220708091308
+                    if (orderNo.equals(orderId)
+                            && payOrder.getNowPayAmount().setScale(2, BigDecimal.ROUND_UP).toString().equals(amount)
+                            && "1".equals(statusCode)) {
+                        // TODO 完成时间应该改成实际完成支付时间
+                        String orderdate = map.get("ORDERDATE");
+                        LocalDateTime localDateTime = new MyUtil().changeTime(orderdate);
+                        payOrder.setFinishTime(localDateTime);
+                        payOrder.setStatus(PayStatus.ALREADY_PAY.getCode());
+                        this.updateById(payOrder);
+                    }
+                } else if (PayMethod.JXNXS_PAY.getCode().equals(payOrder.getPayMethod())) {
+                    Map<String, String> map = payService.queryJXNXSOrderStatus(orderNo);
+                    String orderId = map.get("out_no");
+                    String statusCode = map.get("status");
+                    String amount = map.get("trade_amount");
+                    BigDecimal realPayAmount = new BigDecimal(amount).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_UP); // 分转成元
+
+                    if (orderNo.equals(orderId) && "1".equals(statusCode)) {
+                        if (Math.abs(payOrder.getNowPayAmount().setScale(2, BigDecimal.ROUND_UP).subtract(realPayAmount).doubleValue()) < 0.01) {
+                            payOrder.setStatus(PayStatus.ALREADY_PAY.getCode());
+                            // TODO 完成时间应该改成实际完成支付时间
+                            payOrder.setFinishTime(LocalDateTime.now());
+                            this.updateById(payOrder);
+                        }
+                    }
+                }
+
+            } catch (RRException e) {
+                log.error("订单状态查询失败【{}】", e.getMessage());
+            }
+        }
+
+        OrderStatusVO orderStatusVO = new OrderStatusVO();
+        orderStatusVO.setOrderNo(orderNo);
+        orderStatusVO.setStatus(payOrder.getStatus());
+        orderStatusVO.setPayerId(payOrder.getPayerIdentify());
+        return orderStatusVO;
+    }
+
+    /**
+     * 查询订单状态
+     *
+     * @param orderNo 订单号
+     * @return
+     */
+    @Override
+    public OrderStatusVO queryOrderStatus(String orderNo) {
+        PayOrderEntity payOrder = getByOrderNo(orderNo);
+        return queryOrderStatus(payOrder);
+    }
+
+    /**
+     * 查询当前已完成支付金额
+     *
+     * @param queryTO
+     * @return
+     */
+    @Override
+    public BigDecimal queryCurrentPayedAmount(PayOrderQueryTO queryTO) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        queryTO.setPayStatus(PayStatus.ALREADY_PAY.getCode());
+
+        commonWrapper(wrapper, queryTO);
+
+        wrapper.select("ifnull(sum(order_amount), 0) as total");
+        Map<String, Object> resultMap = this.getMap(wrapper);
+
+        return new BigDecimal(String.valueOf(resultMap.get("total"))).setScale(2, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 下载缴费的名单的txt文件
+     *
+     * @param response //     * @param flag
+     *                 //     * @param dateStr
+     */
+    @Override
+    public void exportOrderTxt(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException {
+
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+
+        commonWrapper(wrapper, queryTO);
+        if (queryTO.getDownIds() != null && queryTO.getDownIds().size() > 0) {
+            wrapper.in("order_no", queryTO.getDownIds());
+        }
+        wrapper.orderByDesc("finish_time").orderByDesc("create_time").orderByAsc("pay_for_identify");
+        List<PayOrderEntity> parOrder = this.list(wrapper);
+        String outPutStr = "";
+        if (parOrder.size() > 0) {
+            JSONArray jsonArray = new JSONArray();
+            jsonArray.addAll(parOrder);
+            for (int i = 0; i < jsonArray.size(); i++) {
+                PayOrderEntity payOrderEntity = (PayOrderEntity) jsonArray.get(i);
+                String year = payOrderEntity.getPayYear().split("-")[0];
+                String payOrderDetail = payItemDetailController.queryAllItemDetail(payOrderEntity.getPayDetail());
+                String[] splitStr = payOrderDetail.split("/");
+                for (int j = 0; j < splitStr.length; j++) {
+                    String[] split = splitStr[j].split(":");
+                    outPutStr += payOrderEntity.getPayForIdentify() + "\t" + payOrderEntity.getStudentName() + "\t" +
+                            year + "\t" + split[0] + "\t" + "\"" + split[1] + "\"" + "\t" + "\r";
+                }
+            }
+        }
+
+        new OutputTxt().outTxt(response, outPutStr);
+    }
+
+
+    /**
+     * 下载缴费的名单
+     *
+     * @param response
+     * @param queryTO  查询条件
+     */
+    @Override
+    public void downloadResult(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException {
+
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+
+        commonWrapper(wrapper, queryTO);
+        if (queryTO.getDownIds() != null && queryTO.getDownIds().size() > 0) {
+            wrapper.in("order_no", queryTO.getDownIds());
+        }
+        wrapper.orderByDesc("finish_time").orderByDesc("create_time").orderByAsc("pay_for_identify");
+        List<PayOrderEntity> parOrder = this.list(wrapper);
+        String fileName = "";
+        if (queryTO.getPayStatus().equals("1")) {
+            fileName = URLEncoder.encode("未缴费学生名单" + new Date().getTime(), "UTF-8");
+        } else {
+            fileName = URLEncoder.encode("已缴费学生名单" + new Date().getTime(), "UTF-8");
+        }
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+        if (queryTO.getPayStatus().equals("1")) {
+            EasyExcel.write(response.getOutputStream(), PayOrderEntity.class).sheet("未缴费学生名单").doWrite(parOrder);
+        } else {
+            EasyExcel.write(response.getOutputStream(), PayOrderEntity.class).sheet("已缴费学生名单").doWrite(parOrder);
+        }
+    }
+
+
+    @Override
+    public Integer queryCurrentPayedRecordNum(PayOrderQueryTO queryTO) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        queryTO.setPayStatus(PayStatus.ALREADY_PAY.getCode());
+
+        commonWrapper(wrapper, queryTO);
+
+        return this.count(wrapper);
+    }
+
+    /**
+     * 生成订单号
+     *
+     * @return
+     */
+    private String generateOrderNo() {
+        String idStr = IdWorker.getIdStr();
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("order_no", idStr);
+        PayOrderEntity one = this.getOne(wrapper);
+        if (one == null) {
+            return idStr;
+        } else {
+            return generateOrderNo();
+        }
+    }
+
+    /**
+     * 构建公共的查询wrapper
+     *
+     * @param wrapper
+     * @param queryTO
+     */
+    private void commonWrapper(QueryWrapper<PayOrderEntity> wrapper, PayOrderQueryTO queryTO) {
+        wrapper.eq(StringUtils.hasText(queryTO.getPayStatus()), "status", queryTO.getPayStatus());
+        wrapper.eq(StringUtils.hasText(queryTO.getPayMethod()), "pay_method", queryTO.getPayMethod());
+        String keyword = queryTO.getKeyword();
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like("student_name", keyword)
+                    .or()
+                    .like("pay_for_identify", keyword)
+                    .or()
+                    .eq("order_no", keyword));
+        }
+        wrapper.eq("pay_item", queryTO.getItemName());
+        if (StringUtils.hasText(queryTO.getPayYear())) {
+            wrapper.eq("pay_year", queryTO.getPayYear());
+        }
+
+        String flag = queryTO.getFlag();
+        String createDateStr = queryTO.getCreateDateStr();
+        if ((StringUtils.hasText(createDateStr))) {
+            wrapper.apply("2".equals(flag), "date_format(create_time, '%Y-%m') = {0}", createDateStr);
+            wrapper.apply("3".equals(flag), "date_format(create_time, '%Y-%m-%d') = {0}", createDateStr);
+        }
+
+        String payDateStr = queryTO.getPayDateStr();
+        if ((StringUtils.hasText(payDateStr))) {
+            wrapper.apply("2".equals(flag), "date_format(finish_time, '%Y-%m') = {0}", payDateStr);
+            wrapper.apply("3".equals(flag), "date_format(finish_time, '%Y-%m-%d') = {0}", payDateStr);
+        }
+    }
+
+    public String queryPayOrderAmount(PayOrderQueryTO queryTO) {
+
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        commonWrapper(wrapper, queryTO);
+
+
+        wrapper.eq(StringUtils.hasText(queryTO.getPayYear()), "pay_year", queryTO.getPayYear())
+                .eq(StringUtils.hasText(queryTO.getItemName()), "pay_item", queryTO.getItemName())
+                .select("ifnull(sum(real_pay_amount), 0) as total,count(id) as count");
+        List<PayOrderEntity> list = this.payOrderService.list(wrapper);
+
+        if (list.size() > 0) {
+            Map<String, Object> resultMap = this.getMap(wrapper);
+            String count = String.valueOf(resultMap.get("count"));
+            return new BigDecimal(String.valueOf(resultMap.get("total"))).setScale(2, BigDecimal.ROUND_HALF_UP) + "-" + count;
+        } else {
+            return "0-0";
+        }
+    }
+
+    public PageUtils queryAllOrderByParent(String orderNo, PageParam pageParam) {
+        QueryWrapper<PayOrderEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("parent_order", orderNo)
+                .eq("status", "2")
+                .or()
+                .eq("order_no", orderNo);
+
+        IPage<PayOrderEntity> page = this.page(
+                new MyQuery<PayOrderEntity>().getPage(pageParam),
+                wrapper
+        );
+        List<PayOrderEntity> records = page.getRecords();
+        records.forEach(order -> {
+            BigDecimal nowPayAmount = BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP);
+            String payDetail = order.getPayDetail();
+            if (StringUtils.hasText(payDetail)) {
+                String[] split = payDetail.split("/");
+                for (int i = 0; i < split.length; i++) {
+                    nowPayAmount = nowPayAmount.add(new BigDecimal(split[i].split(":")[1]).setScale(2, BigDecimal.ROUND_HALF_UP));
+                }
+            }
+
+            order.setNowPayAmount(nowPayAmount);
+        });
+        page.setRecords(records);
+        return new PageUtils(page);
+    }
+}

Разница между файлами не показана из-за своего большого размера
+ 530 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayServiceImpl.java


+ 348 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayableInfoServiceImpl.java

@@ -0,0 +1,348 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSONArray;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.chuanghai.smartschool.tuitionpayment.listener.aliexcel.MyPayableInfoImportListener;
+import com.chuanghai.smartschool.tuitionpayment.service.EnablePayLimitByGradeService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayItemService;
+import com.chuanghai.smartschool.tuitionpayment.service.PayOrderService;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.utils.OutputTxt;
+import com.chuanghai.smartschool.tuitionpayment.vo.StudentPayableInfoVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.MyQuery;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+
+import com.chuanghai.smartschool.tuitionpayment.dao.PayableInfoDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.service.PayableInfoService;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+
+@Service("payableInfoService")
+public class PayableInfoServiceImpl extends ServiceImpl<PayableInfoDao, PayableInfoEntity> implements PayableInfoService {
+
+    @Autowired
+    private PayOrderService payOrderService;
+
+    @Autowired
+    private PayItemService payItemService;
+
+    @Autowired
+    private PayableInfoService payableInfoService;
+
+    @Autowired
+    private EnablePayLimitByGradeService enablePayLimitByGradeService;
+
+
+    @Override
+    public PageUtils queryPage(PayOrderQueryTO queryTO, PageParam pageParam) {
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StringUtils.hasText(queryTO.getItemName()), "payment_item", queryTO.getItemName());
+        if (StringUtils.hasText(queryTO.getKeyword())) {
+            wrapper.and(w -> w.like("student_no", queryTO.getKeyword())
+                    .or()
+                    .like("student_name", queryTO.getKeyword()));
+        }
+        if (StringUtils.hasText(queryTO.getPayStatus())) {
+            wrapper.eq("pay_item_type", queryTO.getPayStatus());
+        }
+        wrapper.apply(StringUtils.hasText(queryTO.getCreateDateStr()), "date_format(pay_create_time, '%Y-%m-%d') = {0}", queryTO.getCreateDateStr());
+        wrapper.apply(StringUtils.hasText(queryTO.getPayDateStr()), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", queryTO.getPayDateStr());
+
+        IPage<PayableInfoEntity> page = this.page(
+                new MyQuery<PayableInfoEntity>().getPage(pageParam),
+                wrapper
+        );
+        return new PageUtils(page);
+    }
+
+//    public void payableInfoWapper(){
+//        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+//
+//        if (StringUtils.hasText(keyword)) {
+//            wrapper.and(w -> w.like("student_no", keyword)
+//                    .or()
+//                    .like("student_name", keyword));
+//        }
+//        if (StringUtils.hasText(payStatus)) {
+//            wrapper.eq("pay_item_type", payStatus);
+//        }
+//        wrapper.apply(StringUtils.hasText(createTime), "date_format(pay_create_time, '%Y-%m-%d') = {0}", createTime);
+//        wrapper.apply(StringUtils.hasText(payTime), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", payTime);
+//
+//    }
+
+    public String queryAmount(PayOrderQueryTO queryTO) {
+
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+        if (StringUtils.hasText(queryTO.getKeyword())) {
+            wrapper.and(w -> w.like("student_no", queryTO.getKeyword())
+                    .or()
+                    .like("student_name", queryTO.getKeyword()));
+        }
+        if (StringUtils.hasText(queryTO.getPayStatus())) {
+            wrapper.eq("pay_item_type", queryTO.getPayStatus());
+        }
+        wrapper.apply(StringUtils.hasText(queryTO.getCreateDateStr()), "date_format(pay_create_time, '%Y-%m-%d') = {0}", queryTO.getCreateDateStr());
+        wrapper.apply(StringUtils.hasText(queryTO.getPayDateStr()), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", queryTO.getPayDateStr());
+
+        if (StringUtils.hasText(queryTO.getItemName())) {
+            wrapper.eq("pay_item_type", queryTO.getPayStatus())
+                    .eq("payment_item", queryTO.getItemName())
+                    .select("ifnull(sum(real_pay_amount), 0) as total,count(id) as count");
+        }
+
+        List<PayableInfoEntity> list = this.payableInfoService.list(wrapper);
+        if (list.size() > 0) {
+            Map<String, Object> resultMap = this.getMap(wrapper);
+            String count = String.valueOf(resultMap.get("count"));
+            return new BigDecimal(String.valueOf(resultMap.get("total"))).setScale(2, BigDecimal.ROUND_HALF_UP) + "-" + count;
+        } else {
+            return "0-0";
+        }
+    }
+
+    public String queryPayItemByName(String name) {
+        QueryWrapper<PayItem> wapper = new QueryWrapper<>();
+        wapper.eq("item_name", name);
+        List<PayItem> list = payItemService.list(wapper);
+        String itemAccount = "";
+        if (list.size() > 0) {
+            PayItem payItem = list.get(0);
+            itemAccount = payItem.getItemAccount();
+            String start = itemAccount.substring(0, 3);
+            String end = itemAccount.substring(itemAccount.length() - 4);
+            itemAccount = payItem.getItemBank() + " (" + start + "****" + end + ")";
+        }
+        return itemAccount;
+    }
+
+    /**
+     * 根据学号查询用户缴费信息
+     *
+     * @param cardNumber
+     * @return
+     */
+    @Override
+    public List<PayableInfoEntity> getPayableInfoByCardNumber(String cardNumber, String studentName) {
+        // 查询用户基本的缴费信息
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper();
+        wrapper.eq("student_no", cardNumber);
+        wrapper.eq(StringUtils.hasText(studentName),"student_name",studentName);
+        wrapper.in("pay_item_type", "1","3");
+        wrapper.eq("pay_notice_type","2");
+
+        return getPayableInfo(wrapper);
+    }
+
+//    /**
+//     * 根据学号和学生姓名获取缴费信息
+//     *
+//     * @param studentNo   学号
+//     * @param studentName 学生姓名
+//     * @return
+//     */
+//    @Override
+//    public List<PayableInfoEntity> getPayableInfoByStudentNoAndName(String studentNo, String studentName) {
+//        // 查询用户基本的缴费信息
+//        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper();
+//        wrapper.eq("student_no", studentNo);
+//        wrapper.eq("student_name", studentName);
+//
+//        return getPayableInfo(wrapper);
+//    }
+
+    /**
+     * 根据学号查询缴费信息
+     *
+     * @param studentNo
+     * @return
+     */
+    @Override
+    public PayableInfoEntity getByStudentNo(String studentNo, String itemName, String payYears) {
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper();
+        wrapper.eq("student_no", studentNo);
+        wrapper.eq("payment_item", itemName);
+        wrapper.eq("years", payYears);
+        PayableInfoEntity payableInfoEntity = this.getOne(wrapper);
+        if (payableInfoEntity == null) {
+            throw new RRException(BizCodeEnume.PAYABLE_INFO_IS_NOT_EXIT);
+        }
+
+        return payableInfoEntity;
+    }
+
+    /**
+     * 导入学生应缴信息原始数据
+     *
+     * @param file
+     */
+    @Transactional
+    @Override
+    public void importByExcel(MultipartFile file) throws IOException {
+
+        EasyExcel.read(file.getInputStream(),
+                PayableInfoEntity.class,
+                new MyPayableInfoImportListener(this))
+                .sheet().doRead();
+
+    }
+
+
+    /**
+     * 下载缴费的名单的txt文件
+     *
+     * @param response //     * @param flag
+     *                 //     * @param dateStr
+     */
+    @Override
+    public void exportTxt(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException {
+
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StringUtils.hasText(queryTO.getItemName()), "payment_item", queryTO.getItemName());
+        wrapper.eq(StringUtils.hasText(queryTO.getPayStatus()), "pay_item_type", queryTO.getPayStatus());
+        wrapper.eq(StringUtils.hasText(queryTO.getPayMethod()), "pay_method", queryTO.getPayMethod());
+        if (queryTO.getDownIds() != null && queryTO.getDownIds().size() > 0) {
+            wrapper.in("student_no", queryTO.getDownIds());
+        }
+        wrapper.apply(StringUtils.hasText(queryTO.getCreateDateStr()), "date_format(pay_create_time, '%Y-%m-%d') = {0}", queryTO.getCreateDateStr());
+        wrapper.apply(StringUtils.hasText(queryTO.getPayDateStr()), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", queryTO.getPayDateStr());
+//        String flag = queryTO.getFlag();
+//        String createDateStr = queryTO.getCreateDateStr();
+//        if ((StringUtils.hasText(createDateStr))) {
+//            wrapper.apply("2".equals(flag), "date_format(pay_create_time, '%Y-%m') = {0}", createDateStr);
+//            wrapper.apply("3".equals(flag), "date_format(pay_create_time, '%Y-%m-%d') = {0}", createDateStr);
+//        }
+//
+//        String payDateStr = queryTO.getPayDateStr();
+//        if ((StringUtils.hasText(payDateStr))) {
+//            wrapper.apply("2".equals(flag), "date_format(pay_finish_time, '%Y-%m') = {0}", payDateStr);
+//            wrapper.apply("3".equals(flag), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", payDateStr);
+//        }
+
+        wrapper.orderByDesc("pay_finish_time");
+        List<PayableInfoEntity> parOrder = this.payableInfoService.list(wrapper);
+        String outPutStr = "";
+        if (parOrder.size() > 0) {
+            JSONArray jsonArray = new JSONArray();
+            jsonArray.addAll(parOrder);
+            for (int i = 0; i < jsonArray.size(); i++) {
+                PayableInfoEntity payableInfoEntity = (PayableInfoEntity) jsonArray.get(i);
+                outPutStr += payableInfoEntity.getStudentNo() + "\t" + payableInfoEntity.getStudentName() + "\t" + payableInfoEntity.getRealPayAmount() + "\t" +
+                        payableInfoEntity.getPayableAccount() + "\t" + payableInfoEntity.getMustMoney() + "\t" + payableInfoEntity.getNotMustMoney() + "\t" +
+                        payableInfoEntity.getOrderNotice() + "\t" + payableInfoEntity.getPaymentItem() + "\r";
+            }
+        }
+
+        new OutputTxt().outTxt(response, outPutStr);
+    }
+
+    /**
+     * 下载完成缴费的名单
+     *
+     * @param response
+     * @param queryTO  查询条件
+     *                 // * @param downIds  勾选的id
+     */
+    @Override
+    public void downloadResult(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException {
+
+        QueryWrapper<PayableInfoEntity> wrapper = new QueryWrapper<>();
+
+        commonWrapper(wrapper, queryTO);
+//        if (queryTO.getDownIds().size() > 0) {
+//            wrapper.in("student_no", queryTO.getDownIds());
+//        }
+        wrapper.orderByDesc("pay_finish_time").orderByDesc("pay_create_time");
+        List<PayableInfoEntity> parOrder = this.list(wrapper);
+        String fileName = URLEncoder.encode("缴费学生名单" + new Date().getTime(), "UTF-8");
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+
+        EasyExcel.write(response.getOutputStream(), PayableInfoEntity.class).sheet("缴费学生名单").doWrite(parOrder);
+    }
+
+
+    /**
+     * 构建公共的查询wrapper
+     *
+     * @param wrapper
+     * @param queryTO
+     */
+    private void commonWrapper(QueryWrapper<PayableInfoEntity> wrapper, PayOrderQueryTO queryTO) {
+        wrapper.eq(StringUtils.hasText(queryTO.getPayStatus()), "pay_item_type", queryTO.getPayStatus());
+        wrapper.eq(StringUtils.hasText(queryTO.getPayMethod()), "pay_method", queryTO.getPayMethod());
+        String keyword = queryTO.getKeyword();
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like("student_name", keyword)
+                    .or()
+                    .like("student_no", keyword));
+        }
+        wrapper.eq("payment_item", queryTO.getItemName());
+
+
+        String flag = queryTO.getFlag();
+        String createDateStr = queryTO.getCreateDateStr();
+        if ((StringUtils.hasText(createDateStr))) {
+            wrapper.apply("2".equals(flag), "date_format(pay_create_time, '%Y-%m') = {0}", createDateStr);
+            wrapper.apply("3".equals(flag), "date_format(pay_create_time, '%Y-%m-%d') = {0}", createDateStr);
+        }
+
+        String payDateStr = queryTO.getPayDateStr();
+        if ((StringUtils.hasText(payDateStr))) {
+            wrapper.apply("2".equals(flag), "date_format(pay_finish_time, '%Y-%m') = {0}", payDateStr);
+            wrapper.apply("3".equals(flag), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", payDateStr);
+        }
+    }
+
+
+    /**
+     * 清空表数据
+     */
+    @Override
+    public void truncateTable() {
+        this.baseMapper.truncateTable();
+    }
+
+    private List<PayableInfoEntity> getPayableInfo(QueryWrapper<PayableInfoEntity> wrapper) {
+
+        List<PayableInfoEntity> list = payableInfoService.list(wrapper);
+        if (list.size() < 0) {
+            throw new RRException(BizCodeEnume.PAYABLE_INFO_IS_NOT_EXIT);
+        }
+        // List<StudentPayableInfoVO> studentPayableInfoList = new ArrayList<>();
+        // StudentPayableInfoVO studentPayableInfoVO = new StudentPayableInfoVO();
+        // 查询用户是否已经缴费
+//        boolean alreadyPay = payOrderService.isAlreadyPay(studentNo);
+//        payableInfoEntityList.forEach(payableInfoEntity -> {
+//            BeanUtils.copyProperties(payableInfoEntity, studentPayableInfoVO);
+//            studentPayableInfoVO.setPay(alreadyPay);
+//            studentPayableInfoList.add(studentPayableInfoVO);
+//        });
+
+        return list;
+    }
+}

+ 292 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/service/impl/PayableInfoWaterServiceImpl.java

@@ -0,0 +1,292 @@
+package com.chuanghai.smartschool.tuitionpayment.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.BizCodeEnume;
+import com.chuanghai.smartschool.tuitionpayment.common.exception.RRException;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.MyQuery;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageUtils;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayableInfoDao;
+import com.chuanghai.smartschool.tuitionpayment.dao.PayableInfoWaterDao;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayItem;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoEntity;
+import com.chuanghai.smartschool.tuitionpayment.entity.PayableInfoWaterEntity;
+import com.chuanghai.smartschool.tuitionpayment.enume.PayStatus;
+import com.chuanghai.smartschool.tuitionpayment.listener.aliexcel.MyPayableInfoImportListener;
+import com.chuanghai.smartschool.tuitionpayment.listener.aliexcel.MyPayableInfoWaterImportListener;
+import com.chuanghai.smartschool.tuitionpayment.service.*;
+import com.chuanghai.smartschool.tuitionpayment.to.PayOrderQueryTO;
+import com.chuanghai.smartschool.tuitionpayment.utils.OutputTxt;
+import com.chuanghai.smartschool.tuitionpayment.vo.StudentPayableInfoVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@Service("payableInfoWaterService")
+public class PayableInfoWaterServiceImpl extends ServiceImpl<PayableInfoWaterDao, PayableInfoWaterEntity> implements PayableInfoWaterService {
+
+    @Autowired
+    private PayableInfoWaterService payableInfoWaterService;
+    @Autowired
+    private PayableInfoService payableInfoService;
+    @Autowired
+    private PayItemService payItemService;
+
+    /**
+     * 导入学生应缴信息原始数据
+     *
+     * @param file
+     */
+    @Transactional
+    @Override
+    public void importByExcel(MultipartFile file) throws IOException {
+
+        // 清除之前的表数据
+        List<PayableInfoWaterEntity> payableInfoWater = payableInfoWaterService.list();
+        if (payableInfoWater.size() > 0){
+            QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+            wrapper.eq("payment_item", payableInfoWater.get(0).getPaymentItem());
+            List<PayableInfoWaterEntity> infoEntityList = payableInfoWaterService.list(wrapper);
+            List<Long> idList = infoEntityList.stream().map(PayableInfoWaterEntity::getId).collect(Collectors.toList());
+            payableInfoWaterService.removeByIds(idList);
+        }
+
+
+        EasyExcel.read(file.getInputStream(),
+                PayableInfoWaterEntity.class,
+                new MyPayableInfoWaterImportListener(this))
+                .sheet()
+                .doRead();
+
+    }
+
+
+    public String queryPayItemByName(String name) {
+        QueryWrapper<PayItem> wapper = new QueryWrapper<>();
+        wapper.eq("item_name", name);
+        List<PayItem> list = payItemService.list(wapper);
+        String itemAccount = "";
+        if (list.size() > 0) {
+            PayItem payItem = list.get(0);
+            itemAccount = payItem.getItemAccount();
+            String start = itemAccount.substring(0, 3);
+            String end = itemAccount.substring(itemAccount.length() - 4);
+            itemAccount = payItem.getItemBank() + " (" + start + "****" + end + ")";
+        }
+        return itemAccount;
+    }
+
+    @Override
+    public PageUtils queryPage(PayOrderQueryTO queryTO,PageParam pageParam ) {
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StringUtils.hasText(queryTO.getItemName()),"payment_item",queryTO.getItemName());
+        if (StringUtils.hasText(queryTO.getKeyword())) {
+            wrapper.and(w -> w.like("student_no", queryTO.getKeyword())
+                    .or()
+                    .like("student_name", queryTO.getKeyword()));
+        }
+        if (StringUtils.hasText(queryTO.getPayStatus())) {
+            wrapper.eq("pay_item_type", queryTO.getPayStatus());
+        }
+        wrapper.apply(StringUtils.hasText(queryTO.getCreateDateStr()), "date_format(pay_create_time, '%Y-%m-%d') = {0}", queryTO.getCreateDateStr());
+        wrapper.apply(StringUtils.hasText(queryTO.getPayDateStr()), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", queryTO.getPayDateStr());
+
+        IPage<PayableInfoWaterEntity> page = this.page(
+                new MyQuery<PayableInfoWaterEntity>().getPage(pageParam),
+                wrapper
+        );
+        return new PageUtils(page);
+    }
+
+    public String queryAmount(String itemName, String payItemType, String keyword, String payStatus, String createTime, String payTime) {
+
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like("student_no", keyword)
+                    .or()
+                    .like("student_name", keyword));
+        }
+        if (StringUtils.hasText(payStatus)) {
+            wrapper.eq("pay_item_type", payStatus);
+        }
+        wrapper.apply(StringUtils.hasText(createTime), "date_format(pay_create_time, '%Y-%m-%d') = {0}", createTime);
+        wrapper.apply(StringUtils.hasText(payTime), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", payTime);
+
+        if (StringUtils.hasText(itemName)) {
+            wrapper.eq("pay_item_type", payItemType)
+                    .eq("payment_item", itemName)
+                    .select("ifnull(sum(real_pay_amount), 0) as total,count(id) as count");
+        }
+
+        List<PayableInfoWaterEntity> list = this.payableInfoWaterService.list(wrapper);
+        if (list.size() > 0) {
+            Map<String, Object> resultMap = this.getMap(wrapper);
+            String count = String.valueOf(resultMap.get("count"));
+            return new BigDecimal(String.valueOf(resultMap.get("total"))).setScale(2, BigDecimal.ROUND_HALF_UP) + "-" + count;
+        } else {
+            return "-";
+        }
+    }
+
+    /**
+     * 下载缴费的名单的txt文件
+     *
+     * @param response
+    //     * @param flag
+    //     * @param dateStr
+     */
+    @Override
+    public void exportTxt(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException {
+
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StringUtils.hasText(queryTO.getItemName()),"payment_item",queryTO.getItemName());
+
+        wrapper.eq(StringUtils.hasText(queryTO.getPayStatus()),"pay_item_type", queryTO.getPayStatus());
+        wrapper.eq(StringUtils.hasText(queryTO.getPayMethod()), "pay_method", queryTO.getPayMethod());
+        if (queryTO.getDownIds() != null && queryTO.getDownIds().size() > 0) {
+            wrapper.in("student_no", queryTO.getDownIds());
+        }
+        wrapper.apply(StringUtils.hasText(queryTO.getCreateDateStr()), "date_format(pay_create_time, '%Y-%m-%d') = {0}", queryTO.getCreateDateStr());
+        wrapper.apply(StringUtils.hasText(queryTO.getPayDateStr()), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", queryTO.getPayDateStr());
+//        String flag = queryTO.getFlag();
+//        String createDateStr = queryTO.getCreateDateStr();
+//        if ((StringUtils.hasText(createDateStr))) {
+//            wrapper.apply("2".equals(flag), "date_format(pay_create_time, '%Y-%m') = {0}", createDateStr);
+//            wrapper.apply("3".equals(flag), "date_format(pay_create_time, '%Y-%m-%d') = {0}", createDateStr);
+//        }
+//
+//        String payDateStr = queryTO.getPayDateStr();
+//        if ((StringUtils.hasText(payDateStr))) {
+//            wrapper.apply("2".equals(flag), "date_format(pay_finish_time, '%Y-%m') = {0}", payDateStr);
+//            wrapper.apply("3".equals(flag), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", payDateStr);
+//        }
+
+        wrapper.orderByDesc("pay_finish_time");
+        List<PayableInfoWaterEntity> parOrder = this.list(wrapper);
+        String outPutStr = "";
+        if (parOrder.size() > 0){
+            JSONArray jsonArray = new JSONArray();
+            jsonArray.addAll(parOrder);
+            for (int i = 0; i < jsonArray.size(); i++) {
+                PayableInfoWaterEntity payableInfoWaterEntity = (PayableInfoWaterEntity) jsonArray.get(i);
+                outPutStr += payableInfoWaterEntity.getStudentNo() + "\t" + payableInfoWaterEntity.getStudentName() + "\t" + payableInfoWaterEntity.getRealPayAmount() + "\t" +
+                        payableInfoWaterEntity.getPayableAccount() + "\t" +payableInfoWaterEntity.getPayAmountDetail() + "\t" +payableInfoWaterEntity.getDorm() + "\t" +
+                        payableInfoWaterEntity.getOrderNotice() + "\t" +payableInfoWaterEntity.getPaymentItem() + "\r";
+            }
+        }
+
+        new OutputTxt().outTxtWater(response, outPutStr);
+    }
+
+    @Override
+    public List<PayableInfoWaterEntity> getPayableInfoWaterByCardNumber(String cardNumber, String studentName) {
+        // 查询用户基本的缴费信息
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper();
+        wrapper.eq("student_no", cardNumber);
+        wrapper.eq(StringUtils.hasText(studentName),"student_name", studentName);
+        wrapper.eq("pay_item_type","1");
+        wrapper.eq("pay_notice_type","2");
+        return getPayableInfoWater(wrapper);
+    }
+
+
+    private List<PayableInfoWaterEntity> getPayableInfoWater(QueryWrapper<PayableInfoWaterEntity> wrapper) {
+        List<PayableInfoWaterEntity> list = payableInfoWaterService.list(wrapper);
+
+        if (list.size() < 0) {
+            throw new RRException(BizCodeEnume.PAYABLE_INFO_IS_NOT_EXIT);
+        }
+        return list;
+    }
+
+
+
+    /**
+     * 下载完成缴费的名单
+     *
+     * @param response
+     * @param queryTO 查询条件
+    // * @param downIds  勾选的id
+     */
+    @Override
+    public void downloadResult(HttpServletResponse response, PayOrderQueryTO queryTO) throws IOException {
+
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+
+        commonWrapper(wrapper, queryTO);
+
+        wrapper.orderByDesc("pay_finish_time").orderByDesc("pay_create_time");
+        List<PayableInfoWaterEntity> parOrder = this.list(wrapper);
+        String fileName = URLEncoder.encode("水费缴费学生名单" + new Date().getTime(), "UTF-8");
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+
+        EasyExcel.write(response.getOutputStream(), PayableInfoWaterEntity.class).sheet("水费缴费学生名单").doWrite(parOrder);
+    }
+
+
+    /**
+     * 构建公共的查询wrapper
+     *
+     * @param wrapper
+     * @param queryTO
+     */
+    private void commonWrapper(QueryWrapper<PayableInfoWaterEntity> wrapper, PayOrderQueryTO queryTO) {
+        wrapper.eq(StringUtils.hasText(queryTO.getPayStatus()), "pay_item_type", queryTO.getPayStatus());
+        wrapper.eq(StringUtils.hasText(queryTO.getPayMethod()), "pay_method", queryTO.getPayMethod());
+        String keyword = queryTO.getKeyword();
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like("student_name", keyword)
+                    .or()
+                    .like("student_no", keyword));
+        }
+        wrapper.eq("payment_item", queryTO.getItemName());
+
+
+        String flag = queryTO.getFlag();
+        String createDateStr = queryTO.getCreateDateStr();
+        if ((StringUtils.hasText(createDateStr))) {
+            wrapper.apply("2".equals(flag), "date_format(pay_create_time, '%Y-%m') = {0}", createDateStr);
+            wrapper.apply("3".equals(flag), "date_format(pay_create_time, '%Y-%m-%d') = {0}", createDateStr);
+        }
+
+        String payDateStr = queryTO.getPayDateStr();
+        if ((StringUtils.hasText(payDateStr))) {
+            wrapper.apply("2".equals(flag), "date_format(pay_finish_time, '%Y-%m') = {0}", payDateStr);
+            wrapper.apply("3".equals(flag), "date_format(pay_finish_time, '%Y-%m-%d') = {0}", payDateStr);
+        }
+    }
+
+    @Override
+   public PayableInfoWaterEntity getByStudentNo(String studentNo,String itemName,String payYear){
+        QueryWrapper<PayableInfoWaterEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq("student_no",studentNo);
+        wrapper.eq("payment_item",itemName);
+        wrapper.eq("pay_month",payYear);
+        PayableInfoWaterEntity one = payableInfoWaterService.getOne(wrapper);
+        return  one;
+    }
+
+
+}

+ 73 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/to/DeletePayableInfoTO.java

@@ -0,0 +1,73 @@
+package com.chuanghai.smartschool.tuitionpayment.to;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Author: codingliang
+ * @Description: 删除缴费信息TO
+ * @Date: 2021-08-20 11:22
+ * @Version: V1.0
+ **/
+@Data
+public class DeletePayableInfoTO {
+
+    /**
+     * 学号
+     */
+    private String studentNo;
+    /**
+     * 姓名
+     */
+    private String studentName;
+    /**
+     * 年级
+     */
+    private String grade;
+    /**
+     * 收费年度
+     */
+    private String years;
+    /**
+     * 学院名称
+     */
+    private String collegeName;
+    /**
+     * 专业名称
+     */
+    private String majorName;
+    /**
+     * 班级名称
+     */
+    private String className;
+    /**
+     * 应付金额
+     */
+    private BigDecimal realPayAmount;
+    /**
+     * 备注
+     */
+    private String payItemNote;
+    /**
+     * 校区
+     */
+    private String studentCampus;
+    /**
+     * 必缴费用 教材费:1000\学费:18000\住宿费:1800
+     */
+    private String mustMoney;
+    /**
+     * 非必缴费用 教材费:1000\学费:18000\住宿费:1800
+     */
+    private String notMustMoney;
+    /**
+     * 应付详情 格式:教材费:1000\学费:18000\住宿费:1800\N教学设备费:100.00   每笔缴费前需添加标识字母 N(非必缴费用)
+     */
+    private String payItemDetail;
+
+    /**
+     * 提示信息
+     */
+    private String msg;
+}

+ 45 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/to/FeedbackMsgCreateTO.java

@@ -0,0 +1,45 @@
+package com.chuanghai.smartschool.tuitionpayment.to;
+
+import lombok.Builder;
+import lombok.Data;
+import org.assertj.core.internal.bytebuddy.implementation.bind.annotation.Default;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+/**
+ * @Author: codingliang
+ * @Description: 反馈信息创建TO
+ * @Date: 2021-08-13 9:25
+ * @Version: V1.0
+ **/
+@Data
+public class FeedbackMsgCreateTO {
+
+    /**
+     * 反馈者姓名
+     */
+    @NotBlank(message = "反馈者姓名不能为空")
+    private String feedbackPersonName;
+    /**
+     * 反馈者电话
+     */
+    @NotBlank(message = "反馈者电话不能为空")
+    private String feedbackPersonPhone;
+    /**
+     * 反馈类别
+     */
+    @NotBlank(message = "反馈类别不能为空")
+    private String feedbackItemName;
+    /**
+     * 反馈问题,不要超过512个字符
+     */
+    @NotBlank(message = "反馈信息不能为空")
+    @Size(max = 512, message = "反馈信息内容超长")
+    private String feedbackInfo;
+
+    /**
+     * 反馈通知状态
+     */
+    private String feedbackNoticeType;
+}

+ 57 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/to/PayOrderQueryTO.java

@@ -0,0 +1,57 @@
+package com.chuanghai.smartschool.tuitionpayment.to;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Author: codingliang
+ * @Description: 支付订单查询to
+ * @Date: 2021-08-13 11:10
+ * @Version: V1.0
+ **/
+@Data
+public class PayOrderQueryTO {
+
+    /**
+     * 支付状态 不传查所有,1未支付、2支付成功
+     */
+    private String payStatus;
+    /**
+     * 支付方式 不传查所有,1建行支付、2江西农商行支付
+     * @since 0.1.0
+     */
+    private String payMethod;
+    /**
+     * 关键字,支持缴费用户姓名、班级、订单号搜索
+     */
+    private String keyword;
+    /**
+     * 查询标志,1查询所有数据、2查询指定月份数据、3查询指定日期数据
+     */
+    private String flag;
+    /**
+     *创建时间月份或日期,当flag为2、3时必传,月份格式:yyyy-MM、日期格式:yyyy-MM-dd
+     */
+    private String createDateStr;
+    /**
+     * 支付时间月份或日期,当flag为2、3时必传,月份格式:yyyy-MM、日期格式:yyyy-MM-dd
+     */
+    private String payDateStr;
+    /**
+     * 缴费项目
+     */
+    private String itemName;
+    /**
+     * 查询缴费金额所需的 支付状态参数   1 未支付  2 已支付
+     */
+    private String statusMoery;
+    /**
+     * 支付年度
+     */
+    private String payYear;
+    /**
+     * 勾选的学号
+     */
+    private List<String> downIds;
+}

+ 11 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/to/PayableInfoQueryTO.java

@@ -0,0 +1,11 @@
+package com.chuanghai.smartschool.tuitionpayment.to;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/28 星期二 17:49
+ * @Description: com.chuanghai.smartschool.tuitionpayment.to
+ * @version: 1.0
+ */
+public class PayableInfoQueryTO {
+    private String keyword;
+}

+ 95 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/CCBRSASig.java

@@ -0,0 +1,95 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+import netpay.merchant.crypto.ABAProvider;
+import netpay.merchant.crypto.RSAPrivKeyCrt;
+import netpay.merchant.crypto.RSAPubKey;
+
+import java.security.Security;
+import java.security.Signature;
+
+/**
+ * @Author: codingliang
+ * @Description: 建行Rsa工具
+ * @Date: 2021-08-03 16:11
+ * @Version: V1.0
+ **/
+public class CCBRSASig {
+
+    /**
+     * 生成签名
+     * @param src 原始串
+     * @param priKey 私钥
+     * @return
+     */
+    public static String generateSigature(String src, String priKey) {
+        try {
+            Security.addProvider(new ABAProvider());
+            Signature sigEng = Signature.getInstance("MD5withRSA", "ABA");
+
+            byte[] pribyte = hexStrToBytes(priKey.trim());
+            sigEng.initSign(new RSAPrivKeyCrt(pribyte));
+            sigEng.update(src.getBytes());
+
+            byte[] signature = sigEng.sign();
+            return bytesToHexStr(signature);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 验证签名
+     * @param sign 签名
+     * @param src 原始串
+     * @param pubKey 公钥
+     * @return
+     */
+    public static boolean verifySigature(String sign, String src, String pubKey) {
+        try {
+            Security.addProvider(new ABAProvider());
+            Signature sigEng = Signature.getInstance("MD5withRSA", "ABA");
+
+            byte[] pubbyte = hexStrToBytes(pubKey.trim());
+            sigEng.initVerify(new RSAPubKey(pubbyte));
+            sigEng.update(src.getBytes());
+
+            byte[] sign1 = hexStrToBytes(sign);
+            if (sigEng.verify(sign1)) {
+                return true;
+            } else {
+                return false;
+            }
+
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    private static final String bytesToHexStr(
+            byte[] bcd) {
+        StringBuffer s = new StringBuffer(bcd.length * 2);
+
+        for (int i = 0; i < bcd.length; i++) {
+            s.append(bcdLookup[(bcd[i] >>> 4) & 0x0f]);
+            s.append(bcdLookup[bcd[i] & 0x0f]);
+        }
+
+        return s.toString();
+    }
+
+    private static final byte[] hexStrToBytes(
+            String s) {
+        byte[] bytes;
+
+        bytes = new byte[s.length() / 2];
+
+        for (int i = 0; i < bytes.length; i++) {
+            bytes[i] = (byte) Integer.parseInt(
+                    s.substring(2 * i, 2 * i + 2), 16);
+        }
+
+        return bytes;
+    }
+
+    private static final char[] bcdLookup = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+}

+ 34 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/FileUtilss.java

@@ -0,0 +1,34 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/29 星期三 10:44
+ * @Description: com.chuanghai.smartschool.tuitionpayment.utils
+ * @version: 1.0
+ */
+public abstract class FileUtilss {
+
+    /**
+     * 生成导出附件中文名。应对导出文件中文乱码
+     * <p>
+     * response.addHeader("Content-Disposition", "attachment; filename=" + cnName);
+     *
+     * @param cnName
+     * @param defaultName
+     * @return
+     */
+    public static String genAttachmentFileName(String cnName, String defaultName) {
+        try {
+//            fileName = URLEncoder.encode(fileName, "UTF-8");
+            cnName = new String(cnName.getBytes("gb2312"), "ISO8859-1");
+            /*
+            if (fileName.length() > 150) {
+                fileName = new String( fileName.getBytes("gb2312"), "ISO8859-1" );
+            }
+            */
+        } catch (Exception e) {
+            cnName = defaultName;
+        }
+        return cnName;
+    }
+}

+ 164 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/JXNXSPayUtil.java

@@ -0,0 +1,164 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+
+import org.springframework.boot.configurationprocessor.json.JSONObject;
+import org.springframework.util.StringUtils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+
+/**
+ * 农商行支付工具类
+ *
+ * Description
+ * Create 2017-03-07 14:01:23
+ *
+ * @author Benny.YEE
+ */
+public class JXNXSPayUtil {
+
+    public static String SHA1(String decript) {
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-1");
+            digest.update(decript.getBytes("UTF-8"));
+            byte[] messageDigest = digest.digest();
+            StringBuilder hexString = new StringBuilder();
+            for (byte message : messageDigest) {
+                String shaHex = Integer.toHexString(message & 0xFF);
+                if (shaHex.length() < 2)
+                    hexString.append(0);
+
+                hexString.append(shaHex);
+            }
+            return hexString.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    /**
+     * 签名
+     *
+     * @param data
+     * @return
+     */
+    public static String sign(Map<String, String> data) {
+        String sign = null;
+
+        try {
+            // A~z排序 (加上open_key)
+            Set<String> keySet = data.keySet();
+            String[] keyArray = keySet.toArray(new String[keySet.size()]);
+            Arrays.sort(keyArray);
+            StringBuilder sb = new StringBuilder();
+            for (String k : keyArray) {
+                if (k.equals("sign")) {  // 删除sign节点
+                    continue;
+                }
+                sb.append(k).append("=").append(data.get(k).trim()).append("&");
+            }
+
+            String sbStr = sb.toString();
+            String sortStr = sbStr.substring(0, sbStr.length() - 1);
+
+            // sha1加密(小写)
+            String sha1 = SHA1(sortStr).toLowerCase();
+
+            // md5加密(小写)
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            byte[] digest = md5.digest(sha1.getBytes("utf-8"));
+            String resultString = byte2hex(digest);
+
+            sign = resultString.toLowerCase();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return sign;
+    }
+
+    /**
+     * AES加密,再二进制转十六进制(bin2hex)
+     * @param dataJsonStr 需要加密的字符串
+     * @param key key
+     * @throws Exception
+     */
+    public static String handleEncrypt(String dataJsonStr, String key) throws Exception {
+
+        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ASCII"), "AES");
+        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+        cipher.init(1, skeySpec);
+        byte[] encrypted = cipher.doFinal(dataJsonStr.getBytes("UTF-8"));
+
+        return byte2hex(encrypted);
+    }
+
+    public static String decrypt(String sSrc, String sKey) throws Exception {
+        SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes("ASCII"), "AES");
+        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+        cipher.init(2, skeySpec);
+        byte[] encrypted1 = hex2byte(sSrc);
+        byte[] original = cipher.doFinal(encrypted1);
+        return new String(original, "UTF-8");
+    }
+
+    /**
+     * 验签
+     *
+     * @param params
+     * @param key 农商openKey
+     * @return
+     */
+    public static Boolean verifySign(Map<String, String> params, String key) {
+        String respSign = params.get("sign");
+
+        if (StringUtils.hasText(respSign)) {
+            params.put("open_key", key);
+            String veriSign = sign(params);
+            if (respSign.equals(veriSign)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * byte数组转十六进制字符串
+     */
+    public static String byte2hex(byte[] result) {
+        StringBuffer sb = new StringBuffer(result.length * 2);
+        for (int i = 0; i < result.length; i++) {
+            int hight = ((result[i] >> 4) & 0x0f);
+            int low = result[i] & 0x0f;
+            sb.append(hight > 9 ? (char) ((hight - 10) + 'a') : (char) (hight + '0'));
+            sb.append(low > 9 ? (char) ((low - 10) + 'a') : (char) (low + '0'));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 十六进制字符串转byte数组
+     */
+    public static byte[] hex2byte(String strhex) {
+        if (strhex == null)
+            return null;
+
+        int l = strhex.length();
+        if (l % 2 == 1)
+            return null;
+
+        byte[] b = new byte[l / 2];
+        for (int i = 0; i != l / 2; ++i)
+            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
+
+        return b;
+    }
+
+}

+ 122 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/ListPageUtil.java

@@ -0,0 +1,122 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/4/27 星期三 16:05
+ * @Description: com.chuanghai.recognition.utils
+ * @version: 1.0
+ */
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class ListPageUtil<T> {
+    /**
+     * 原集合
+     */
+    private List<T> data;
+
+    /**
+     * 上一页
+     */
+    private int lastPage;
+
+    /**
+     * 当前页
+     */
+    private int currPage;
+
+    /**
+     * 下一页
+     */
+    private int nextPage;
+
+    /**
+     * 每页条数
+     */
+    private int pageSize;
+
+    /**
+     * 总页数
+     */
+    private int totalPage;
+
+    /**
+     * 总数据条数
+     */
+    private int totalCount;
+
+    public ListPageUtil(List<T> data, int currPage, int pageSize) {
+        if (data == null || data.isEmpty()) {
+            throw new IllegalArgumentException("data must be not empty!");
+        }
+
+        this.data = data;
+        this.pageSize = pageSize;
+        this.currPage = currPage;
+        this.totalCount = data.size();
+        this.totalPage = (totalCount + pageSize - 1) / pageSize;
+        this.lastPage = currPage - 1 > 1 ? currPage - 1 : 1;
+        this.nextPage = currPage >= totalPage ? totalPage : currPage + 1;
+
+    }
+
+    /**
+     * 得到分页后的数据
+     *
+     * @return 分页后结果
+     */
+    public List<T> getPagedList() {
+        int fromIndex = (currPage - 1) * pageSize;
+        if (fromIndex >= data.size()) {
+            return Collections.emptyList();//空数组
+        }
+        if (fromIndex < 0) {
+            return Collections.emptyList();//空数组
+        }
+        int toIndex = currPage * pageSize;
+        if (toIndex >= data.size()) {
+            toIndex = data.size();
+        }
+        return data.subList(fromIndex, toIndex);
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public List<T> getData() {
+        return data;
+    }
+
+    public int getLastPage() {
+        return lastPage;
+    }
+
+    public int getNowPage() {
+        return currPage;
+    }
+
+    public int getNextPage() {
+        return nextPage;
+    }
+
+    public int getTotalPage() {
+        return totalPage;
+    }
+
+    public int getTotalCount() {
+        return totalCount;
+    }
+
+    public static void main(String[] args) {
+        Integer[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+        List<Integer> list = Arrays.asList(array);
+
+        ListPageUtil<Integer> listPageUtil = new ListPageUtil<Integer>(list, 2, 4);
+        List<Integer> pagedList = listPageUtil.getPagedList();
+        System.out.println(pagedList);
+    }
+}
+

+ 110 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/MyAES.java

@@ -0,0 +1,110 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+import com.chuanghai.smartschool.tuitionpayment.config.WeixiaoConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * @Author: codingliang
+ * @Description: 微校接口数据加解密
+ * @Date: 2021-06-21 10:26
+ * @Version: V1.0
+ **/
+@Component
+public class MyAES {
+
+    @Autowired
+    private WeixiaoConfig weixiaoConfig;
+
+    /**
+     * 加密
+     * @param sSrc 需要加密的字串
+     * @return
+     * @throws Exception
+     */
+    public String encrypt(String sSrc) throws Exception {
+        String sKey = weixiaoConfig.getAppKey();
+        String sIv = weixiaoConfig.getAppSecret();
+        sIv = sIv.substring(0, 16); // app_secret 取前16位
+
+        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+        int blockSize = cipher.getBlockSize();
+
+        byte[] dataBytes = sSrc.getBytes();
+        int plaintextLength = dataBytes.length;
+        if (plaintextLength % blockSize != 0) {
+            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
+        }
+
+        byte[] plaintext = new byte[plaintextLength];
+        System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
+
+        SecretKeySpec keyspec = new SecretKeySpec(sKey.getBytes(), "AES");
+        IvParameterSpec ivspec = new IvParameterSpec(sIv.getBytes());
+
+        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
+        byte[] encrypted = cipher.doFinal(plaintext);
+
+        return byte2hex(encrypted).toLowerCase();
+    }
+
+    /**
+     * 解密
+     * @param sSrc 需要解密的字串
+     * @return
+     * @throws Exception
+     */
+    public String decrypt(String sSrc) throws Exception {
+        String sKey = weixiaoConfig.getAppKey();
+        String sIv = weixiaoConfig.getAppSecret();
+        sIv = sIv.substring(0, 16); // app_secret 取前16位
+
+        byte[] encrypted1 = hex2byte(sSrc);
+
+        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+        SecretKeySpec keyspec = new SecretKeySpec(sKey.getBytes(), "AES");
+        IvParameterSpec ivspec = new IvParameterSpec(sIv.getBytes());
+
+        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
+
+        byte[] original = cipher.doFinal(encrypted1);
+        String originalString = new String(original);
+
+        return originalString;
+    }
+
+    private byte[] hex2byte(String strhex) {
+        if (strhex == null) {
+            return null;
+        }
+        int l = strhex.length();
+        if (l % 2 == 1) {
+            return null;
+        }
+        byte[] b = new byte[l / 2];
+        for (int i = 0; i != l / 2; i++) {
+            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2),
+                    16);
+        }
+
+        return b;
+    }
+
+    private String byte2hex(byte[] b) {
+        String hs = "";
+        String stmp = "";
+        for (int n = 0; n < b.length; n++) {
+            stmp = (Integer.toHexString(b[n] & 0XFF));
+            if (stmp.length() == 1) {
+                hs = hs + "0" + stmp;
+            } else {
+                hs = hs + stmp;
+            }
+        }
+        return hs.toUpperCase();
+    }
+}

+ 96 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/MySignatureUtil.java

@@ -0,0 +1,96 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @Author: codingliang
+ * @Description: 签名工具
+ * @Date: 2021-07-02 10:53
+ * @Version: V1.0
+ **/
+public class MySignatureUtil {
+
+    public enum SignType {
+        MD5, HMACSHA256
+    }
+
+    /**
+     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
+     *
+     * 设所有发送或者接收到的数据为集合M,将集合M内参数值的参数按照参数名ASCII码从小到大排序(字典序),
+     * 使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。 特别注意以下重要规则:
+     *      参数名ASCII码从小到大排序(字典序);
+     *      如果参数的值为空不参与签名;
+     *      参数名区分大小写;
+     *      验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
+     * 在stringA最后拼接上&key=APP_SECRET得到stringSignTemp字符串,
+     * 并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
+     * @param data 待签名数据
+     * @param key API密钥
+     * @param signType 签名方式
+     * @return 签名
+     */
+    public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
+        Set<String> keySet = data.keySet();
+        String[] keyArray = keySet.toArray(new String[keySet.size()]);
+        Arrays.sort(keyArray);
+        StringBuilder sb = new StringBuilder();
+        for (String k : keyArray) {
+            if (k.equals("sign")) {
+                continue;
+            }
+            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
+                sb.append(k).append("=").append(data.get(k).trim()).append("&");
+        }
+        sb.append("key=").append(key);
+        if (SignType.MD5.equals(signType)) {
+            return MD5(sb.toString()).toUpperCase();
+        }
+        else if (SignType.HMACSHA256.equals(signType)) {
+            return HMACSHA256(sb.toString(), key);
+        }
+        else {
+            throw new Exception(String.format("Invalid sign_type: %s", signType));
+        }
+    }
+
+    /**
+     * 生成 MD5
+     *
+     * @param data 待处理数据
+     * @return MD5结果
+     */
+    public static String MD5(String data) throws Exception {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        byte[] array = md.digest(data.getBytes("UTF-8"));
+        StringBuilder sb = new StringBuilder();
+        for (byte item : array) {
+            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
+        }
+        return sb.toString().toUpperCase();
+    }
+
+    /**
+     * 生成 HMACSHA256
+     * @param data 待处理数据
+     * @param key 密钥
+     * @return 加密结果
+     * @throws Exception
+     */
+    public static String HMACSHA256(String data, String key) throws Exception {
+        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
+        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
+        sha256_HMAC.init(secret_key);
+        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
+        StringBuilder sb = new StringBuilder();
+        for (byte item : array) {
+            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
+        }
+        return sb.toString().toUpperCase();
+    }
+}

+ 64 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/MyUtil.java

@@ -0,0 +1,64 @@
+package com.chuanghai.smartschool.tuitionpayment.utils;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @Author: codingliang
+ * @Description: 自定义工具类
+ * @Date: 2021-08-20 10:36
+ * @Version: V1.0
+ **/
+public class MyUtil {
+
+    /**
+     * 计算学生年级
+     *
+     * @param grade 入学年份
+     * @return 年级,如当前是2021年,学生入学年份是2021,则返回 1
+     */
+    public static Integer calcStudentGrade(Integer grade) {
+        LocalDate now = LocalDate.now();
+        int currentYear = now.getYear();
+        int currentMonth = now.getMonthValue();
+
+        int currentGrade = currentYear - grade;
+        if (currentGrade < 0) {
+            return 1;
+        } else {
+            if (currentMonth < 7) {
+                return currentYear - grade;
+            } else {
+                return currentYear - grade + 1;
+            }
+        }
+    }
+
+    /**
+     * 将建行拼接的时间转换成localDateTime时间
+     * @param orderDate
+     * @return
+     */
+    public LocalDateTime changeTime(String orderDate) {
+
+        StringBuilder sb = new StringBuilder(orderDate);//构造一个StringBuilder对象
+        sb.insert(4, "-");//在指定的位置1,插入指定的字符串
+        sb.insert(7, "-");//在指定的位置1,插入指定的字符串
+        sb.insert(10, " ");//在指定的位置1,插入指定的字符串
+        sb.insert(13, ":");//在指定的位置1,插入指定的字符串
+        sb.insert(16, ":");//在指定的位置1,插入指定的字符串
+
+        orderDate = sb.toString();
+
+        LocalDateTime dateTime = LocalDateTime.parse(orderDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        return dateTime;
+    }
+
+    public static void main(String[] args) {
+        LocalDateTime localDateTime = new MyUtil().changeTime("20220708091308");
+        System.out.println(localDateTime);
+
+        System.out.println(calcStudentGrade(2022));
+    }
+}

Разница между файлами не показана из-за своего большого размера
+ 179 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/utils/OutputTxt.java


+ 34 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/CreateOrderResultVO.java

@@ -0,0 +1,34 @@
+package com.chuanghai.smartschool.tuitionpayment.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Author: codingliang
+ * @Description: 创建订单成功VO
+ * @Date: 2021-08-12 17:18
+ * @Version: V1.0
+ **/
+@Data
+public class CreateOrderResultVO {
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+    /**
+     * 信息
+     */
+    private String msg;
+    /**
+     * 支付方式 1建行支付、2农商行支付
+     * @since 0.1.0
+     */
+    private String payMethod;
+    /**
+     * 支付金额
+     * @since 0.1.0
+     */
+    private BigDecimal amount;
+}

+ 20 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/CurrentPayMethodVO.java

@@ -0,0 +1,20 @@
+package com.chuanghai.smartschool.tuitionpayment.vo;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * @Author: codingliang
+ * @Description: 当前支付方式VO
+ * @Date: 2021-08-19 11:42
+ * @Version: V1.0
+ **/
+@Data
+@Builder
+public class CurrentPayMethodVO {
+
+    /**
+     * 当前支付方式 1建行支付、2江西农商行支付
+     */
+    private String currentPayMethod;
+}

+ 39 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/FeedbackMsgQueryVO.java

@@ -0,0 +1,39 @@
+package com.chuanghai.smartschool.tuitionpayment.vo;
+
+import com.chuanghai.smartschool.tuitionpayment.common.utils.PageParam;
+import lombok.Data;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/6/27 星期一 15:01
+ * @Description: com.chuanghai.smartschool.tuitionpayment.vo
+ * @version: 1.0
+ */
+@Data
+public class FeedbackMsgQueryVO {
+
+    /**
+     * 反馈订单状态
+     */
+    private String status;
+    /**
+     * 查询关键字
+     */
+    private String keyword;
+    /**
+     * 创建时间
+     */
+    private String createTime;
+
+    /**
+     * 查询项目类别 不传默认查询所有
+     */
+    private String itemName;
+
+    /**
+     * 分页对象
+     */
+    private PageParam pageParam;
+
+
+}

+ 20 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/OrderReceiveVO.java

@@ -0,0 +1,20 @@
+package com.chuanghai.smartschool.tuitionpayment.vo;
+
+import com.chuanghai.smartschool.tuitionpayment.entity.PayOrderEntity;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Author: bingo
+ * @Date: 2022/7/6 星期三 14:46
+ * @Description: com.chuanghai.smartschool.tuitionpayment.vo
+ * @version: 1.0
+ */
+@Data
+public class OrderReceiveVO extends PayOrderEntity {
+    /**
+     * 本次支付所付金额
+     */
+    private BigDecimal nowPayAmount;
+}

+ 26 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/OrderStatusVO.java

@@ -0,0 +1,26 @@
+package com.chuanghai.smartschool.tuitionpayment.vo;
+
+import lombok.Data;
+
+/**
+ * @Author: codingliang
+ * @Description: 订单状态VO
+ * @Date: 2021-08-12 18:57
+ * @Version: V1.0
+ **/
+@Data
+public class OrderStatusVO {
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+    /**
+     * 订单状态 1未支付、2支付成功
+     */
+    private String status;
+    /**
+     * 支付者id
+     */
+    private String payerId;
+}

+ 0 - 0
src/main/java/com/chuanghai/smartschool/tuitionpayment/vo/OutputTxtVO.java


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