Selaa lähdekoodia

Merge branch 'master' into mall_pay

liujunchi 3 vuotta sitten
vanhempi
commit
ef44aeb49f
60 muutettua tiedostoa jossa 1275 lisäystä ja 295 poistoa
  1. 0 5
      audio-analysis/pom.xml
  2. 3 3
      audio-analysis/src/main/java/com/yonge/audio/AudioAnalysisServerApplication.java
  3. 2 9
      audio-analysis/src/main/java/com/yonge/netty/common/message/MessageDispatcher.java
  4. 1 1
      audio-analysis/src/main/java/com/yonge/netty/common/message/MessageHandler.java
  5. 0 128
      audio-analysis/src/main/resources/application-template.yml
  6. 11 0
      audio-analysis/src/main/resources/bootstrap-dev.yml
  7. 0 16
      audio-analysis/src/main/resources/bootstrap-prod.properties
  8. 0 16
      audio-analysis/src/main/resources/bootstrap-sim.properties
  9. 0 16
      audio-analysis/src/main/resources/bootstrap-test.properties
  10. 55 0
      audio-analysis/src/main/resources/logback-spring.xml
  11. 3 0
      cooleshow-cms/src/main/java/com/yonge/cooleshow/cms/controller/HelpCenterContentController.java
  12. 1 1
      cooleshow-cms/src/main/java/com/yonge/cooleshow/cms/dal/entity/HelpCenterContent.java
  13. 1 1
      cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/OmsOrderReturnApplyServiceImpl.java
  14. 4 2
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java
  15. 11 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/UserOrderPayment.java
  16. 16 5
      cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml
  17. 6 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java
  18. 7 6
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java
  19. 10 2
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/UserOrderPaymentServiceImpl.java
  20. 14 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/HomeController.java
  21. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java
  22. 7 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserWithdrawalDao.java
  23. 58 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderRefundReq.java
  24. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/LiveRoom.java
  25. 21 9
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrderRefunds.java
  26. 7 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleEnum.java
  27. 32 20
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/MessageTypeEnum.java
  28. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoomTypeEnum.java
  29. 30 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseGroupService.java
  30. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/HomeService.java
  31. 5 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java
  32. 10 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderRefundsService.java
  33. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderService.java
  34. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserWithdrawalService.java
  35. 25 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseGroupServiceImpl.java
  36. 25 19
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  37. 95 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/HomeServiceImpl.java
  38. 59 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java
  39. 0 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MemberPriceSettingsServiceImpl.java
  40. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserContractRecordServiceImpl.java
  41. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherAuthEntryRecordServiceImpl.java
  42. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherAuthMusicianRecordServiceImpl.java
  43. 62 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderRefundsServiceImpl.java
  44. 38 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java
  45. 10 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserWithdrawalServiceImpl.java
  46. 4 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/VipCardRecordServiceImpl.java
  47. 85 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseHomeVo.java
  48. 56 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/res/RefundCreateRes.java
  49. 32 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  50. 3 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderRefundsMapper.xml
  51. 7 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserWithdrawalMapper.xml
  52. 2 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/MusicSheetController.java
  53. 1 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/PaymentController.java
  54. 6 0
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/StudentLiveRoomController.java
  55. 22 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/UserOrderController.java
  56. 1 1
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/config/ResourceServerConfig.java
  57. 6 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherLiveRoomController.java
  58. 95 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/WithdrawController.java
  59. 113 0
      toolset/thirdparty-component/src/main/java/com/yonge/toolset/thirdparty/lingxinpay/Md5EncryptUtils.java
  60. 147 0
      toolset/thirdparty-component/src/main/java/com/yonge/toolset/thirdparty/lingxinpay/Withdraw.java

+ 0 - 5
audio-analysis/pom.xml

@@ -28,11 +28,6 @@
 		</dependency>
 
 		<dependency>
-			<groupId>org.springframework.cloud</groupId>
-			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
-		</dependency>
-
-		<dependency>
 			<groupId>com.alibaba.cloud</groupId>
 			<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 		</dependency>

+ 3 - 3
audio-analysis/src/main/java/com/yonge/audio/AudioAnalysisServerApplication.java

@@ -21,9 +21,9 @@ import com.yonge.audio.config.LocalFastJsonHttpMessageConverter;
 
 @SpringBootApplication
 @EnableDiscoveryClient
-@EnableFeignClients("com.ym.mec")
-@MapperScan("com.ym.mec.biz.dal.dao")
-@ComponentScan(basePackages = { "com.yonge.netty", "com.ym.mec", "com.yonge.log" })
+@EnableFeignClients("com.yonge.cooleshow")
+@MapperScan("com.yonge.cooleshow.biz.dal.dao")
+@ComponentScan(basePackages = {"com.yonge.netty", "com.yonge.cooleshow.auth", "com.yonge.cooleshow.biz", "com.yonge.cooleshow.common", "com.yonge.cooleshow.common.security","com.yonge.toolset.thirdparty" })
 @Configuration
 @EnableSwagger2Doc
 public class AudioAnalysisServerApplication {

+ 2 - 9
audio-analysis/src/main/java/com/yonge/netty/common/message/MessageDispatcher.java

@@ -18,17 +18,10 @@ public class MessageDispatcher extends SimpleChannelInboundHandler<Message<?>> {
 	@Override
 	protected void channelRead0(ChannelHandlerContext ctx, Message<?> message) {
 		// 获得 type 对应的 MessageHandler 处理器
-		MessageHandler messageHandler = messageHandlerContainer.getMessageHandler(message.getType());
+		MessageHandler<?> messageHandler = messageHandlerContainer.getMessageHandler(message.getType());
 		// 获得 MessageHandler 处理器 的消息类
 		// Class<? extends Message> messageClass = MessageHandlerContainer.getMessageClass(messageHandler);
 		// 执行逻辑
-		executor.submit(new Runnable() {
-
-			@Override
-			public void run() {
-				messageHandler.execute(ctx.channel(), message.getData());
-			}
-
-		});
+		executor.submit(() -> messageHandler.execute(ctx.channel(), message.getData()));
 	}
 }

+ 1 - 1
audio-analysis/src/main/java/com/yonge/netty/common/message/MessageHandler.java

@@ -10,7 +10,7 @@ public interface MessageHandler<T> {
 	 * @param channel 通道
 	 * @param message 消息
 	 */
-	void execute(Channel channel, T message);
+	void execute(Channel channel, Object message);
 
 	/**
 	 * @return 消息类型,即每个 Message 实现类上的 TYPE 静态字段

+ 0 - 128
audio-analysis/src/main/resources/application-template.yml

@@ -1,128 +0,0 @@
-server:
-  port: 9004
-  tomcat:
-    accesslog:
-      enabled: true
-      buffered: true
-      directory: /var/logs
-      file-date-format: -yyyy-MM-dd
-      pattern: common
-      prefix: tomcat-audio
-      rename-on-rotate: false
-      request-attributes-enabled: false
-      rotate: true
-      suffix: .log
-      
-netty:
-  server:
-    port: 8090
-
-eureka:
-  client:
-    serviceUrl:
-      defaultZone: http://admin:admin123@localhost:8761/eureka/eureka/
-    instance: 
-      lease-renewal-interval-in-seconds: 5
-
-spring:
-  application:
-    name: audio-analysis-server
-    
-  datasource:
-    name: test
-    url: jdbc:mysql://47.114.1.200:3306/mec_test?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
-    username: mec_dev
-    password: dayaDataOnline@2019
-    # 使用druid数据源
-    type: com.alibaba.druid.pool.DruidDataSource
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    filters: stat
-    maxActive: 20
-    initialSize: 1
-    maxWait: 60000
-    minIdle: 1
-    timeBetweenEvictionRunsMillis: 60000
-    minEvictableIdleTimeMillis: 300000
-    validationQuery: select 'x'
-    testWhileIdle: true
-    testOnBorrow: false
-    testOnReturn: false
-    poolPreparedStatements: true
-    maxOpenPreparedStatements: 20
-  
-  redis:
-    host: 47.114.1.200
-    port: 6379
-    password: dyym
-    database: 1
-    #连接超时时间(毫秒)
-    timeout: 10000
-    jedis:
-      pool:
-        #连接池最大连接数(使用负值表示没有限制)
-        max-active: 20
-        #连接池最大阻塞等待时间(使用负值表示没有限制)
-        max-wait: 10000
-        #连接池中的最大空闲连接
-        max-idle: 10
-        #连接池中的最小空闲连接
-        min-idle: 5
-    
-
-mybatis:
-    mapperLocations: classpath:config/mybatis/*.xml
-    
-swagger:
-  base-package: com.yonge.audo.controller
-          
-##认证 
-security:
-  oauth2:
-    client:
-      client-id: app
-      client-secret: app
-    resource:
-      token-info-uri: http://localhost:8001/oauth/check_token
-  
-#spring boot admin 相关配置
-management:
-  endpoints:
-    web:
-      exposure:
-        include: "*"
-  endpoint:
-    health:
-      show-details: ALWAYS
-      
-
-ribbon:  
-    ReadTimeout: 60000  
-    ConnectTimeout: 60000
-
-message:
-  debugMode: true
-  
-##支付流水隐藏
-payment:
-  hiddenMode: false
-  #隐藏的支付方式
-  channel: YQPAY
-  
-eseal:
-  tsign:
-    projectid: 4438776254
-    projectSecret: a94cf63d6361084d232f345d71321691
-    apisUrl: http://smlitsm.tsign.cn:8080/tgmonitor/rest/app!getAPIInfo2
-
-push:
-  jiguang:
-    reqURL: https://api.jpush.cn/v3/push
-    appKey:
-      student: 0e7422e1d6e73637e678716a
-      teacher: 7e0282ca92c12c8c45a93bb3
-      system: 496fc1007dea59b1b4252d2b
-    masterSecret:
-      student: c2361016604eab56ab2db2ac
-      teacher: d47430e2f4755ef5dc050ac5
-      system: a5e51e9cdb25417463afbf7a
-    apns_production: false

+ 11 - 0
audio-analysis/src/main/resources/bootstrap-dev.yml

@@ -0,0 +1,11 @@
+spring:
+  cloud:
+    nacos:
+      config:
+        server-addr: 47.114.1.200:8848
+        namespace: 6f8374a9-598f-4889-bb17-476070ffb8de
+        group: DEFAULT_GROUP
+        prefix: audio-analysis-dev
+        file-extension: yaml
+        enabled: true
+        refresh-enabled: true

+ 0 - 16
audio-analysis/src/main/resources/bootstrap-prod.properties

@@ -1,16 +0,0 @@
-#\u6307\u5b9a\u5f00\u53d1\u73af\u5883
-#spring.profiles.active=dev
-#\u670d\u52a1\u5668\u5730\u5740
-spring.cloud.nacos.config.server-addr=47.96.80.97:8848
-#\u9ed8\u8ba4\u4e3aPublic\u547d\u540d\u7a7a\u95f4,\u53ef\u4ee5\u7701\u7565\u4e0d\u5199
-spring.cloud.nacos.config.namespace=f40a7594-4bd0-4bc6-8397-9353c6d2e63a
-#\u6307\u5b9a\u914d\u7f6e\u7fa4\u7ec4 --\u5982\u679c\u662fPublic\u547d\u540d\u7a7a\u95f4 \u5219\u53ef\u4ee5\u7701\u7565\u7fa4\u7ec4\u914d\u7f6e
-spring.cloud.nacos.config.group=DEFAULT_GROUP
-#\u6587\u4ef6\u540d -- \u5982\u679c\u6ca1\u6709\u914d\u7f6e\u5219\u9ed8\u8ba4\u4e3a ${spring.appliction.name}
-spring.cloud.nacos.config.prefix=audio-analysis
-#\u6307\u5b9a\u6587\u4ef6\u540e\u7f00
-spring.cloud.nacos.config.file-extension=yaml
-#\u662f\u5426\u52a8\u6001\u5237\u65b0
-spring.cloud.nacos.config.refresh.enabled=true
-#\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
-spring.cloud.nacos.config.enabled=true

+ 0 - 16
audio-analysis/src/main/resources/bootstrap-sim.properties

@@ -1,16 +0,0 @@
-#\u6307\u5b9a\u5f00\u53d1\u73af\u5883
-#spring.profiles.active=dev
-#\u670d\u52a1\u5668\u5730\u5740
-spring.cloud.nacos.config.server-addr=47.114.1.200:8848
-#\u9ed8\u8ba4\u4e3aPublic\u547d\u540d\u7a7a\u95f4,\u53ef\u4ee5\u7701\u7565\u4e0d\u5199
-spring.cloud.nacos.config.namespace=763783fd-dfd1-4a44-857e-42a27448c42c
-#\u6307\u5b9a\u914d\u7f6e\u7fa4\u7ec4 --\u5982\u679c\u662fPublic\u547d\u540d\u7a7a\u95f4 \u5219\u53ef\u4ee5\u7701\u7565\u7fa4\u7ec4\u914d\u7f6e
-spring.cloud.nacos.config.group=DEFAULT_GROUP
-#\u6587\u4ef6\u540d -- \u5982\u679c\u6ca1\u6709\u914d\u7f6e\u5219\u9ed8\u8ba4\u4e3a ${spring.appliction.name}
-spring.cloud.nacos.config.prefix=audio-analysis
-#\u6307\u5b9a\u6587\u4ef6\u540e\u7f00
-spring.cloud.nacos.config.file-extension=yaml
-#\u662f\u5426\u52a8\u6001\u5237\u65b0
-spring.cloud.nacos.config.refresh.enabled=true
-#\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
-spring.cloud.nacos.config.enabled=true

+ 0 - 16
audio-analysis/src/main/resources/bootstrap-test.properties

@@ -1,16 +0,0 @@
-#\u6307\u5b9a\u5f00\u53d1\u73af\u5883
-#spring.profiles.active=dev
-#\u670d\u52a1\u5668\u5730\u5740
-spring.cloud.nacos.config.server-addr=47.114.176.40:8848
-#\u9ed8\u8ba4\u4e3aPublic\u547d\u540d\u7a7a\u95f4,\u53ef\u4ee5\u7701\u7565\u4e0d\u5199
-spring.cloud.nacos.config.namespace=46f06363-b9d6-46f0-9cd7-7b33dcf26bb0
-#\u6307\u5b9a\u914d\u7f6e\u7fa4\u7ec4 --\u5982\u679c\u662fPublic\u547d\u540d\u7a7a\u95f4 \u5219\u53ef\u4ee5\u7701\u7565\u7fa4\u7ec4\u914d\u7f6e
-spring.cloud.nacos.config.group=DEFAULT_GROUP
-#\u6587\u4ef6\u540d -- \u5982\u679c\u6ca1\u6709\u914d\u7f6e\u5219\u9ed8\u8ba4\u4e3a ${spring.appliction.name}
-spring.cloud.nacos.config.prefix=audio-analysis
-#\u6307\u5b9a\u6587\u4ef6\u540e\u7f00
-spring.cloud.nacos.config.file-extension=yaml
-#\u662f\u5426\u52a8\u6001\u5237\u65b0
-spring.cloud.nacos.config.refresh.enabled=true
-#\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
-spring.cloud.nacos.config.enabled=true

+ 55 - 0
audio-analysis/src/main/resources/logback-spring.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/logs/audio-analysis-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+		value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+		class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.yonge" level="info" />
+
+	<!--开发环境:打印控制台 -->
+	<springProfile name="dev">
+		<root level="dev">
+			<appender-ref ref="stdout" />
+			<appender-ref ref="file" />
+		</root>
+	</springProfile>
+	
+	<springProfile name="test">
+		<root level="info">
+			<appender-ref ref="stdout" />
+			<appender-ref ref="file" />
+		</root>
+	</springProfile>
+
+	<!--生产环境:输出到文件 -->
+	<springProfile name="prod">
+		<root level="WARN">
+			<appender-ref ref="stdout" />
+			<appender-ref ref="file" />
+		</root>
+	</springProfile>
+
+</configuration>

+ 3 - 0
cooleshow-cms/src/main/java/com/yonge/cooleshow/cms/controller/HelpCenterContentController.java

@@ -63,6 +63,9 @@ public class HelpCenterContentController extends BaseController {
 			return failed("用户信息获取失败");
 		}
 		helpContent.setReleaseStatus(0);
+		if (helpContent.getOrder() == null) {
+			helpContent.setOrder(0);
+		}
 		if (helpContent.getId() != null && helpContent.getId() > 0) {
 
 			HelpCenterContent helpCenterContent = helpCenterContentService.get(helpContent.getId());

+ 1 - 1
cooleshow-cms/src/main/java/com/yonge/cooleshow/cms/dal/entity/HelpCenterContent.java

@@ -17,7 +17,7 @@ public class HelpCenterContent {
 
 	@ApiModelProperty(value = "内容", required = true)
 	@NotBlank(message = "正文不能为空")
-	private String content = "";
+	private String content;
 
 	@ApiModelProperty("发布时间")
 	private Date releaseTime;

+ 1 - 1
cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/OmsOrderReturnApplyServiceImpl.java

@@ -110,7 +110,7 @@ public class OmsOrderReturnApplyServiceImpl implements OmsOrderReturnApplyServic
      */
     private void refundAmount(OmsOrderReturnApply returnApply) {
         // 退款
-        UserOrderPayment userOrderPayment = userOrderPaymentMapper.selectByOrderNo(returnApply.getOrderSn());
+        UserOrderPayment userOrderPayment = userOrderPaymentMapper.selectByTranNo(returnApply.getOrderSn());
         OrderRefundReq refundReq = new OrderRefundReq();
         refundReq.setOrderNo(returnApply.getOrderSn());
         refundReq.setRefundAmount(returnApply.getReturnAmount().setScale(2, RoundingMode.HALF_UP).toString());

+ 4 - 2
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java

@@ -1,6 +1,5 @@
 package com.yonge.cooleshow.mbg.mapper;
 
-import com.yonge.cooleshow.mbg.model.UmsRole;
 import com.yonge.cooleshow.mbg.model.UserOrderPayment;
 
 public interface UserOrderPaymentMapper {
@@ -9,7 +8,10 @@ public interface UserOrderPaymentMapper {
     int insert(UserOrderPayment record);
 
 
-    UserOrderPayment selectByOrderNo(String orderNo);
+    UserOrderPayment selectByTranNo(String orderNo);
 
     int updateByPrimaryKeySelective(UserOrderPayment userOrderPayment);
+
+
+    UserOrderPayment selectByOrderNo(String orderSn, String payChannel, String payStaus);
 }

+ 11 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/UserOrderPayment.java

@@ -20,6 +20,9 @@ public class UserOrderPayment implements Serializable {
     private Long id;
     @ApiModelProperty("订单号 ")
     private String orderNo;
+
+    @ApiModelProperty("支付订单号")
+    private String adapayNo;
     @ApiModelProperty("交易流水号 ")
     private String transNo;
     @ApiModelProperty("支付渠道:  alipay 支付宝  wx_lite 微信 ")
@@ -180,4 +183,12 @@ public class UserOrderPayment implements Serializable {
     public void setPayFailMsg(String payFailMsg) {
         this.payFailMsg = payFailMsg;
     }
+
+    public String getAdapayNo() {
+        return adapayNo;
+    }
+
+    public void setAdapayNo(String adapayNo) {
+        this.adapayNo = adapayNo;
+    }
 }

+ 16 - 5
cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml

@@ -17,13 +17,14 @@
         <result column="close_status_" jdbcType="TIMESTAMP" property="closeStatus" />
         <result column="close_fail_msg_" jdbcType="TIMESTAMP" property="closeFailMsg" />
         <result column="close_time_" jdbcType="TIMESTAMP" property="closeTime" />
+        <result column="adapay_no_" jdbcType="TIMESTAMP" property="adapayNo" />
         <result column="create_time_" jdbcType="TIMESTAMP" property="createTime" />
         <result column="update_time_" jdbcType="TIMESTAMP" property="updateTime" />
     </resultMap>
     <sql id="Base_Column_List">
         <!--@mbg.generated-->
         id_, order_no_, trans_no_, pay_channel_, pay_amt_, fee_amt_, pay_info_, status_,
-        pay_fail_msg_, arrival_time_,close_status_,close_fail_msg_,close_time_,create_time_, update_time_
+        pay_fail_msg_, arrival_time_,close_status_,close_fail_msg_,close_time_,create_time_, update_time_,adapay_no_
     </sql>
     <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
         <!--@mbg.generated-->
@@ -42,12 +43,12 @@
         insert into user_order_payment (order_no_, trans_no_, pay_channel_,
         pay_amt_, fee_amt_, pay_info_,
         status_, pay_fail_msg_, arrival_time_,
-        create_time_, update_time_,close_status_,close_fail_msg_,close_time_)
+        create_time_, update_time_,close_status_,close_fail_msg_,close_time_,adapay_no_)
         values (#{orderNo,jdbcType=VARCHAR}, #{transNo,jdbcType=VARCHAR}, #{payChannel,jdbcType=VARCHAR},
         #{payAmt,jdbcType=DECIMAL}, #{feeAmt,jdbcType=DECIMAL}, #{payInfo,jdbcType=VARCHAR},
         #{status,jdbcType=VARCHAR}, #{payFailMsg,jdbcType=VARCHAR}, #{arrivalTime,jdbcType=TIMESTAMP},
         #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP},#{closeStatus},#{closeFailMsg}
-        ,#{closeTime})
+        ,#{closeTime},#{adapayNo})
     </insert>
     <insert id="insertSelective" keyColumn="id_" keyProperty="id" parameterType="com.yonge.cooleshow.mbg.model.UserOrderPayment" useGeneratedKeys="true">
         <!--@mbg.generated-->
@@ -95,6 +96,9 @@
             <if test="closeTime != null">
                 close_time_,
             </if>
+            <if test="adapayNo != null">
+                adapay_no_,
+            </if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="orderNo != null">
@@ -139,6 +143,9 @@
             <if test="closeTime != null">
                 #{closeTime},
             </if>
+            <if test="adapayNo != null">
+                #{adapayNo},
+            </if>
         </trim>
     </insert>
     <update id="updateByPrimaryKeySelective" parameterType="com.yonge.cooleshow.mbg.model.UserOrderPayment">
@@ -187,6 +194,9 @@
             <if test="closeTime != null">
                 close_time_ = #{closeTime,jdbcType=TIMESTAMP},
             </if>
+            <if test="adapayNo != null">
+                adapay_no_ = #{closeTime,jdbcType=TIMESTAMP},
+            </if>
         </set>
         where id_ = #{id,jdbcType=BIGINT}
     </update>
@@ -207,12 +217,13 @@
         close_status_ = #{closeStatus},
         close_fail_msg_ = #{closeFailMsg},
         close_time_ = #{closeTime,jdbcType=TIMESTAMP},
+        adapay_no_ = #{adapayNo,jdbcType=TIMESTAMP},
         where id_ = #{id,jdbcType=BIGINT}
     </update>
 
-    <select id="selectByOrderNo" resultMap="BaseResultMap">
+    <select id="selectByTranNo" resultMap="BaseResultMap">
         select
         <include refid="Base_Column_List" />
-      from user_order_payment where order_no_ = #{orderNo} limit 1
+      from user_order_payment where trans_no_ = #{orderNo} limit 1
     </select>
 </mapper>

+ 6 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java

@@ -1,5 +1,7 @@
 package com.yonge.cooleshow.portal.service;
 
+import com.yonge.cooleshow.enums.PayChannelEnum;
+import com.yonge.cooleshow.enums.PayStatusEnum;
 import com.yonge.cooleshow.mbg.model.UserOrderPayment;
 
 /**
@@ -16,7 +18,7 @@ public interface UserOrderPaymentService {
      * @param orderNo 订单id
      * @return
      */
-    UserOrderPayment getByOrderNo(String orderNo);
+    UserOrderPayment getByTranNo(String orderNo);
 
     /**
      * 保存订单记录
@@ -26,4 +28,7 @@ public interface UserOrderPaymentService {
     void save(UserOrderPayment userOrderPayment);
 
     void saveOrUpdate(UserOrderPayment userOrderPayment);
+
+    UserOrderPayment getByOrderNo(String orderSn, PayChannelEnum payChannel, PayStatusEnum pending);
+
 }

+ 7 - 6
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java

@@ -327,7 +327,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
                 UmsMember member = memberService.getById(cancelOrder.getMemberId());
                 memberService.updateIntegration(cancelOrder.getMemberId(), member.getIntegration() + cancelOrder.getUseIntegration());
             }
-            UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(cancelOrder.getOrderSn());
+            UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(cancelOrder.getOrderSn());
             if (null != orderPayment) {
                 // 发起关单
                 OrderCloseReq orderCloseReq = new OrderCloseReq();
@@ -479,7 +479,8 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             orderPayRes.setMessage("订单已付款或已关闭");
             return orderPayRes;
         }
-        UserOrderPayment userOrderPayment = userOrderPaymentService.getByOrderNo(detail.getOrderSn());
+        UserOrderPayment userOrderPayment = userOrderPaymentService
+                .getByOrderNo(detail.getOrderSn(), payReq.getPayChannel(), PayStatusEnum.pending);
         payReq.orderStatus(detail.getStatus());
         payReq.setOrderNo(detail.getOrderSn());
         payReq.setOrderPrice(detail.getPayAmount());
@@ -599,7 +600,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      * @updateTime 2022/4/27 15:33
      */
     private void paymentCloseSucceededHandle(JSONObject hfRes) {
-        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(hfRes.getString("payment_id"));
+        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(hfRes.getString("payment_id"));
         if (null == orderPayment) {
             return;
         }
@@ -615,7 +616,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      * @updateTime 2022/4/27 15:33
      */
     private void paymentCloseFailedHandle(JSONObject hfRes) {
-        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(hfRes.getString("payment_id"));
+        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(hfRes.getString("payment_id"));
         if (null == orderPayment) {
             return;
         }
@@ -634,7 +635,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     @Transactional(rollbackFor = Exception.class)
     void payingOrderHandle(OmsOrder userOrder) {
         //判断汇付订单状态
-        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(userOrder.getOrderSn());
+        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(userOrder.getOrderSn());
         if (null == orderPayment) {
             return;
         }
@@ -665,7 +666,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     @Transactional(rollbackFor = Exception.class)
     void orderSuccess(OmsOrder detail, JSONObject hfRes) {
         //更新订单
-        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(detail.getOrderSn());
+        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(detail.getOrderSn());
         if (orderPayment.getPayChannel().equals("alipay")) {
             paySuccess(detail.getId(),1);
         } else if (orderPayment.getPayChannel().equals("wx_lite")) {

+ 10 - 2
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/UserOrderPaymentServiceImpl.java

@@ -1,5 +1,7 @@
 package com.yonge.cooleshow.portal.service.impl;
 
+import com.yonge.cooleshow.enums.PayChannelEnum;
+import com.yonge.cooleshow.enums.PayStatusEnum;
 import com.yonge.cooleshow.mbg.mapper.UserOrderPaymentMapper;
 import com.yonge.cooleshow.mbg.model.UserOrderPayment;
 import com.yonge.cooleshow.portal.service.UserOrderPaymentService;
@@ -19,8 +21,8 @@ public class UserOrderPaymentServiceImpl implements UserOrderPaymentService {
     private UserOrderPaymentMapper userOrderPaymentMapper;
 
     @Override
-    public UserOrderPayment getByOrderNo(String orderNo) {
-        return userOrderPaymentMapper.selectByOrderNo(orderNo);
+    public UserOrderPayment getByTranNo(String orderNo) {
+        return userOrderPaymentMapper.selectByTranNo(orderNo);
     }
 
     @Override
@@ -36,4 +38,10 @@ public class UserOrderPaymentServiceImpl implements UserOrderPaymentService {
             userOrderPaymentMapper.updateByPrimaryKeySelective(userOrderPayment);
         }
     }
+
+    @Override
+    public UserOrderPayment getByOrderNo(String orderSn, PayChannelEnum payChannel, PayStatusEnum payStatus) {
+
+        return userOrderPaymentMapper.selectByOrderNo(orderSn,payChannel.getCode(),payStatus.getCode());
+    }
 }

+ 14 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/HomeController.java

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.admin.controller;
 import com.yonge.cooleshow.biz.dal.dto.req.TotalReq;
 import com.yonge.cooleshow.biz.dal.service.HomeService;
 import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
+import com.yonge.cooleshow.biz.dal.vo.CourseHomeVo;
 import com.yonge.cooleshow.biz.dal.vo.HomeMusicSheetVo;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeTotalStudent;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeTotalTeacher;
@@ -15,6 +16,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/home")
@@ -47,11 +49,22 @@ public class HomeController extends BaseController {
         return homeService.totalStudent(totalReq);
     }
 
-
     @ApiOperation(value = "首页曲目点播数据")
     @PostMapping("/musicSheet")
     public HttpResponseResult<HomeMusicSheetVo> musicSheet() {
         return succeed(musicSheetService.getMusicSheetHome());
     }
 
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "year", dataType = "Integer", value = "年"),
+            @ApiImplicitParam(name = "month", dataType = "Integer", value = "月"),
+            @ApiImplicitParam(name = "type", dataType = "String", value = "类型  PRACTICE陪练课  LIVE直播课"),
+    })
+    @ApiOperation(value = "获取首页课程数据")
+    @PostMapping("/courseHome")
+    @PreAuthorize("@pcs.hasPermissions('home/courseHome')")
+    public HttpResponseResult<CourseHomeVo> queryCourseHomeData(@RequestBody Map<String,Object> param) {
+        return succeed(homeService.queryCourseHomeData(param));
+    }
+
 }

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java

@@ -185,5 +185,17 @@ public interface CourseScheduleDao extends BaseMapper<CourseSchedule> {
 
     //根据id统计评价
     Integer countReplies(Long studentId);
+
+    /**
+     * 按年查询首页课程数据
+     * @param param
+     */
+    List<CourseHomeVo.CourseHomeInfoVo> queryCourseHomeOfYear(@Param("param") Map<String, Object> param);
+
+    /**
+     * 按月查询首页课程数据
+     * @param param
+     */
+    List<CourseHomeVo.CourseHomeInfoVo> queryCourseHomeOfMonth(@Param("param") Map<String, Object> param);
 }
 

+ 7 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserWithdrawalDao.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.dao;
 
 import java.util.List;
+import java.util.Map;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -35,5 +36,10 @@ public interface UserWithdrawalDao extends BaseMapper<UserWithdrawal>{
 	 */
 	List<UserWithdrawalVo> selectList(@Param("param") TeacherWithdrawalSearch teacherWithdrawal);
 
-	
+	/**
+	 * @Description: 提现成功回调
+	 * @Author: cy
+	 * @Date: 2022/5/9
+	 */
+    void withdrawSuccess(Map<String, Object> withdrawRecord);
 }

+ 58 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderRefundReq.java

@@ -0,0 +1,58 @@
+package com.yonge.cooleshow.biz.dal.dto.req;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 退款请求
+ *
+ * @Author: liweifan
+ * @Data: 2022/3/31 14:55
+ */
+@ApiModel(value = "OrderRefundReq对象", description = "退款请求")
+public class OrderRefundReq {
+    @NotBlank(message = "订单号不能为空")
+    @ApiModelProperty(value = "订单号 ", required = true)
+    private String orderNo;
+    @NotBlank(message = "详情id不能为空")
+    @ApiModelProperty(value = "订单详情id ", required = true)
+    private Long orderDetilId;
+    @ApiModelProperty(value = "退款说明 ")
+    private String reason;
+
+    private Long userId;
+
+    public String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
+
+    public Long getOrderDetilId() {
+        return orderDetilId;
+    }
+
+    public void setOrderDetilId(Long orderDetilId) {
+        this.orderDetilId = orderDetilId;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public void setReason(String reason) {
+        this.reason = reason;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+}

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/LiveRoom.java

@@ -63,7 +63,7 @@ public class LiveRoom implements Serializable {
     private Integer roomState;
 
     @TableField("type_")
-    @ApiModelProperty(value = "房间类型 live直播课  temp临时直播间")
+    @ApiModelProperty(value = "房间类型 live直播课  temp临时直播间 practice陪练课")
     private String type;
 
     @TableField("cover_pic_")

+ 21 - 9
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrderRefunds.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -23,13 +24,16 @@ public class UserOrderRefunds implements Serializable {
     @TableId(value = "id_", type = IdType.AUTO)
     private Long id;
 	@TableField(value = "user_id_")
-    private Integer userId;
+    private Long userId;
     @ApiModelProperty("订单号 ")
 	@TableField(value = "order_no_")
     private String orderNo;
-    @ApiModelProperty("状态(1,审核中;2,通过;-1,拒绝;) ")
+    @ApiModelProperty("订单详情id ")
+    @TableField(value = "order_detil_id_")
+    private Long orderDetilId;
+    @ApiModelProperty("状态 DOING、审核中 PASS、通过 UNPASS、不通过")
 	@TableField(value = "status_")
-    private String status;
+    private AuthStatusEnum status;
     @ApiModelProperty("申请退费金额 ")
 	@TableField(value = "apply_amount_")
     private BigDecimal applyAmount;
@@ -61,11 +65,11 @@ public class UserOrderRefunds implements Serializable {
         this.id = id;
     }
     
-	public Integer getUserId() {
+	public Long getUserId() {
         return userId;
     }
 
-    public void setUserId(Integer userId) {
+    public void setUserId(Long userId) {
         this.userId = userId;
     }
     
@@ -76,12 +80,20 @@ public class UserOrderRefunds implements Serializable {
     public void setOrderNo(String orderNo) {
         this.orderNo = orderNo;
     }
-    
-	public String getStatus() {
+
+    public Long getOrderDetilId() {
+        return orderDetilId;
+    }
+
+    public void setOrderDetilId(Long orderDetilId) {
+        this.orderDetilId = orderDetilId;
+    }
+
+    public AuthStatusEnum getStatus() {
         return status;
     }
 
-    public void setStatus(String status) {
+    public void setStatus(AuthStatusEnum status) {
         this.status = status;
     }
     
@@ -92,7 +104,7 @@ public class UserOrderRefunds implements Serializable {
     public void setApplyAmount(BigDecimal applyAmount) {
         this.applyAmount = applyAmount;
     }
-    
+
 	public BigDecimal getActualAmount() {
         return actualAmount;
     }

+ 7 - 4
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleEnum.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.biz.dal.enums;
 
 import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.yonge.toolset.base.enums.BaseEnum;
+import com.yonge.toolset.base.exception.BizException;
 
 import java.util.Arrays;
 import java.util.List;
@@ -39,7 +40,7 @@ public enum CourseScheduleEnum implements BaseEnum<String,CourseScheduleEnum> {
     public static CourseScheduleEnum existCourseType(String code, String errMsg) {
         CourseScheduleEnum[] values = {PRACTICE, LIVE};
         existCourse(values, code, errMsg);
-        //陪练课-校验学生时间是否交集
+        //返回枚举对象
         if (code.equals(CourseScheduleEnum.PRACTICE.getCode())) {
             return CourseScheduleEnum.PRACTICE;
         } else {
@@ -59,10 +60,12 @@ public enum CourseScheduleEnum implements BaseEnum<String,CourseScheduleEnum> {
     }
 
     private static void existCourse(CourseScheduleEnum[] values, String code, String errMsg) {
-        List<String> collect = Arrays.stream(values).map(CourseScheduleEnum::getCode).collect(Collectors.toList());
-        boolean typeFlag = collect.contains(code);
+        List<String> collect = Arrays.stream(values)
+                .map(CourseScheduleEnum::getCode)
+                .collect(Collectors.toList());
+        boolean typeFlag = collect.contains(code.toUpperCase());
         if (!typeFlag) {
-            throw new RuntimeException(errMsg);
+            throw new BizException(errMsg);
         }
     }
 

+ 32 - 20
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/MessageTypeEnum.java

@@ -11,16 +11,29 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
     STUDENT_BUY_TEACHER_MUSIC_SHEET("STUDENT_BUY_TEACHER_MUSIC_SHEET","学员购买老师乐谱"),
     MUSIC_SHEET_AUTH_PASS("MUSIC_SHEET_AUTH_PASS","乐谱审核通过"),
     MUSIC_SHEET_AUTH_UNPASS("MUSIC_SHEET_AUTH_UNPASS","乐谱审核失败"),
+
     STUDENT_BUY_MUSIC_SHEET_SUCCESS("STUDENT_BUY_MUSIC_SHEET_SUCCESS","学员购买乐谱成功"),
+    SMS_STUDENT_BUY_MUSIC_SHEET_SUCCESS("SMS_STUDENT_BUY_MUSIC_SHEET_SUCCESS","学员购买乐谱(短信)"),
+
     TEACHER_DECORATE_HOMEWORK("TEACHER_DECORATE_HOMEWORK","老师布置作业"),
     TEACHER_REVIEW_HOMEWORK("TEACHER_REVIEW_HOMEWORK","老师点评作业"),
     STUDENT_SUBMIT_HOMEWORK("STUDENT_SUBMIT_HOMEWORK","学生提交作业"),
 
-    TEACHER_AUTH_PASS("TEACHER_AUTH_PASS","老师认证通过"),
-    TEACHER_AUTH_FAIL("TEACHER_AUTH_FAIL","老师认证失败"),
-    MUSICIAN_AUTH_PASS("MUSICIAN_AUTH_PASS","音乐人认证通过"),
+    TEACHER_AUTH_PASS("TEACHER_AUTH_PASS","老师认证通过","H5?https//www.xxxx.com/teacher/#/practiceSetting"),
+    SMS_TEACHER_AUTH_PASS("SMS_TEACHER_AUTH_PASS","老师认证通过(短信)"),
+
+    TEACHER_AUTH_FAIL("TEACHER_AUTH_FAIL","老师认证失败","H5?https//www.xxxx.com/teacher/#/teacherCert"),
+    SMS_TEACHER_AUTH_FAIL("SMS_TEACHER_AUTH_FAIL","老师认证失败(短信)"),
+
+    MUSICIAN_AUTH_PASS("MUSICIAN_AUTH_PASS","音乐人认证通过","H5?https//www.xxxx.com/teacher/#/music-upload"),
+    SMS_MUSICIAN_AUTH_PASS("SMS_MUSICIAN_AUTH_PASS","音乐人认证通过(短信)"),
+
     MUSICIAN_AUTH_FAIL("MUSICIAN_AUTH_FAIL","音乐人认证失败"),
+    SMS_MUSICIAN_AUTH_FAIL("SMS_MUSICIAN_AUTH_FAIL","音乐人认证失败(短信)"),
+
     STUDENT_BUY_PRACTICE("STUDENT_BUY_PRACTICE","学员购买陪练课"),
+    SMS_STUDENT_BUY_PRACTICE("SMS_STUDENT_BUY_PRACTICE","学员购买陪练课(短信)"),
+
     STUDENT_BUY_LIVE("STUDENT_BUY_LIVE","学员购买直播课"),
     STUDENT_BUY_VIDEO("STUDENT_BUY_VIDEO","学员购买视频课"),
     LIVE_COMPLETION_SUCCESS("LIVE_COMPLETION_SUCCESS","直播课成课"),
@@ -33,12 +46,26 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
     STUDENT_EVALUATE_TEACHER_PRACTICE("STUDENT_EVALUATE_TEACHER_PRACTICE","学员对老师评价"),
     WITHDRAWAL_SUCCESS("WITHDRAWAL_SUCCESS","提现成功"),
     STUDENT_JOIN_FANSGROUP("STUDENT_JOIN_FANSGROUP","学员申请加入粉丝群"),
+
     VIP_BUY_SUCCESS("VIP_BUY_SUCCESS","会员购买成功"),
-    VIP_EXPIRE_THIRTY_DAY("VIP_EXPIRE_THIRTY_DAY","会员到期前30天"),
-    VIP_EXPIRE("VIP_EXPIRE","会员到期"),
+    SMS_VIP_BUY_SUCCESS("SMS_VIP_BUY_SUCCESS","会员购买成功(短信)"),
+
+    VIP_EXPIRE_THIRTY_DAY("VIP_EXPIRE_THIRTY_DAY","会员到期前30天","H5?https//www.xxxx.com/student/#/memberCenter"),
+    SMS_VIP_EXPIRE_THIRTY_DAY("SMS_VIP_EXPIRE_THIRTY_DAY","会员到期前30天(短信)","H5?https//www.xxxx.com/student/#/memberCenter"),
+
+    VIP_EXPIRE("VIP_EXPIRE","会员到期","H5?https//www.xxxx.com/student/#/memberCenter"),
+    SMS_VIP_EXPIRE("SMS_VIP_EXPIRE","会员到期(短信)","H5?https//www.xxxx.com/student/#/memberCenter"),
+
     PRACTICE_BUY("PRACTICE_BUY","陪练课购买"),
+    SMS_PRACTICE_BUY("SMS_PRACTICE_BUY", "陪练课购买(短信)"),
+
     LIVE_BUY("LIVE_BUY","直播课购买"),
+    SMS_LIVE_BUY("SMS_LIVE_BUY","直播课购买"),
+
+
     VIDEO_BUY("VIDEO_BUY","视频课购买"),
+    SMS_VIDEO_BUY("SMS_VIDEO_BUY","视频课购买(短信)"),
+
     PRACTICE_REMIND("PRACTICE_REMIND","陪练课提醒(陪练课开始前20分钟)"),
     LIVE_REMIND("LIVE_REMIND","直播课提醒(直播课开始前20分钟)"),
     NOT_EVALUATE_TEACHER_PRACTICE("NOT_EVALUATE_TEACHER_PRACTICE","当日陪练课未对老师评价(每晚9点,已评价不发)"),
@@ -46,22 +73,7 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
 
     //------短信模板------
     SMS_BUY_LIVE("SMS_BUY_LIVE","直播课购买成功"),
-    SMS_LIVE_BUY("SMS_LIVE_BUY","直播课购买"),
     SMS_LIVE_COMPLETION_SUCCESS("SMS_LIVE_COMPLETION_SUCCESS","直播课成课"),
-
-    SMS_STUDENT_BUY_MUSIC_SHEET_SUCCESS("SMS_STUDENT_BUY_MUSIC_SHEET_SUCCESS","学员购买乐谱(短信)"),
-
-    SMS_TEACHER_AUTH_PASS("SMS_TEACHER_AUTH_PASS","老师认证通过(短信)"),
-    SMS_TEACHER_AUTH_FAIL("SMS_TEACHER_AUTH_FAIL","老师认证失败(短信)"),
-    SMS_MUSICIAN_AUTH_PASS("SMS_MUSICIAN_AUTH_PASS","音乐人认证通过(短信)"),
-    SMS_MUSICIAN_AUTH_FAIL("SMS_MUSICIAN_AUTH_FAIL","音乐人认证失败(短信)"),
-    SMS_VIP_BUY_SUCCESS("SMS_VIP_BUY_SUCCESS","会员购买成功(短信)"),
-    SMS_VIP_EXPIRE_THIRTY_DAY("SMS_VIP_EXPIRE_THIRTY_DAY","会员到期前30天(短信)"),
-    SMS_VIP_EXPIRE("SMS_VIP_EXPIRE","会员到期(短信)"),
-
-    SMS_VIDEO_BUY("SMS_VIDEO_BUY","视频课购买(短信)"),
-    SMS_STUDENT_BUY_PRACTICE("SMS_STUDENT_BUY_PRACTICE","学员购买陪练课(短信)"),
-    SMS_PRACTICE_BUY("SMS_PRACTICE_BUY", "陪练课购买(短信)"),
     SMS_TOMORROW_COURSE_REMINDER("SMS_TOMORROW_COURSE_REMINDER", "明日课程提醒(每晚9点)(短信)");
 
     MessageTypeEnum(String code, String msg) {

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoomTypeEnum.java

@@ -7,6 +7,7 @@ import java.util.stream.Collectors;
 public enum RoomTypeEnum {
 
     LIVE("LIVE", "直播课"),
+    PRACTICE("PRACTICE", "陪练课"),
     TEMP("TEMP", "临时直播间");
 
     private String code;

+ 30 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseGroupService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.CourseGroupDao;
 import com.yonge.cooleshow.biz.dal.dto.CheckCourseTimeDto;
 import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupStudentCourseSearch;
@@ -13,6 +14,7 @@ import com.yonge.cooleshow.biz.dal.entity.CourseGroup;
 import com.yonge.cooleshow.biz.dal.entity.CourseTimeEntity;
 import com.yonge.cooleshow.biz.dal.vo.*;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.base.page.PageInfo;
 import org.redisson.api.RMap;
@@ -142,6 +144,33 @@ public interface CourseGroupService extends IService<CourseGroup> {
      * <p>定时将符合结束售卖日期的在售卖中的直播课课程组修改为取消或者成课状态状态-每隔10分钟执行一次
      */
     void opsCourseGroup();
-
+    /***
+     * 直播课退款单-创建前
+     * @param: refundReq
+     * @updateTime 2022/5/9 15:11
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes>
+     */
+    HttpResponseResult<RefundCreateRes> refundCreate(OrderRefundReq refundReq);
+    /***
+     * 直播课退款单-创建后
+     * @param: refundReq
+     * @updateTime 2022/5/9 15:11
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes>
+     */
+    void refundAfter(UserOrderRefundsVo userOrderRefundsVo);
+    /***
+     * 直播课退款单-退款成功
+     * @param: refundReq
+     * @updateTime 2022/5/9 15:11
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes>
+     */
+    void refundSuccess(UserOrderRefundsVo userOrderRefundsVo);
+    /***
+     * 直播课退款单-退款失败
+     * @param: refundReq
+     * @updateTime 2022/5/9 15:11
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes>
+     */
+    void refundCancel(UserOrderRefundsVo userOrderRefundsVo);
 }
 

+ 15 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/HomeService.java

@@ -1,11 +1,14 @@
 package com.yonge.cooleshow.biz.dal.service;
 
 import com.yonge.cooleshow.biz.dal.dto.req.TotalReq;
+import com.yonge.cooleshow.biz.dal.vo.CourseHomeVo;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeTotalStudent;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeTotalTeacher;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeUserToDoNum;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 
+import java.util.Map;
+
 /**
  * @Author: liweifan
  * @Data: 2022/3/30 18:07
@@ -35,4 +38,16 @@ public interface HomeService {
      * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<com.yonge.cooleshow.biz.dal.vo.res.HomeTotalTeacher>
      */
     HttpResponseResult<HomeTotalStudent> totalStudent(TotalReq totalReq);
+
+    /**
+     * 获取首页课程数据
+     * <p>未完成  未开始&进行中
+     * <p>已完成  已完成课程
+     *
+     * @param param 传入参数
+     *              <p> - year 年
+     *              <p> - month 月
+     *              <p> - type 类型  PRACTICE陪练课  LIVE直播课
+     */
+    CourseHomeVo queryCourseHomeData(Map<String, Object> param);
 }

+ 5 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java

@@ -39,6 +39,11 @@ public interface LiveRoomService extends IService<LiveRoom> {
     void destroyExpiredLiveRoom();
 
     /**
+     * 定时任务-清理过期的房间-陪练课
+     */
+    void destroyExpiredPracticeRoom();
+
+    /**
      * 创建临时房间-直播间
      */
     String createTempLiveRoom(Map<String, Object> param);

+ 10 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderRefundsService.java

@@ -2,9 +2,11 @@ package com.yonge.cooleshow.biz.dal.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderRefundsVo;
 import com.yonge.cooleshow.biz.dal.dto.search.OrderRefundsSearch;
 import com.yonge.cooleshow.biz.dal.entity.UserOrderRefunds;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
 
 /**
  * 用户退款表 服务类
@@ -12,7 +14,6 @@ import com.yonge.cooleshow.biz.dal.entity.UserOrderRefunds;
  * @date 2022-03-30
  */
 public interface UserOrderRefundsService extends IService<UserOrderRefunds>  {
-
 	/**
      * 查询详情
      * @author liweifan
@@ -26,4 +27,12 @@ public interface UserOrderRefundsService extends IService<UserOrderRefunds>  {
  	 * @date 2022-03-30
      */
     IPage<UserOrderRefundsVo> selectPage(IPage<UserOrderRefundsVo> page, OrderRefundsSearch query);
+	/***
+	 * 订单退款
+	 * @author liweifan
+	 * @param: refundReq
+	 * @updateTime 2022/5/9 14:29
+	 * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.lang.Boolean>
+	 */
+	HttpResponseResult<Boolean> orderRefund(OrderRefundReq refundReq);
 }

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderService.java

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.biz.dal.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 import com.yonge.cooleshow.biz.dal.entity.UserOrder;
 import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
@@ -114,6 +115,16 @@ public interface UserOrderService extends IService<UserOrder> {
      * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.lang.Boolean>
      */
     HttpResponseResult<Boolean> orderCancel(OrderPayReq payReq);
+
+    /***
+     * 订单退款
+     * @author liweifan
+     * @param: payReq
+     * @updateTime 2022/4/21 19:39
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.lang.Boolean>
+     */
+    HttpResponseResult<Boolean> orderRefund(OrderRefundReq refundReq);
+
     /***
      * 取消订单(未判断付款单状态)
      * @author liweifan
@@ -154,4 +165,5 @@ public interface UserOrderService extends IService<UserOrder> {
      * @updateTime 2022/4/29 18:41
      */
     void setOrderStatus(String orderNo, OrderStatusEnum orderStatus);
+
 }

+ 8 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserWithdrawalService.java

@@ -12,6 +12,7 @@ import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.utils.easyexcel.ExcelDataReaderProperty;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 用户账户提现表 服务类
@@ -67,4 +68,11 @@ public interface UserWithdrawalService extends IService<UserWithdrawal>  {
 	 * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.util.List<com.yonge.toolset.utils.easyexcel.ErrMsg>>
 	 */
     void importExcel(List<ExcelDataReaderProperty<UserWithdrawalExport>> dataList, Long userId);
+
+	/**
+	 * @Description: 提现成功回调
+	 * @Author: cy
+	 * @Date: 2022/5/9
+	 */
+	void withdrawSuccess(Map<String, Object> withdrawRecord);
 }

+ 25 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseGroupServiceImpl.java

@@ -12,6 +12,7 @@ import com.yonge.cooleshow.biz.dal.dao.CourseGroupDao;
 import com.yonge.cooleshow.biz.dal.dto.CheckCourseTimeDto;
 import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto;
 import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto.CoursePlanDto;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupStudentCourseSearch;
@@ -24,6 +25,7 @@ import com.yonge.cooleshow.biz.dal.support.PageUtil;
 import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
 import com.yonge.cooleshow.biz.dal.vo.*;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.base.exception.BizException;
@@ -834,6 +836,29 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
         closeCourseGroup();
     }
 
+    @Override
+    public HttpResponseResult<RefundCreateRes> refundCreate(OrderRefundReq refundReq) {
+        RefundCreateRes refundCreateRes = new RefundCreateRes();
+        refundCreateRes.setRes(true);
+        refundCreateRes.setActualPrice(BigDecimal.ZERO);
+        return HttpResponseResult.succeed(refundCreateRes);
+    }
+
+    @Override
+    public void refundAfter(UserOrderRefundsVo userOrderRefundsVo) {
+
+    }
+
+    @Override
+    public void refundSuccess(UserOrderRefundsVo userOrderRefundsVo) {
+
+    }
+
+    @Override
+    public void refundCancel(UserOrderRefundsVo userOrderRefundsVo) {
+
+    }
+
     /**
      * 定时将符合开售日期的未开售的直播课课程组修改为报名中状态
      */

+ 25 - 19
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java

@@ -124,6 +124,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         param.put("endDate", lastDay.toString());
         param.put("teacherId", getSysUser().getId());
         param.put("type", CourseScheduleEnum.LIVE.getCode());
+        log.info("queryTeacherLiveCourse:{}", param);
         Page<TeacherLiveCourseInfoVo> pageInfo = PageUtil.getPageInfo(param);
         pageInfo.setAsc("a.start_time_");
         IPage<TeacherLiveCourseInfoVo> page = baseMapper.queryLiveTeacherCourse(pageInfo, param);
@@ -131,7 +132,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     }
 
     /**
-     * 校验该学生大于当前时间未开始的课程时间和传入时间段有没有交集
+     * 校验该学生大于当前时间未开始和进行中的课程时间和传入时间段有没有交集
      *
      * @param studentId 学生id
      * @param startTime 新增课程 开始时间
@@ -148,7 +149,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         param.put("studentId", studentId);
         param.put("greaterDate", new Date());
         param.put("classDate", ymd);
-        param.put("status", CourseScheduleEnum.NOT_START.getCode());
+        param.put("statusList", Lists.newArrayList(CourseScheduleEnum.NOT_START.getCode(), CourseScheduleEnum.ING.getCode()));
         List<CourseSchedule> list = baseMapper.queryStudentCourse(param);
         return checkCourseTime(list, CourseSchedule::getStartTime, CourseSchedule::getEndTime, startTime, endTime);
     }
@@ -166,10 +167,8 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         WrapperUtil.checkObj(startTime, "开始时间不能为空!");
         //获取日期-目前上课没有跨天情况
         String ymd = DateUtil.format(startTime, DateUtil.DEFAULT_PATTERN);
-        //查询老师当天所有的课程时间数据
-        List<CourseSchedule> list = this.list(Wrappers.<CourseSchedule>lambdaQuery()
-                .eq(CourseSchedule::getTeacherId, teacherId)
-                .eq(CourseSchedule::getClassDate, ymd));
+        //查询老师当天未开始、进行中的课程
+        List<CourseSchedule> list = getTeacherCourseTime(teacherId, ymd, ymd);
         return checkCourseTime(list, CourseSchedule::getStartTime, CourseSchedule::getEndTime, startTime, endTime);
     }
 
@@ -296,19 +295,27 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
                         holidayMap.put(calendarYear, list);
                         return list;
                     });
-            //是否是节假日  0:不是 1是
-            calendarEntity.setHoliday(holiday.contains(calendarEntity.getDate()) ? 1 : 0);
-            calendarEntity.setSkipHoliday(skipHoliday);//直播课日历只展示节假日 不跳过节假日
+            //是否是节假日 1是 0:不是
+            int holidayFlag = holiday.contains(calendarEntity.getDate()) ? 1 : 0;
+            calendarEntity.setHoliday(holidayFlag);
+
+            //是节假日又有需要跳过节假日
+            if (holidayFlag == 1 && skipHoliday == 1) {
+                calendarEntity.setSkipHoliday(1);//跳过节假日
+                calendarEntity.setCourseTime(null);//清空课程时间
+            } else {
+                calendarEntity.setSkipHoliday(0);//不跳过节假日
+            }
         });
     }
 
     /**
-     * 获取老师的课程时间数据
+     * 获取老师未开始、进行中的课程
      *
      * @param teacherId 老师id
      * @param startDate 开始时间
      * @param endDate   结束时间
-     * @return key:日期-年月日 value:课程时间-开始时间,结束时间
+     * @return 课程列表
      */
     private List<CourseSchedule> getTeacherCourseTime(Long teacherId, String startDate, String endDate) {
         //未开始、进行中的课程
@@ -533,9 +540,11 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
      *
      * @param teacherId 老师id
      * @param studentId 学员id
+     * @param startDate 开始日期
+     * @param endDate   结束日期
      */
     private Map<String, List<CourseTimeEntity>> getAllPracticeCourseTime(Long teacherId, Long studentId, String startDate, String endDate) {
-        //获取老师的课程时间数据
+        //获取老师未开始、进行中的课程
         List<CourseSchedule> courseList = getTeacherCourseTime(teacherId, startDate, endDate);
         if (CollectionUtils.isEmpty(courseList)) {
             courseList = new ArrayList<>();
@@ -837,7 +846,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
 
         String orderNo = orderReqInfo.getOrderNo();
         scheduleDto.setType(CourseScheduleEnum.PRACTICE.getCode());
-        scheduleDto.setStatus(CourseGroupEnum.NOT_SALE.getCode());
+        scheduleDto.setStatus(CourseGroupEnum.ING.getCode());
         scheduleDto.setMixStudentNum(1);
         scheduleDto.setStudentId(studentId);
 
@@ -1047,15 +1056,12 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
                 Map<Long, String> teacherReceivers = new HashMap<>();
                 teacherReceivers.put(info.getTeacherId(), info.getPhone());
                 sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.NOT_EVALUATE_STUDENT_PRACTICE,
-                                                   teacherReceivers, null, 0, null, ClientEnum.TEACHER.getCode(),
-                                                   info.getRepliedNum(),info.getDecorateNum());
+                        teacherReceivers, null, 0, null, ClientEnum.TEACHER.getCode(),
+                        info.getRepliedNum(), info.getDecorateNum());
             } catch (Exception e) {
-                log.warn("老师当日陪练课未评价/布置作业消息发送失败,{}",e.getMessage());
+                log.warn("老师当日陪练课未评价/布置作业消息发送失败,{}", e.getMessage());
             }
-
         }
-
-
     }
 
     /**

+ 95 - 5
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/HomeServiceImpl.java

@@ -1,23 +1,29 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
+import com.yonge.cooleshow.biz.dal.dao.CourseScheduleDao;
 import com.yonge.cooleshow.biz.dal.dao.HomeDao;
 import com.yonge.cooleshow.biz.dal.dto.req.TotalReq;
-import com.yonge.cooleshow.biz.dal.enums.PeriodEnum;
+import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
+import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
 import com.yonge.cooleshow.biz.dal.service.HomeService;
+import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
+import com.yonge.cooleshow.biz.dal.vo.CourseHomeVo;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeTotalStudent;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeTotalTeacher;
 import com.yonge.cooleshow.biz.dal.vo.res.HomeUserToDoNum;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
-import com.yonge.toolset.base.exception.BizException;
-import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
 import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * @Author: liweifan
@@ -27,6 +33,8 @@ import java.util.List;
 public class HomeServiceImpl implements HomeService {
     @Autowired
     private HomeDao baserMapper;
+    @Autowired
+    private CourseScheduleService courseScheduleService;
 
     @Override
     public HomeUserToDoNum getUserToDoNum() {
@@ -106,4 +114,86 @@ public class HomeServiceImpl implements HomeService {
         total.setInfoList(totalList);
         return HttpResponseResult.succeed(total);
     }
+
+    /**
+     * 获取首页课程数据
+     * <p>未完成  未开始&进行中
+     * <p>已完成  已完成课程
+     *
+     * @param param 传入参数
+     *              <p> - year 年
+     *              <p> - month 月
+     *              <p> - type 类型  PRACTICE陪练课  LIVE直播课
+     */
+    public CourseHomeVo queryCourseHomeData(Map<String, Object> param) {
+        CourseScheduleEnum.existCourseType(WrapperUtil.toStr(param, "type"), "课程类型参数错误");
+        Integer year = WrapperUtil.toInt(param, "year", "年份不能为空!");
+        Integer monthParam = WrapperUtil.toInt(param, "month");
+        //按月查询true  年查询false
+        boolean isYear = monthParam == 0;
+        int month = isYear ? 1 : monthParam;
+
+        LocalDate firstDate;
+        LocalDate endDate;
+        CourseHomeVo result = new CourseHomeVo();
+        CourseScheduleDao courseScheduleServiceDao = courseScheduleService.getDao();
+        firstDate = LocalDate.of(year, month, 1);
+        //获取开始时间
+        if (isYear) {
+            //查询当年最后一天
+            endDate = firstDate.with(TemporalAdjusters.lastDayOfYear());
+        } else {
+            //查询当月最后一天
+            endDate = firstDate.with(TemporalAdjusters.lastDayOfMonth());
+        }
+        param.put("startDate", firstDate);
+        param.put("endDate", endDate);
+
+        //查询数据
+        List<CourseHomeVo.CourseHomeInfoVo> courseYearInfoList;
+        if (isYear) {
+            courseYearInfoList = courseScheduleServiceDao.queryCourseHomeOfYear(param);
+        } else {
+            courseYearInfoList = courseScheduleServiceDao.queryCourseHomeOfMonth(param);
+        }
+        if (CollectionUtils.isEmpty(courseYearInfoList)) {
+            courseYearInfoList = new ArrayList<>();
+        }
+        Map<String, CourseHomeVo.CourseHomeInfoVo> collect = courseYearInfoList.stream()
+                .collect(Collectors.toMap(CourseHomeVo.CourseHomeInfoVo::getDate, Function.identity(), (key1, key2) -> key2));
+        //补全数据
+        while (firstDate.isBefore(endDate)) {
+            CourseHomeVo.CourseHomeInfoVo infoVo = collect.get(firstDate.toString());
+            if (Objects.isNull(infoVo)) {
+                infoVo = new CourseHomeVo.CourseHomeInfoVo();
+                if (isYear) {
+                    infoVo.setDate(firstDate.toString().substring(0, 7));
+                } else {
+                    infoVo.setDate(firstDate.toString());
+                }
+                infoVo.setDoneCount(0);
+                infoVo.setUndoneCount(0);
+                courseYearInfoList.add(infoVo);
+            } else {
+                if (isYear) {
+                    infoVo.setDate(firstDate.toString().substring(0, 7));
+                }
+            }
+            if (isYear) {
+                firstDate = firstDate.plusMonths(1L);
+            } else {
+                firstDate = firstDate.plusDays(1L);
+            }
+        }
+        result.setCourseHomeInfoList(courseYearInfoList);
+        //计算总数方法
+        Function<Function<CourseHomeVo.CourseHomeInfoVo, Integer>, Integer> reduceFunc = (c) -> result.getCourseHomeInfoList().stream()
+                .map(c)
+                .reduce(0, Integer::sum);
+        result.setTotalDoneCount(reduceFunc.apply(CourseHomeVo.CourseHomeInfoVo::getDoneCount));
+        result.setTotalUndoneCount(reduceFunc.apply(CourseHomeVo.CourseHomeInfoVo::getUndoneCount));
+        result.setTotalCount(result.getTotalDoneCount() + result.getTotalUndoneCount());
+        return result;
+    }
+
 }

+ 59 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java

@@ -33,8 +33,7 @@ import java.util.function.BiFunction;
 import java.util.stream.Collectors;
 
 import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.*;
-import static com.yonge.cooleshow.common.constant.SysConfigConstant.DESTROY_EXPIRED_LIVE_ROOM_MINUTE;
-import static com.yonge.cooleshow.common.constant.SysConfigConstant.PRE_CREATE_LIVE_ROOM_MINUTE;
+import static com.yonge.cooleshow.common.constant.SysConfigConstant.*;
 
 /**
  * 直播房间与课程的关系表表(LiveRoom)表服务实现类
@@ -340,6 +339,64 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
     /**
+     * 定时任务-清理过期的房间-陪练课
+     */
+    public void destroyExpiredPracticeRoom() {
+        //查询房间过期时间
+        String expiredMinuteStr = sysConfigService.findConfigValue(PRE_CREATE_PRACTICE_ROOM_MINUTE);
+        if (StringUtils.isEmpty(expiredMinuteStr)) {
+            log.info("roomDestroy>>>> 未查询到配置:{}", PRE_CREATE_PRACTICE_ROOM_MINUTE);
+            return;
+        }
+        Date now = new Date();
+        //查询已经开始并且没有删除及销毁的直播间
+        List<LiveRoom> list = this.list(Wrappers.<LiveRoom>lambdaQuery()
+                .eq(LiveRoom::getRoomState, 0)
+                .eq(LiveRoom::getLiveState, 1)
+                .eq(LiveRoom::getType, RoomTypeEnum.PRACTICE.getCode())
+                .le(LiveRoom::getLiveEndTime, now));
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+        list.forEach(room -> {
+            Date expiredDate = DateUtil.addMinutes(room.getLiveEndTime(), Integer.parseInt(expiredMinuteStr));
+            //当前时间 大于(结束播时间 + 设置的过期分钟数)
+            if (now.getTime() >= expiredDate.getTime()) {
+                //删除房间
+                destroyLiveRoom(room.getRoomUid());
+                //查询老师分润表
+                CourseScheduleTeacherSalary salary = courseScheduleTeacherSalaryService.getOne(Wrappers.<CourseScheduleTeacherSalary>lambdaQuery()
+                        .eq(CourseScheduleTeacherSalary::getCourseScheduleId, room.getCourseId())
+                );
+                if (Objects.isNull(salary)) {
+                    return;
+                }
+                //查询该学生及课程id 对应的支付订单号
+                CourseScheduleStudentPayment payment = courseScheduleStudentPaymentService.getOne(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
+                        .eq(CourseScheduleStudentPayment::getCourseId, room.getCourseId())
+                        .eq(CourseScheduleStudentPayment::getUserId, salary.getStudentId())
+                );
+                if (Objects.isNull(payment)) {
+                    return;
+                }
+                //获取教师课酬写入到金额变更表
+                UserAccountRecordDto userAccountRecord = new UserAccountRecordDto();
+                userAccountRecord.setUserId(room.getSpeakerId());
+                userAccountRecord.setInOrOut(InOrOutEnum.IN);
+                userAccountRecord.setBizType(AccountBizTypeEnum.PRACTICE);
+                userAccountRecord.setBizId(room.getCourseId());
+                userAccountRecord.setBizName(room.getRoomTitle());
+                userAccountRecord.setTransAmount(salary.getActualSalary());//扣除手续费后所得金额
+                userAccountRecord.setOrderNo(payment.getOrderNo());
+                userAccountService.accountChange(userAccountRecord);
+                //修改老师课酬表
+                salary.setStatus(TeacherSalaryEnum.COMPLETE.getCode());
+                courseScheduleTeacherSalaryService.updateById(salary);
+            }
+        });
+    }
+
+    /**
      * 销毁房间-聊天室
      *
      * @param roomId 房间Uid

+ 0 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MemberPriceSettingsServiceImpl.java

@@ -118,7 +118,6 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
 
         //会员购买消息推送
         authSend(studentVo.getUserId(), studentVo.getPhone(), DateUtil.format(vipCardRecord.getEndTime(), DateUtil.DEFAULT_PATTERN));
-
     }
 
 

+ 15 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserContractRecordServiceImpl.java

@@ -3,7 +3,9 @@ package com.yonge.cooleshow.biz.dal.service.impl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.biz.dal.dao.SysUserContractRecordDao;
 import com.yonge.cooleshow.biz.dal.entity.SysUserContractRecord;
+import com.yonge.cooleshow.biz.dal.service.ContractTemplateService;
 import com.yonge.cooleshow.biz.dal.service.SysUserContractRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import org.slf4j.Logger;
@@ -20,10 +22,23 @@ public class SysUserContractRecordServiceImpl extends ServiceImpl<SysUserContrac
 
     private final static Logger log = LoggerFactory.getLogger(SysUserContractRecordServiceImpl.class);
 
+    @Autowired
+    private ContractTemplateService contractTemplateService;
+
     @Override
     public SysUserContractRecordDao getDao() {
         return this.baseMapper;
     }
 
+    /**
+     * 校验当前用户签署的协议是否是最新版本
+     */
+    public void checkContractRecord(Long userId,String type) {
+        //根据人员id及协议类型查询最新协议记录
+        //查询对应类型的最新的协议
+        //对比当前类型及人员id的协议版本
+        //如果不是最新版本,则返回false
+    }
+
 }
 

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherAuthEntryRecordServiceImpl.java

@@ -118,7 +118,7 @@ public class TeacherAuthEntryRecordServiceImpl extends ServiceImpl<TeacherAuthEn
         } else {
             try {
                 sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_AUTH_FAIL,
-                        receivers, null, 0, null, ClientEnum.TEACHER.getCode(), reason, "app内认证链接");
+                        receivers, null, 0, null, ClientEnum.TEACHER.getCode(), reason, MessageTypeEnum.TEACHER_AUTH_FAIL.getUrl());
             } catch (Exception e) {
                 log.error("入驻审核极光消息推送异常,userId={}", userId);
             }

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherAuthMusicianRecordServiceImpl.java

@@ -124,7 +124,7 @@ public class TeacherAuthMusicianRecordServiceImpl extends ServiceImpl<TeacherAut
         if (isPass) {
             try {
                 sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.MUSICIAN_AUTH_PASS,
-                        receivers, null, 0, null, ClientEnum.TEACHER.getCode(), "app内上传乐谱链接");
+                        receivers, null, 0, null, ClientEnum.TEACHER.getCode(), MessageTypeEnum.MUSICIAN_AUTH_PASS.getUrl());
             } catch (Exception e) {
                 log.error("音乐人认证极光消息推送异常,userId={}", userId);
             }

+ 62 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderRefundsServiceImpl.java

@@ -1,7 +1,18 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
+import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
+import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
+import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
+import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
+import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.biz.dal.vo.res.RefundCreateRes;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.yonge.cooleshow.biz.dal.entity.UserOrderRefunds;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderRefundsVo;
@@ -9,9 +20,40 @@ import com.yonge.cooleshow.biz.dal.dto.search.OrderRefundsSearch;
 import com.yonge.cooleshow.biz.dal.dao.UserOrderRefundsDao;
 import com.yonge.cooleshow.biz.dal.service.UserOrderRefundsService;
 
+import javax.annotation.PostConstruct;
+import java.sql.Wrapper;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
 
 @Service
 public class UserOrderRefundsServiceImpl extends ServiceImpl<UserOrderRefundsDao, UserOrderRefunds> implements UserOrderRefundsService {
+    @Autowired
+    private CourseGroupService courseGroupService;
+
+    //验证是否可以退款,获取退款金额信息
+    private static final Map<GoodTypeEnum, Function<OrderRefundReq, HttpResponseResult<RefundCreateRes>>> refundCreate = new HashMap<>();
+    //插入退款后执行
+    private static final Map<GoodTypeEnum, Consumer<UserOrderRefundsVo>> refundAfter = new HashMap<>();
+    //退款完成后执行
+    private static final Map<GoodTypeEnum, Consumer<UserOrderRefundsVo>> refundSuccess = new HashMap<>();
+    //退款未通过后执行
+    private static final Map<GoodTypeEnum, Consumer<UserOrderRefundsVo>> refundCancel = new HashMap<>();
+
+    @PostConstruct
+    private void init() {
+        /**********退费单生成前******************/
+        //直播课退费
+        refundCreate.put(GoodTypeEnum.LIVE, courseGroupService::refundCreate);
+
+        refundAfter.put(GoodTypeEnum.LIVE, courseGroupService::refundAfter);
+
+        refundSuccess.put(GoodTypeEnum.LIVE, courseGroupService::refundSuccess);
+
+        refundCancel.put(GoodTypeEnum.LIVE, courseGroupService::refundCancel);
+    }
 
 	@Override
     public UserOrderRefundsVo detail(Long id) {
@@ -23,5 +65,24 @@ public class UserOrderRefundsServiceImpl extends ServiceImpl<UserOrderRefundsDao
     public IPage<UserOrderRefundsVo> selectPage(IPage<UserOrderRefundsVo> page, OrderRefundsSearch query){
         return page.setRecords(baseMapper.selectPage(page, query));
     }
-	
+
+    @Override
+    public HttpResponseResult<Boolean> orderRefund(OrderRefundReq refundReq) {
+        UserOrderRefunds old = baseMapper.selectOne(Wrappers.<UserOrderRefunds>lambdaQuery()
+                .eq(UserOrderRefunds::getUserId, refundReq.getUserId())
+                .eq(UserOrderRefunds::getOrderNo, refundReq.getOrderNo())
+                .eq(UserOrderRefunds::getOrderDetilId, refundReq.getOrderDetilId()));
+        if(null != old){
+            return HttpResponseResult.failed("已存在退款记录");
+        }
+        UserOrderRefunds orderRefunds = new UserOrderRefunds();
+        orderRefunds.setUserId(refundReq.getUserId());
+        orderRefunds.setOrderNo(refundReq.getOrderNo());
+        orderRefunds.setOrderDetilId(refundReq.getOrderDetilId());
+        orderRefunds.setReason(refundReq.getReason());
+        orderRefunds.setStatus(AuthStatusEnum.DOING);
+
+        return null;
+    }
+
 }

+ 38 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java

@@ -2,9 +2,11 @@ package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.biz.dal.config.HuifuConfiguration;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
 import com.yonge.cooleshow.biz.dal.enums.*;
 import com.yonge.cooleshow.biz.dal.support.DistributedLock;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
@@ -59,6 +61,8 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
     @Autowired
     private UserOrderPaymentService orderPaymentService;
     @Autowired
+    private UserOrderRefundsService orderRefundsService;
+    @Autowired
     private PaymentSdk paymentSdk;
     @Autowired
     private IdGeneratorService idGeneratorService;
@@ -73,7 +77,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
     @Autowired
     private RedissonClient redissonClient;
 
-    //验证订单是否可以下单
+    //验证订单是否可以下单,获取订单金额信息
     private static final Map<GoodTypeEnum, Function<OrderReq.OrderReqInfo, HttpResponseResult<OrderCreateRes>>> orderCreate = new HashMap<>();
     //插入订单后执行
     private static final Map<GoodTypeEnum, Consumer<UserOrderDetailVo>> orderAfter = new HashMap<>();
@@ -204,6 +208,38 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HttpResponseResult<Boolean> orderRefund(OrderRefundReq refundReq) {
+        UserOrderVo detail = detail(refundReq.getOrderNo(), refundReq.getUserId());
+        if (null == detail || CollectionUtils.isEmpty(detail.getOrderDetailList())) {
+            return HttpResponseResult.failed("未找到订单信息");
+        }
+        if (!OrderStatusEnum.PAID.equals(detail.getStatus())) {
+            return HttpResponseResult.failed("订单状态异常");
+        }
+        UserOrderDetailVo orderDetail = null;
+        for (UserOrderDetailVo vo : detail.getOrderDetailList()) {
+            if(vo.getId().equals(refundReq.getOrderDetilId())){
+                orderDetail = vo;
+            }
+        }
+
+        if (null == orderDetail) {
+            return HttpResponseResult.failed("未找到订单信息");
+        }
+
+        if (StringUtil.isEmpty(detail.getTransNo())) {
+            return HttpResponseResult.failed("未找到订单付款信息");
+        }
+        UserOrderPayment orderPayment = orderPaymentService.detailByTransNo(detail.getTransNo());
+        if (null == orderPayment || !TradeStatusEnum.succeeded.equals(orderPayment.getStatus())) {
+            return HttpResponseResult.failed("订单付款状态异常");
+        }
+        //发起退款申请
+        return orderRefundsService.orderRefund(refundReq);
+    }
+
+    @Override
     public void setSuccessStatus() {
         OrderSearch query = new OrderSearch();
         query.setStatus("WAIT_PAY,PAYING");
@@ -345,7 +381,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
      */
     private void paymentSucceededHandle(JSONObject hfRes) {
         UserOrderPayment orderPayment = orderPaymentService.detailByAdapayNo(hfRes.getString("order_no"));
-        if(null == orderPayment){
+        if (null == orderPayment) {
             return;
         }
         //订单完成

+ 10 - 4
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserWithdrawalServiceImpl.java

@@ -39,10 +39,7 @@ import org.springframework.util.DigestUtils;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
 
 @Service
@@ -282,4 +279,13 @@ public class UserWithdrawalServiceImpl extends ServiceImpl<UserWithdrawalDao, Us
         return subtract;
     }
 
+    /**
+     * @Description: 提现成功回调
+     * @Author: cy
+     * @Date: 2022/5/9
+     */
+    @Override
+    public void withdrawSuccess(Map<String, Object> withdrawRecord) {
+        baseMapper.withdrawSuccess(withdrawRecord);
+    }
 }

+ 4 - 4
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/VipCardRecordServiceImpl.java

@@ -91,14 +91,14 @@ public class VipCardRecordServiceImpl extends ServiceImpl<VipCardRecordDao, VipC
         receivers.put(userId, phone);
         try {
             sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.VIP_EXPIRE_THIRTY_DAY,
-                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), "会员中心链接");
+                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), MessageTypeEnum.VIP_EXPIRE_THIRTY_DAY.getUrl());
         } catch (Exception e) {
             log.error("会员到期3天极光消息推送异常,userId={}", userId);
         }
 
         try {
             sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_VIP_EXPIRE_THIRTY_DAY,
-                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), "会员中心链接");
+                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), MessageTypeEnum.SMS_VIP_EXPIRE_THIRTY_DAY.getUrl());
         } catch (Exception e) {
             log.error("会员到期3天短信消息推送异常,userId={}", userId);
         }
@@ -110,14 +110,14 @@ public class VipCardRecordServiceImpl extends ServiceImpl<VipCardRecordDao, VipC
         receivers.put(userId, phone);
         try {
             sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.VIP_EXPIRE,
-                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), "会员中心链接");
+                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), MessageTypeEnum.VIP_EXPIRE.getUrl());
         } catch (Exception e) {
             log.error("会员到期3天极光消息推送异常,userId={}", userId);
         }
 
         try {
             sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_VIP_EXPIRE,
-                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), "会员中心链接");
+                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), MessageTypeEnum.SMS_VIP_EXPIRE.getUrl());
         } catch (Exception e) {
             log.error("会员到期3天短信消息推送异常,userId={}", userId);
         }

+ 85 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseHomeVo.java

@@ -0,0 +1,85 @@
+package com.yonge.cooleshow.biz.dal.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.List;
+
+@ApiModel(description = "首页课程信息")
+public class CourseHomeVo {
+
+    @ApiModelProperty(value = "未完成课程总数")
+    private Integer totalUndoneCount;
+    @ApiModelProperty(value = "已完成课程总数")
+    private Integer totalDoneCount;
+    @ApiModelProperty(value = "总课程数")
+    private Integer totalCount;
+    @ApiModelProperty(value = "数据明细")
+    private List<CourseHomeInfoVo> courseHomeInfoList;
+
+    @ApiModel(description = "首页课程明细")
+    public static class CourseHomeInfoVo {
+        @ApiModelProperty(value = "日期-按年查询返回年月 按月查询返回年月日")
+        private String date;
+        @ApiModelProperty(value = "未完成课程数")
+        private Integer undoneCount;
+        @ApiModelProperty(value = "已完成课程数")
+        private Integer doneCount;
+
+        public String getDate() {
+            return date;
+        }
+
+        public void setDate(String date) {
+            this.date = date;
+        }
+
+        public Integer getUndoneCount() {
+            return undoneCount;
+        }
+
+        public void setUndoneCount(Integer undoneCount) {
+            this.undoneCount = undoneCount;
+        }
+
+        public Integer getDoneCount() {
+            return doneCount;
+        }
+
+        public void setDoneCount(Integer doneCount) {
+            this.doneCount = doneCount;
+        }
+    }
+
+    public Integer getTotalUndoneCount() {
+        return totalUndoneCount;
+    }
+
+    public void setTotalUndoneCount(Integer totalUndoneCount) {
+        this.totalUndoneCount = totalUndoneCount;
+    }
+
+    public Integer getTotalDoneCount() {
+        return totalDoneCount;
+    }
+
+    public void setTotalDoneCount(Integer totalDoneCount) {
+        this.totalDoneCount = totalDoneCount;
+    }
+
+    public Integer getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(Integer totalCount) {
+        this.totalCount = totalCount;
+    }
+
+    public List<CourseHomeInfoVo> getCourseHomeInfoList() {
+        return courseHomeInfoList;
+    }
+
+    public void setCourseHomeInfoList(List<CourseHomeInfoVo> courseHomeInfoList) {
+        this.courseHomeInfoList = courseHomeInfoList;
+    }
+}

+ 56 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/res/RefundCreateRes.java

@@ -0,0 +1,56 @@
+package com.yonge.cooleshow.biz.dal.vo.res;
+
+import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022/3/31 16:18
+ */
+@ApiModel(value = "OrderCheckRes", description = "退款创建业务返回对象")
+public class RefundCreateRes {
+    @ApiModelProperty("验证结果(必填)")
+    private Boolean res;
+    @ApiModelProperty("实际价格(必填)")
+    private BigDecimal actualPrice;
+
+    @ApiModelProperty("商品类型:  VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播")
+    private GoodTypeEnum goodType;
+    @ApiModelProperty(value = "冗余字段,用于传递参数用")
+    private Object bizParam;
+
+    public Boolean getRes() {
+        return res;
+    }
+
+    public void setRes(Boolean res) {
+        this.res = res;
+    }
+
+    public BigDecimal getActualPrice() {
+        return actualPrice;
+    }
+
+    public void setActualPrice(BigDecimal actualPrice) {
+        this.actualPrice = actualPrice;
+    }
+
+    public GoodTypeEnum getGoodType() {
+        return goodType;
+    }
+
+    public void setGoodType(GoodTypeEnum goodType) {
+        this.goodType = goodType;
+    }
+
+    public Object getBizParam() {
+        return bizParam;
+    }
+
+    public void setBizParam(Object bizParam) {
+        this.bizParam = bizParam;
+    }
+}

+ 32 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -655,4 +655,36 @@
         FROM course_schedule_replied
         WHERE student_id_=#{studentId}
     </select>
+
+
+    <select id="queryCourseHomeOfYear" parameterType="map"
+            resultType="com.yonge.cooleshow.biz.dal.vo.CourseHomeVo$CourseHomeInfoVo">
+        select `date`,
+               sum(a.not_start_count) as undoneCount,
+               sum(a.complete_count)  as doneCount
+        from (select date_format(class_date_, '%Y-%m-01')                                      as `date`,
+                     ifnull(case when status_ in ('NOT_START', 'ING') then count(1) end, 0) as not_start_count,
+                     ifnull(case when status_ = 'COMPLETE' then count(1) end, 0)            as complete_count
+              from course_schedule
+              where type_ = #{param.type}
+                and status_ in ('NOT_START', 'ING', 'COMPLETE')
+        <![CDATA[ AND class_date_ >= #{param.startDate} ]]>
+        <![CDATA[ AND class_date_ <= #{param.endDate} ]]>
+        group by class_date_) as a
+        group by date
+    </select>
+
+    <select id="queryCourseHomeOfMonth" parameterType="map"
+            resultType="com.yonge.cooleshow.biz.dal.vo.CourseHomeVo$CourseHomeInfoVo">
+        select class_date_                                                            as `date`,
+               ifnull(case when status_ in ('NOT_START', 'ING') then count(1) end, 0) as undoneCount,
+               ifnull(case when status_ = 'COMPLETE' then count(1) end, 0)            as doneCount
+        from course_schedule
+        where type_ = #{param.type}
+          and status_ in ('NOT_START', 'ING', 'COMPLETE')
+        <![CDATA[ AND class_date_ >= #{param.startDate} ]]>
+        <![CDATA[ AND class_date_ <= #{param.endDate} ]]>
+        group by class_date_
+    </select>
+
 </mapper>

+ 3 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderRefundsMapper.xml

@@ -5,7 +5,8 @@
             <result column="id_" property="id" />
 	        <result column="user_id_" property="userId" />
 	        <result column="order_no_" property="orderNo" />
-	        <result column="status_" property="status" />
+            <result column="order_detil_id_" property="orderDetilId" />
+            <result column="status_" property="status" />
 	        <result column="apply_amount_" property="applyAmount" />
 	        <result column="actual_amount_" property="actualAmount" />
 	        <result column="reason_" property="reason" />
@@ -20,6 +21,7 @@
          t.id_ as id
         , t.user_id_ as userId
         , t.order_no_ as orderNo
+        , t.order_detil_id_ as orderDetilId
         , t.status_ as status
         , t.apply_amount_ as applyAmount
         , t.actual_amount_ as actualAmount

+ 7 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserWithdrawalMapper.xml

@@ -81,4 +81,11 @@
     <select id="selectList" resultType="com.yonge.cooleshow.biz.dal.vo.UserWithdrawalVo">
         <include refid="selectSql"/>
     </select>
+
+    <insert id="withdrawSuccess" parameterType="java.util.Map">
+        INSERT INTO user_withdrawal_history
+        VALUES (#{outMemberNo},#{outerOrderNo},#{orderNo},#{name},#{mobile},#{certificateNo},
+                #{status},#{payType},#{payAccount},#{predictAmount},#{actualAmount},#{endTime})
+    </insert>
+
 </mapper>

+ 2 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/MusicSheetController.java

@@ -87,7 +87,7 @@ public class MusicSheetController extends BaseController {
 
     @ApiOperation(value = "乐谱(专辑和曲目同时查询)分页查询", httpMethod="POST", consumes="application/json", produces="application/json")
     @PostMapping(value="/albumAndSheetList", consumes="application/json", produces="application/json")
-    public HttpResponseResult<AlbumAndSheetVo> albumAndSheetlist(@RequestBody StudentMusicSheetSearch query) {
+    public HttpResponseResult<AlbumAndSheetVo> albumAndSheetList(@RequestBody StudentMusicSheetSearch query) {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         if (sysUser == null  || sysUser.getId() == null) {
             return failed("用户信息获取失败");
@@ -106,6 +106,7 @@ public class MusicSheetController extends BaseController {
         MusicAlbumSearch musicAlbumSearch = new MusicAlbumSearch();
         musicAlbumSearch.setAlbumStatus(YesOrNoEnum.YES);
         musicAlbumSearch.setSortBy(1);
+        musicAlbumSearch.setIdAndName(query.getIdAndName());
         musicAlbumSearch.setAuditVersion(appAuditVersion);
         musicAlbumSearch.setAlbumTagIds(query.getMusicTagIds());
         musicAlbumSearch.setPage(query.getPage());

+ 1 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/PaymentController.java

@@ -96,7 +96,7 @@ public class PaymentController extends BaseController {
             String sign = request.getParameter("sign");
             //回调业务类型
             String type = request.getParameter("type");
-            log.info("汇付回调,type is {},type is {}, res is {}", type, sign, data);
+            log.info("汇付回调,type is {},sign is {}, data is {}", type, sign, data);
             if (StringUtil.isEmpty(type)) {
                 log.error("汇付回调参数异常");
                 return;

+ 6 - 0
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/StudentLiveRoomController.java

@@ -80,6 +80,12 @@ public class StudentLiveRoomController extends BaseController {
         liveRoomService.destroyExpiredLiveRoom();
     }
 
+    @ApiOperation("定时任务-销毁房间-直播间-陪练课")
+    @GetMapping("/destroyExpiredPracticeRoom")
+    public void destroyExpiredPracticeRoom() {
+        liveRoomService.destroyExpiredPracticeRoom();
+    }
+
     /**
      * 同步融云用户状态变更
      *

+ 22 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/UserOrderController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderRefundReq;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
 import com.yonge.cooleshow.biz.dal.entity.UserOrder;
@@ -140,7 +141,7 @@ public class UserOrderController extends BaseController {
             @ApiImplicitParam(name = "orderNo", value = "订单号", paramType = "query", dataType = "String", required = true),
             @ApiImplicitParam(name = "reason", value = "取消说明", paramType = "query", dataType = "String")
     })
-    public HttpResponseResult<Boolean> orderCancel(@ApiIgnore @RequestBody OrderPayReq payReq, HttpServletRequest request) {
+    public HttpResponseResult<Boolean> orderCancel(@ApiIgnore @RequestBody OrderPayReq payReq) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");
@@ -162,6 +163,26 @@ public class UserOrderController extends BaseController {
         }
     }
 
+    @ApiOperation(value = "订单退款")
+    @PostMapping("/orderRefund")
+    public HttpResponseResult<Boolean> orderRefund(@RequestBody OrderRefundReq refundReq) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        refundReq.setUserId(user.getId());
+        Future<HttpResponseResult<Boolean>> httpResponseResultFuture = DistributedLock.of(redissonClient)
+                .callIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(user.getId())
+                        , () -> userOrderService.orderRefund(refundReq), 60L, TimeUnit.SECONDS);
+
+        try {
+            return httpResponseResultFuture.get();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return HttpResponseResult.failed("订单退款失败");
+        }
+    }
+
     /**
      * 查询分页
      */

+ 1 - 1
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/config/ResourceServerConfig.java

@@ -33,7 +33,7 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
 				.authorizeRequests()
 				.antMatchers("/task/**").hasIpAddress("0.0.0.0/0")
 				.antMatchers("/v2/api-docs", "/code/*","/payment/callback",
-                        "/liveRoom/test","/liveRoom/syncUserStatus","/courseGroup/getLockCache")
+                        "/liveRoom/test","/liveRoom/syncUserStatus","/courseGroup/getLockCache","/withdraw/callback")
                 .permitAll().anyRequest().authenticated().and().httpBasic();
 	}
 

+ 6 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherLiveRoomController.java

@@ -80,6 +80,12 @@ public class TeacherLiveRoomController extends BaseController {
         liveRoomService.destroyExpiredLiveRoom();
     }
 
+    @ApiOperation("定时任务-销毁房间-直播间-陪练课")
+    @GetMapping("/destroyExpiredPracticeRoom")
+    public void destroyExpiredPracticeRoom() {
+        liveRoomService.destroyExpiredPracticeRoom();
+    }
+
     /**
      * 同步融云用户状态变更
      *

+ 95 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/WithdrawController.java

@@ -0,0 +1,95 @@
+package com.yonge.cooleshow.teacher.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.yonge.cooleshow.biz.dal.service.UserWithdrawalService;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.toolset.thirdparty.lingxinpay.RSA;
+import com.yonge.toolset.thirdparty.lingxinpay.Withdraw;
+import io.swagger.annotations.Api;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @Description: 提现回调
+ * @Author: cy
+ * @Date: 2022/5/9
+ */
+@RestController
+@RequestMapping("/withdraw")
+@Api(value = "提现回调", tags = "提现回调")
+public class WithdrawController extends BaseController {
+    private final static Logger log = LoggerFactory.getLogger(WithdrawController.class);
+
+    //这里需要填写商户自己生成的私钥
+    private String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANf/X1s2raYQAmY5VY929XqOIRESFlpLzWbltA08EI2i0jnJY3/kcCpo1sCHqkyWpDFGRgM1WYE90ayzEpS6EdZpyJ2/N5JFJzx4wMil5KHLdtQUmVv9si+xuYNOKfJW6Xn6zI/Wh81J1+hMlUY4WigU5Qci7DjdOjg5OD6e5DO3AgMBAAECgYEAor9ENhII3SsK48MneKWFaQZWW+po9ThQV8uT0rUDM/UOuYPIeMDC0vGTfhW6d2K57Haqohg8jGjr51g2E+HvNV+fARaBfCwy00DGcxjI6N8gEInj2AppsGV6a0ZtzGBh3BxGhEFV7x3NmTylDk3WkGnkGDqDNyrBUgK0BzCJEmECQQD+gYckYRevVfrZEHDQHRNzzMUlV9/ljA9x8dt0LoCNbd/wFvs0Ekjhas/2lUBkewEd4Kr0jaFcYzlUO/qihcpNAkEA2UP5W44yLuIo8ttPpdsfkH/8Ax64IywQHrXWq+thH7I91VwY2vomTduw8x0PafZtp8xryF3LixTZwQ7gsYbwEwJAQbb8SB5x2SogPVALcREw5qOm+/92pnTFwCws+BDRzLLkMcAdWNKn0tybmhXrrIY+QZKzUbYIRiywrtlV3AUjuQJBAJbnFnfX4NUdchGT79Mjyd2kdxZ3rK+JOD0MUWkhWFkahMX/bKgTXK1xLIr/ISiY53rHigkl1Gzqc4Aa5EeJkI8CQFlzlBOfoVnq3fPMZCCZcZSm97L12MgHho0AzoNj9sw9YYn9WPM7bw2HT8GUheiU3aiZGCyGGpYuVHMiBGa7l9U=";
+
+    @Autowired
+    private UserWithdrawalService userWithdrawalService;
+
+    /**
+     * 异步回调接收
+     *
+     * @param content
+     * @param request
+     * @return
+     */
+    @PostMapping("/callback")
+    public String test(@RequestBody String content, HttpServletRequest request) {
+        log.info("交易回调请求地址:{} 请求参数:{}", request.getRemoteAddr(), content);
+        try {
+            if (StringUtils.isBlank(content)) {
+                throw new Exception();
+            }
+            Map<String, Object> map = JSONObject.parseObject(content);
+            String jsonStr = RSA.decryptPri((String) map.get("sign"), privateKey);
+            log.info("jsonStr:{}", jsonStr);
+
+//            Map<String, Object> withdrawRecord = JSONObject.parseObject(jsonStr);
+//            userWithdrawalService.withdrawSuccess(withdrawRecord);
+            return jsonStr;
+        } catch (Exception e) {
+            log.error("解密失败e:{}", e);
+            return "failed";
+        }
+    }
+    @GetMapping("/test")
+    public String a(){
+        Withdraw withdraw = new Withdraw();
+
+        //输入商户订单号
+        String outerOrderNo = UUID.randomUUID().toString().substring(0, 12);
+        System.out.println("商户订单号:"+outerOrderNo);
+        //输入收款人手机号
+        String name = "何亮";
+        //输入收款人姓名
+        String mobile = "17600220933";
+        //输入收款人身份证号
+        String certificateNo = "130423199206192818";
+        //输入转账金额(单位分)
+        String predictAmount = "1";
+        //输入收款人账号
+        String payAccount = "6228480018864836772";
+        //输入卡类型:DC借记卡,CC信用卡(暂不支持)
+        String cardType = "DC";
+        //输入发放类型(0:工资,1:奖金,2:绩效,3:劳务,4:个人经营所得,5:其他)
+        String salaryType = "4";
+        //输入项目名称
+        String projectName = "测试";
+        //输入支付类型(1:银行卡)
+        String payType = "1";
+        //输入卡属性:(C:对私 ,B:对公)暂时不支持对公
+        String cardAttribute = "C";
+
+        String requestParam = withdraw.withdraw(outerOrderNo, name, mobile, certificateNo, predictAmount, payAccount, cardType,
+                salaryType, projectName, payType, cardAttribute);
+        log.info("单笔请求返回参数:{}", requestParam);
+        return requestParam;
+    }
+}

+ 113 - 0
toolset/thirdparty-component/src/main/java/com/yonge/toolset/thirdparty/lingxinpay/Md5EncryptUtils.java

@@ -0,0 +1,113 @@
+package com.yonge.toolset.thirdparty.lingxinpay;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * MD5加密算法
+ * @author xumum
+ *
+ */
+public class Md5EncryptUtils {
+	/**
+	 * Used building output as Hex
+	 */
+	private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6',
+			'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+	/**
+	 * 对字符串进行MD5加密
+	 * @param text 明文
+	 * @return 密文
+	 */
+	public static String md5(String text) {
+		MessageDigest msgDigest = null;
+		try {
+			msgDigest = MessageDigest.getInstance("MD5");
+		} catch (NoSuchAlgorithmException e) {
+			throw new IllegalStateException(
+					"System doesn't support MD5 algorithm.");
+		}
+		try {
+			msgDigest.update(text.getBytes("UTF-8"));
+		} catch (UnsupportedEncodingException e) {
+			throw new IllegalStateException(
+					"System doesn't support your  EncodingException.");
+		}
+		byte[] bytes = msgDigest.digest();
+		String md5Str = new String(encodeHex(bytes));
+		return md5Str;
+	}
+
+	public static char[] encodeHex(byte[] data) {
+		int l = data.length;
+		char[] out = new char[l << 1];
+		for (int i = 0, j = 0; i < l; i++) {
+			out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
+			out[j++] = DIGITS[0x0F & data[i]];
+		}
+		return out;
+	}
+	
+	
+	/** 
+     * 方法描述:签名字符串 
+     * @author xumum
+     * @param params 需要签名的参数 
+     * @param key 签名密钥 
+     * @return 
+     */  
+    public static String sign(Map<String, Object> params, String key) {  
+        StringBuilder valueSb = new StringBuilder();  
+       
+        // 将参数以参数名的字典升序排序  
+        Map<String, Object> sortParams = new TreeMap<String, Object>(params);  
+        Set<Entry<String, Object>> entrys = sortParams.entrySet();  
+        // 参数以参数名的字典升序排序 ,并拼接param1=value1&param2=value2...&key=value格式  
+        for (Entry<String, Object> entry : entrys) {  
+        	valueSb.append(entry.getKey());
+        	valueSb.append("=");
+            valueSb.append(entry.getValue());  
+            valueSb.append("&");  
+        }  
+        String paramStr = valueSb.toString();
+        paramStr = paramStr.substring(0, paramStr.length()-1);
+        return MD5sign(paramStr,key);  
+    }  
+    
+    /** 
+     * MD5生成签名字符串 
+     * @param parmas 需签名参数
+     * @param key MD5key 
+     * @return 
+     */  
+    public static String MD5sign(String parmas, String key) {  
+        String sign = "";
+        try {  
+        	parmas += "&key=" + key;  
+        	sign = md5(parmas);  
+        } catch (Exception e) {  
+            e.printStackTrace();  
+        }  
+        return sign;  
+    }  
+    
+    public static void main(String[] args) {  
+        Map<String ,Object> map = new HashMap<String,Object>();  
+        map.put("companyNo", "1504a229bb034f19b6bf21738976981d");  
+        map.put("salaryOrderCode", "2018040353359360");  
+        map.put("predictNumber", 1);  
+        map.put("predictTotalSum", "1.00");  
+        /***MD5签名与验签**/  
+        String key="7d50522f57df480c80c16703493bf259";  
+        String sign= sign(map,key);  
+        System.out.println("生成的MD5签名:"+sign);  
+    }  
+
+}

+ 147 - 0
toolset/thirdparty-component/src/main/java/com/yonge/toolset/thirdparty/lingxinpay/Withdraw.java

@@ -0,0 +1,147 @@
+package com.yonge.toolset.thirdparty.lingxinpay;
+
+import com.alibaba.fastjson.JSONObject;
+import com.yonge.toolset.utils.http.HttpUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author: cy
+ * @date: 2022/5/9 11:24
+ */
+@Service
+public class Withdraw {
+    private static final Logger logger = LoggerFactory.getLogger(Withdraw.class);
+
+    private String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYT5eCY6r8sGWgbiId/VqSZmS6XkBNGMkzUqTIkpkecOzsFBxFXTQmgDeR991YfgqmyOaHsJ/ons/H+e8l+RmHsOm4eErFU+9qXFq+k195YFV1vAR9O7MIG+FR5vmLDuhgimPsgqscWhUrGinc8RUpi5KwClgx7d+d8ZJ4GmkR0QIDAQAB";
+    private String md5Key = "0fd42370bad6485e46718b97f3dd1536";
+    private String notifyUrl = "http://47.114.1.200:8000/teacher-server/withdraw/callback";//回调地址
+    private String memberNo = "1491663782974988288";//商户号
+    private String apiUrl = "http://39.107.15.64:8090";//第三方url
+
+    /**
+     * 单笔提现
+     *
+     * @param outerOrderNo  商户唯一订单号
+     * @param name          收款方姓名(银行预留姓名等)
+     * @param mobile        收款方电话
+     * @param certificateNo 收款方身份证号
+     * @param predictAmount 应发金额(单位为:分,范围: 1~10000000000)
+     * @param payAccount    收款方账号(银行卡号/支付宝账号 /open_id)以实际业务为准
+     * @param cardType      卡类型:DC 借记卡
+     * @param salaryType    发放类型(0:个人经营所得)
+     * @param projectName   项目名称
+     * @param payType       支付类型(1:银行卡,2:支付宝,4:微信) 以实际业务为准
+     * @param cardAttribute 卡属性:(C:对私)
+     * @return
+     */
+    public String withdraw(String outerOrderNo, String name, String mobile, String certificateNo, String predictAmount,
+                           String payAccount, String cardType, String salaryType, String projectName, String payType, String cardAttribute) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("outMemberNo", memberNo);
+        map.put("outerOrderNo", outerOrderNo);
+        map.put("name", name);
+        map.put("certificateNo", certificateNo);
+        map.put("predictAmount", predictAmount);
+        String signs = Md5EncryptUtils.sign(map, md5Key);
+
+        map.put("charset", "UTF-8");
+        map.put("mobile", mobile);
+        map.put("version", "1.1");
+        map.put("service", "bpotop.zx.pay.order");
+        map.put("Md5Key", signs);
+        map.put("notifyUrl", notifyUrl);
+        map.put("cardType", cardType);
+        map.put("salaryType", salaryType);
+        map.put("projectName", projectName);
+        map.put("payType", payType);
+        map.put("cardAttribute", cardAttribute);
+        map.put("payAccount", payAccount);
+        String jsonStr = JSONObject.toJSONString(map);
+
+        //签名
+        JSONObject mapParam = new JSONObject();
+        try {
+            //使用公钥加密
+            String encryptStr = RSA.encryptPub(jsonStr, publicKey);
+            mapParam.put("outMemberNo", memberNo);
+            mapParam.put("signType", "RSA");
+            mapParam.put("sign", encryptStr);
+            logger.info("单笔请求请求参数:{}", JSONObject.toJSONString(mapParam));
+        } catch (Exception e) {
+            logger.info("加密失败:{}", e);
+        }
+
+        //发送
+        try {
+            String resultJsonStr = HttpUtil.postForHttp(apiUrl + "/bpotop_trade/single", JSONObject.toJSONString(mapParam), null);
+            logger.info("单笔请求返回参数:{}", resultJsonStr);
+            return resultJsonStr;
+        } catch (IOException e) {
+            logger.info("发送失败:{}", e);
+        }
+        return null;
+    }
+
+    /**
+     * 查询接口
+     *
+     * @param outerOrderNo 商户唯一订单号
+     * @throws Exception
+     */
+    public void query(String outerOrderNo) throws Exception {
+        Map<String, Object> requestMap = new HashMap<>();
+        requestMap.put("outMemberNo", memberNo);
+        requestMap.put("outerOrderNo", outerOrderNo);
+        requestMap.put("service", "bpotop.zx.pay.order");
+        requestMap.put("version", "1.0");
+        requestMap.put("signType", "RSA");
+        requestMap.put("charset", "UTF-8");
+        String jsonStr = JSONObject.toJSONString(requestMap);
+        String encryptStr = RSA.encryptPub(jsonStr, publicKey);
+
+        Map<String, Object> requestMap2 = new HashMap<>();
+        requestMap2.put("outMemberNo", memberNo);
+        requestMap2.put("sign", encryptStr);
+        logger.info("单笔查询请求参数:{}", JSONObject.toJSONString(requestMap2));
+        String resultJsonStr = HttpUtil.postForHttp(apiUrl + "/bpotop_trade/order_query", JSONObject.toJSONString(requestMap2), null);
+        logger.info("单笔查询响应参数:{}", resultJsonStr);
+    }
+
+    public static void main(String[] args) throws Exception {
+        Withdraw withdraw = new Withdraw();
+
+        //输入商户订单号
+        String outerOrderNo = UUID.randomUUID().toString().substring(0, 12);
+        //输入收款人手机号
+        String name = "何亮";
+        //输入收款人姓名
+        String mobile = "17600220933";
+        //输入收款人身份证号
+        String certificateNo = "130423199206192818";
+        //输入转账金额(单位分)
+        String predictAmount = "1";
+        //输入收款人账号
+        String payAccount = "6228480018864836772";
+        //输入卡类型:DC借记卡,CC信用卡(暂不支持)
+        String cardType = "DC";
+        //输入发放类型(0:工资,1:奖金,2:绩效,3:劳务,4:个人经营所得,5:其他)
+        String salaryType = "4";
+        //输入项目名称
+        String projectName = "测试";
+        //输入支付类型(1:银行卡)
+        String payType = "1";
+        //输入卡属性:(C:对私 ,B:对公)暂时不支持对公
+        String cardAttribute = "C";
+
+        String requestParam = withdraw.withdraw(outerOrderNo, name, mobile, certificateNo, predictAmount, payAccount, cardType,
+                salaryType, projectName, payType, cardAttribute);
+        logger.info("单笔请求返回参数:{}", requestParam);
+    }
+}