소스 검색

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseGroupServiceImpl.java
weifanli 3 년 전
부모
커밋
abcccc11e9
44개의 변경된 파일1103개의 추가작업 그리고 100개의 파일을 삭제
  1. 3 0
      cooleshow-cms/src/main/java/com/yonge/cooleshow/cms/controller/HelpCenterContentController.java
  2. 1 1
      cooleshow-cms/src/main/java/com/yonge/cooleshow/cms/dal/entity/HelpCenterContent.java
  3. 1 1
      cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/OmsOrderReturnApplyServiceImpl.java
  4. 4 2
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java
  5. 11 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/UserOrderPayment.java
  6. 16 5
      cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml
  7. 52 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/OrderCloseReq.java
  8. 1 1
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/OrderPayReq.java
  9. 39 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/res/OrderCloseRes.java
  10. 12 6
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/res/OrderPayRes.java
  11. 10 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/PaymentService.java
  12. 15 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/impl/AdapayPaymentServiceImpl.java
  13. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/component/CancelOrderReceiver.java
  14. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java
  15. 5 4
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/PaymentController.java
  16. 9 3
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/OmsPortalOrderService.java
  17. 6 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java
  18. 134 32
      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. 1 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicSheetController.java
  22. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java
  23. 7 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserWithdrawalDao.java
  24. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/LiveRoom.java
  25. 7 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleEnum.java
  26. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoomTypeEnum.java
  27. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/HomeService.java
  28. 5 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java
  29. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserWithdrawalService.java
  30. 25 19
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  31. 98 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/HomeServiceImpl.java
  32. 59 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java
  33. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserContractRecordServiceImpl.java
  34. 10 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserWithdrawalServiceImpl.java
  35. 85 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseHomeVo.java
  36. 32 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  37. 7 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserWithdrawalMapper.xml
  38. 2 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/MusicSheetController.java
  39. 6 0
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/StudentLiveRoomController.java
  40. 1 1
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/config/ResourceServerConfig.java
  41. 6 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherLiveRoomController.java
  42. 95 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/WithdrawController.java
  43. 113 0
      toolset/thirdparty-component/src/main/java/com/yonge/toolset/thirdparty/lingxinpay/Md5EncryptUtils.java
  44. 147 0
      toolset/thirdparty-component/src/main/java/com/yonge/toolset/thirdparty/lingxinpay/Withdraw.java

+ 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>

+ 52 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/OrderCloseReq.java

@@ -0,0 +1,52 @@
+package com.yonge.cooleshow.sdk.req;
+
+import io.swagger.annotations.ApiModel;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-05-05
+ */
+@ApiModel("关闭订单请求")
+public class OrderCloseReq {
+
+    /**
+     * 支付id
+     */
+    private String paymentId;
+
+    /**
+     * 关单描述
+     */
+    private String reason;
+
+    /**
+     * 扩展域
+     */
+    private String expend;
+
+    public String getPaymentId() {
+        return paymentId;
+    }
+
+    public void setPaymentId(String paymentId) {
+        this.paymentId = paymentId;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public void setReason(String reason) {
+        this.reason = reason;
+    }
+
+    public String getExpend() {
+        return expend;
+    }
+
+    public void setExpend(String expend) {
+        this.expend = expend;
+    }
+}

+ 1 - 1
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/OrderPayReq.java

@@ -42,7 +42,7 @@ public class OrderPayReq {
     @ApiModelProperty(value = "商品描述",hidden = true)
     private String goodDesc;
 
-    @ApiModelProperty("拉起支付信息")
+    @ApiModelProperty(value = "拉起支付信息",hidden = true)
     private String payInfo;
 
     public void orderStatus(Integer orderStatus) {

+ 39 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/res/OrderCloseRes.java

@@ -0,0 +1,39 @@
+package com.yonge.cooleshow.sdk.res;
+
+import io.swagger.annotations.ApiModel;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-05-05
+ */
+@ApiModel("关闭订单信息")
+public class OrderCloseRes {
+
+    /**
+     * 执行状态
+     */
+    private boolean status = true;
+
+    /**
+     * 错误信息
+     */
+    private String failMsg;
+
+    public boolean isStatus() {
+        return status;
+    }
+
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+
+    public String getFailMsg() {
+        return failMsg;
+    }
+
+    public void setFailMsg(String failMsg) {
+        this.failMsg = failMsg;
+    }
+}

+ 12 - 6
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/res/OrderPayRes.java

@@ -1,5 +1,6 @@
 package com.yonge.cooleshow.sdk.res;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.yonge.cooleshow.enums.PayStatusEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -15,23 +16,28 @@ public class OrderPayRes {
     @ApiModelProperty("pay_info")
     private String pay_info;
 
-    @ApiModelProperty("执行状态")
+    @ApiModelProperty(value = "执行状态",required = true)
+    @JsonIgnore
     private boolean status = true;
 
-    @ApiModelProperty("出错信息")
+    @ApiModelProperty(value = "出错信息",required = true)
+    @JsonIgnore
     private String message;
 
-    @ApiModelProperty("支付状态")
+    @ApiModelProperty(value = "支付状态",required = true)
+    @JsonIgnore
     private PayStatusEnum payStatus;
 
 
-    @ApiModelProperty("订单编号")
+    @ApiModelProperty(value = "订单编号",required = true)
+    @JsonIgnore
     private String orderNo;
 
-    @ApiModelProperty("支付方式")
+    @ApiModelProperty("支付渠道:  alipay 支付宝  wx_lite 微信")
     private String payChannel;
 
-    @ApiModelProperty("交易流水号")
+    @ApiModelProperty(value = "交易流水号",required = true)
+    @JsonIgnore
     private String transNo;
 
     public String getPay_amt() {

+ 10 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/PaymentService.java

@@ -1,7 +1,9 @@
 package com.yonge.cooleshow.service;
 
+import com.yonge.cooleshow.sdk.req.OrderCloseReq;
 import com.yonge.cooleshow.sdk.req.OrderPayReq;
 import com.yonge.cooleshow.sdk.req.OrderRefundReq;
+import com.yonge.cooleshow.sdk.res.OrderCloseRes;
 import com.yonge.cooleshow.sdk.res.OrderPayRes;
 import com.yonge.cooleshow.sdk.res.OrderRefundRes;
 
@@ -33,4 +35,12 @@ public interface PaymentService {
      * @return
      */
     OrderRefundRes orderRefund(OrderRefundReq refundReq);
+
+    /**
+     * 关闭订单
+     *
+     * @param closeReq 关闭订单
+     * @return
+     */
+    OrderCloseRes orderClose(OrderCloseReq closeReq);
 }

+ 15 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/impl/AdapayPaymentServiceImpl.java

@@ -9,9 +9,11 @@ import com.yonge.cooleshow.enums.PayStatusEnum;
 import com.yonge.cooleshow.sdk.adapay.PaymentSdk;
 import com.yonge.cooleshow.sdk.adapay.dto.RefundReq;
 import com.yonge.cooleshow.sdk.req.DeviceInfo;
+import com.yonge.cooleshow.sdk.req.OrderCloseReq;
 import com.yonge.cooleshow.sdk.req.OrderPayReq;
 import com.yonge.cooleshow.sdk.adapay.dto.PaymentReq;
 import com.yonge.cooleshow.sdk.req.OrderRefundReq;
+import com.yonge.cooleshow.sdk.res.OrderCloseRes;
 import com.yonge.cooleshow.sdk.res.OrderRefundRes;
 import com.yonge.cooleshow.sdk.res.OrderPayRes;
 import com.yonge.cooleshow.service.PaymentService;
@@ -142,4 +144,17 @@ public class AdapayPaymentServiceImpl implements PaymentService {
         }
         return orderRefundRes;
     }
+
+    @Override
+    public OrderCloseRes orderClose(OrderCloseReq closeReq) {
+        HttpResponseResult<Map<String, Object>> mapHttpResponseResult = paymentSdk.closePayment(closeReq.getPaymentId(),
+                                                                                                closeReq.getReason(),
+                                                                                                closeReq.getExpend());
+        OrderCloseRes closeRes = new OrderCloseRes();
+        if (!mapHttpResponseResult.getStatus()) {
+            closeRes.setFailMsg(mapHttpResponseResult.getMsg());
+            closeRes.setStatus(false);
+        }
+        return closeRes;
+    }
 }

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/component/CancelOrderReceiver.java

@@ -20,7 +20,7 @@ public class CancelOrderReceiver {
     private OmsPortalOrderService portalOrderService;
     @RabbitHandler
     public void handle(Long orderId){
-        portalOrderService.cancelOrder(orderId);
+        portalOrderService.cancelOrder(orderId, "超时取消");
         LOGGER.info("process orderId:{}",orderId);
     }
 }

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java

@@ -91,7 +91,7 @@ public class OmsPortalOrderController {
     @RequestMapping(value = "/cancelUserOrder", method = RequestMethod.POST)
     @ResponseBody
     public CommonResult cancelUserOrder(Long orderId) {
-        portalOrderService.cancelOrder(orderId);
+        portalOrderService.cancelOrder(orderId, "用户取消订单");
         return CommonResult.success(null);
     }
 

+ 5 - 4
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/PaymentController.java

@@ -13,6 +13,7 @@ import com.yonge.cooleshow.util.DistributedLock;
 import com.yonge.cooleshow.sdk.adapay.PaymentSdk;
 import com.yonge.cooleshow.sdk.req.OrderPayReq;
 import com.yonge.cooleshow.sdk.res.OrderPayRes;
+import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.utils.web.WebUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -94,9 +95,7 @@ public class PaymentController extends BaseController {
                 //验签成功逻辑
                 log.info("验签成功");
                 String type = request.getParameter("type");
-                if (type.contains("payment")) {
-                    portalOrderService.orderCallback(data);
-                }
+                portalOrderService.orderCallback(data,type);
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -124,7 +123,9 @@ public class PaymentController extends BaseController {
             }  else {
                 return failed(orderPayRes.getMessage());
             }
-        } catch (Exception e) {
+        }catch (BizException e) {
+            return failed(e.getMessage());
+        }catch (Exception e) {
             e.printStackTrace();
             return HttpResponseResult.failed("付款失败");
         }

+ 9 - 3
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/OmsPortalOrderService.java

@@ -10,7 +10,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Future;
 
 /**
  * 前台订单管理Service
@@ -45,7 +44,7 @@ public interface OmsPortalOrderService {
      * 取消单个超时订单
      */
     @Transactional
-    void cancelOrder(Long orderId);
+    void cancelOrder(Long orderId, String message);
 
     /**
      * 发送延迟消息取消订单
@@ -78,8 +77,15 @@ public interface OmsPortalOrderService {
     /**
      *
      * @param data
+     * @param type
+     */    /**
+     * 订单拉起支付
+     *
+     * @param payReq 支付信息
+     * @return
      */
-    void orderCallback(String data);
+    @Transactional
+    void orderCallback(String data, String type);
 
     /**
      * 订单拉起支付

+ 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);
+
 }

+ 134 - 32
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java

@@ -19,7 +19,9 @@ import com.yonge.cooleshow.portal.dao.SmsCouponHistoryDao;
 import com.yonge.cooleshow.portal.domain.*;
 import com.yonge.cooleshow.portal.service.*;
 import com.yonge.cooleshow.sdk.adapay.PaymentSdk;
+import com.yonge.cooleshow.sdk.req.OrderCloseReq;
 import com.yonge.cooleshow.sdk.req.OrderPayReq;
+import com.yonge.cooleshow.sdk.res.OrderCloseRes;
 import com.yonge.cooleshow.sdk.res.OrderPayRes;
 import com.yonge.cooleshow.service.PaymentService;
 import org.slf4j.Logger;
@@ -291,14 +293,14 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             if (timeOutOrder.getStatus() == 0) {
                 payingOrderHandle(timeOutOrder);
             } else if (timeOutOrder.getStatus() == 6) {
-                cancelOrder(timeOutOrder.getId());
+                cancelOrder(timeOutOrder.getId(), "超时取消");
             }
         }
         return timeOutOrders.size();
     }
 
     @Override
-    public void cancelOrder(Long orderId) {
+    public void cancelOrder(Long orderId, String message) {
         //查询未付款的取消订单
         OmsOrderExample example = new OmsOrderExample();
         example.createCriteria().andIdEqualTo(orderId).andDeleteStatusEqualTo(0);
@@ -325,11 +327,24 @@ 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();
+                orderCloseReq.setPaymentId(orderPayment.getTransNo());
+                orderCloseReq.setReason(message);
+                OrderCloseRes closeRes = adapayPaymentService.orderClose(orderCloseReq);
+                if (closeRes.isStatus()) {
+                    orderPayment.setCloseStatus(PayStatusEnum.pending.getCode());
+                } else {
+                    orderPayment.setCloseStatus(PayStatusEnum.failed.getCode());
+                    orderPayment.setCloseFailMsg(closeRes.getFailMsg());
+                }
+
                 //更新付款单
                 orderPayment.setStatus(PayStatusEnum.failed.getCode());
-                orderPayment.setPayFailMsg("交易取消");
+                orderPayment.setPayFailMsg(message);
+                orderPayment.setUpdateTime(new Date());
                 userOrderPaymentService.saveOrUpdate(orderPayment);
             }
         }
@@ -459,7 +474,13 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             orderPayRes.setMessage("订单不存在");
             return orderPayRes;
         }
-        UserOrderPayment userOrderPayment = userOrderPaymentService.getByOrderNo(detail.getOrderSn());
+        if (detail.getStatus() != 0 && detail.getStatus() != 6) {
+            orderPayRes.setStatus(false);
+            orderPayRes.setMessage("订单已付款或已关闭");
+            return orderPayRes;
+        }
+        UserOrderPayment userOrderPayment = userOrderPaymentService
+                .getByOrderNo(detail.getOrderSn(), payReq.getPayChannel(), PayStatusEnum.pending);
         payReq.orderStatus(detail.getStatus());
         payReq.setOrderNo(detail.getOrderSn());
         payReq.setOrderPrice(detail.getPayAmount());
@@ -471,13 +492,14 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         // 支付中的返回拉起信息
         orderPayRes = adapayPaymentService.orderPay(payReq);
         if (!orderPayRes.isStatus()) {
-            if (orderPayRes.getPayStatus() != null
-            && PayStatusEnum.failed.getCode().equals(orderPayRes.getPayStatus().getCode())) {
-                // 异常将取消订单
-                cancelOrder(detail.getId());
-            }
+            // 异常将取消订单
+            cancelOrder(detail.getId(),orderPayRes.getMessage());
             throw new BizException(orderPayRes.getMessage());
         }
+        if (!orderPayRes.getPay_amt().equals(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString())) {
+            cancelOrder(detail.getId(),"订单金额和实际支付金额不符");
+            throw new BizException("订单金额和实际支付金额不符");
+        }
         // 订单状态和付款状态都是付款中,直接返回付款拉起信息
         if (OrderStatusEnum.PAYING.getCode().equals(payReq.getOrderStatus().getCode())
                 && PayStatusEnum.pending.getCode().equals(orderPayRes.getPayStatus().getCode())) {
@@ -488,7 +510,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         OmsOrder omsOrder = new OmsOrder();
         omsOrder.setId(detail.getId());
         if (orderPayRes.getPayStatus().getCode().equals(OrderStatusEnum.PAYING.getCode())) {
-            omsOrder.setStatus(1);
+            omsOrder.setStatus(0);
             orderMapper.updateByPrimaryKeySelective(omsOrder);
             // 保存订单支付表
             if (userOrderPayment == null) {
@@ -506,29 +528,104 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             userOrderPaymentService.saveOrUpdate(userOrderPayment);
         }else {
             // 异常将取消订单
-            cancelOrder(detail.getId());
+            cancelOrder(detail.getId(), orderPayRes.getMessage());
         }
 
         return orderPayRes;
     }
 
     @Override
-    public void orderCallback(String data) {
+    public void orderCallback(String data, String type) {
         JSONObject hfRes = JSONObject.parseObject(data);
-        if (PayStatusEnum.succeeded.getCode().equals(hfRes.getString("status"))) {
-            //订单完成
-            OmsOrderDetail orderDetail = detail(hfRes.getString("order_no"));
-            if (null == orderDetail) {
-                log.error("汇付支付回调,订单未找到。 req is {}", data);
-                return;
-            }
-            if (orderDetail.getStatus() == 0) {
-                orderSuccess(orderDetail, hfRes);
-            } else {
-                log.error("汇付支付回调,订单状态异常。 req is {}", data);
-            }
+
+        if (type.equals("payment.succeeded")) {//支付成功
+            paymentSucceededHandle(hfRes);
+        } else if (type.equals("payment.failed")) {//支付失败
+            paymentFailedHandle(hfRes);
+        } else if (type.equals("payment.close.succeeded")) {//支付关单成功
+            paymentCloseSucceededHandle(hfRes);
+        } else if (type.equals("payment.close.failed")) {//支付关单失败
+            paymentCloseFailedHandle(hfRes);
+        }
+    }
+
+
+
+    /***
+     * 处理回调-支付成功
+     * @author liweifan
+     * @param: hfRes
+     * @updateTime 2022/4/27 15:09
+     */
+    private void paymentSucceededHandle(JSONObject hfRes) {
+        //订单完成
+        OmsOrder detail = detail(hfRes.getString("order_no"));
+        if (null == detail) {
+            log.error("汇付支付回调,订单未找到。 req is {}", hfRes.toJSONString());
+            return;
+        }
+        if (detail.getStatus() == 0) {
+            orderSuccess(detail, hfRes);
+        } else {
+            log.error("汇付支付回调,订单状态异常。 req is {}", hfRes.toJSONString());
+        }
+    }
+
+    /***
+     * 处理回调-支付失败
+     * @author liweifan
+     * @param: hfRes
+     * @updateTime 2022/4/27 15:09
+     */
+    private void paymentFailedHandle(JSONObject hfRes) {
+        //订单完成
+        OmsOrder detail = detail(hfRes.getString("order_no"));
+
+        if (null == detail) {
+            log.error("汇付支付回调,订单未找到。 req is {}", hfRes.toJSONString());
+            return;
+        }
+        if (detail.getStatus() == 0) {
+
+            cancelOrder(detail.getId(), "支付回调失败");
+        } else {
+            log.error("汇付支付回调,订单状态异常。 req is {}", hfRes.toJSONString());
         }
     }
+
+    /***
+     * 支付关单成功
+     * @author liweifan
+     * @param: hfRes
+     * @updateTime 2022/4/27 15:33
+     */
+    private void paymentCloseSucceededHandle(JSONObject hfRes) {
+        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(hfRes.getString("payment_id"));
+        if (null == orderPayment) {
+            return;
+        }
+        orderPayment.setStatus(PayStatusEnum.succeeded.getCode());
+        orderPayment.setUpdateTime(new Date());
+        userOrderPaymentService.saveOrUpdate(orderPayment);
+    }
+
+    /***
+     * 支付关单失败
+     * @author liweifan
+     * @param: hfRes
+     * @updateTime 2022/4/27 15:33
+     */
+    private void paymentCloseFailedHandle(JSONObject hfRes) {
+        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(hfRes.getString("payment_id"));
+        if (null == orderPayment) {
+            return;
+        }
+        orderPayment.setStatus(PayStatusEnum.failed.getCode());
+        orderPayment.setPayFailMsg("支付关单回调失败-" + hfRes.getString("error_msg"));
+        orderPayment.setUpdateTime(new Date());
+        userOrderPaymentService.saveOrUpdate(orderPayment);
+    }
+
     /***
      * 处理支付中订单
      * @author liweifan
@@ -538,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;
         }
@@ -546,11 +643,12 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             Map<String, Object> resMap = paymentSdk.queryPayment(orderPayment.getTransNo());
             //支付失败
             if (PayStatusEnum.failed.getCode().equals(resMap.get("status").toString())) {
-                cancelOrder(userOrder.getId());
-            }
-            //支付成功
-            if (PayStatusEnum.succeeded.getCode().equals(resMap.get("status").toString())) {
+                cancelOrder(userOrder.getId(), "支付失败");
+            }else if (PayStatusEnum.succeeded.getCode().equals(resMap.get("status").toString())) {
+                // 支付成功
                 orderSuccess(userOrder,null);
+            } else {
+                cancelOrder(userOrder.getId(), "支付超时");
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -568,17 +666,21 @@ 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")) {
             paySuccess(detail.getId(),2);
         }
+        String pay_amt = hfRes.getString("pay_amt");
+        if (!pay_amt.equals(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString())) {
+            orderPayment.setPayFailMsg("订单金额和实际支付金额不符");
+        }
         orderPayment.setStatus(PayStatusEnum.succeeded.getCode());
         orderPayment.setArrivalTime(new Date());
         if (null != hfRes) {
             try {
-                orderPayment.setPayAmt(new BigDecimal(hfRes.getString("pay_amt")));
+                orderPayment.setPayAmt(new BigDecimal(pay_amt));
                 orderPayment.setFeeAmt(new BigDecimal(hfRes.getString("fee_amt")));
             } catch (Exception e) {
                 e.printStackTrace();

+ 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 = "dateTime", dataType = "String", value = "如果查询年数据 yyyy   如果查询月数据 yyyy-mm"),
+            @ApiImplicitParam(name = "timeType", dataType = "String", value = " 时间类型 MONTH月度  YEAR年度"),
+            @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));
+    }
+
 }

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

@@ -146,7 +146,7 @@ public class MusicSheetController extends BaseController {
         if (sysUser == null  || sysUser.getId() == null) {
             return failed("用户信息获取失败");
         }
-
+        query.setAuditStatus(AuthStatusEnum.PASS);
         IPage<MusicSheetVo> musicSheetVoIPage = musicSheetService.selectPage(PageUtil.getPage(query), query);
         return succeed(PageUtil.pageInfo(musicSheetVoIPage));
     }

+ 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);
 }

+ 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_")

+ 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);
         }
     }
 

+ 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;

+ 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
@@ -34,4 +37,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> - dateTime  如果查询年数据 yyyy   如果查询月数据 yyyy-mm
+     *              <p> - type 类型  PRACTICE陪练课  LIVE直播课
+     *              <p> - timeType 时间类型 MONTH、月度 YEAR
+     */
+    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);

+ 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 - 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());
             }
-
         }
-
-
     }
 
     /**

+ 98 - 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,89 @@ public class HomeServiceImpl implements HomeService {
         total.setInfoList(totalList);
         return HttpResponseResult.succeed(total);
     }
+
+    /**
+     * 获取首页课程数据
+     * <p>未完成  未开始&进行中
+     * <p>已完成  已完成课程
+     *
+     * @param param 传入参数
+     *              <p> - dateTime  如果查询年数据 yyyy   如果查询月数据 yyyy-mm
+     *              <p> - type 类型  PRACTICE陪练课  LIVE直播课
+     *              <p> - timeType 时间类型 MONTH、月度 YEAR
+     */
+    public CourseHomeVo queryCourseHomeData(Map<String, Object> param) {
+        CourseScheduleEnum.existCourseType(WrapperUtil.toStr(param, "type"), "课程类型参数错误");
+        String dateTimeStr = WrapperUtil.toStr(param, "dateTime", "查询时间不能为空!");
+        String timeType = WrapperUtil.toStr(param, "timeType", "查询时间不类型不能为空!");
+        //按年查询true  按月查询false
+        boolean isYear = timeType.equals("YEAR");
+        //获取年
+        String[] split = dateTimeStr.split("-");
+        int year = Integer.parseInt(split[0]);
+        //获取月
+        int month = isYear ? 1 : Integer.parseInt(split[1]);;
+        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

+ 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
+    }
+
 }
 

+ 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);
+    }
 }

+ 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;
+    }
+}

+ 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>

+ 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());

+ 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();
+    }
+
     /**
      * 同步融云用户状态变更
      *

+ 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);
+    }
+}