Revert "feat: 东区缴费分支初始化"

This reverts commit 90c60a4910.
This commit is contained in:
2025-05-15 18:15:36 +08:00
parent 90c60a4910
commit e6ab06b994
1198 changed files with 72566 additions and 3763 deletions
@@ -0,0 +1,69 @@
package com.yida.data.device.consume.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.consume.EduConsumeDevice;
import com.yida.data.device.consume.service.EduConsumeDeviceService;
import com.yida.data.device.vo.consume.ConsumeDeviceVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 消费机设备Controller
*
* @author ZYJ
* @date 2023-03-14 18:02:27
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("consumeDevice")
@Api(tags = "消费机设备后台api")
public class EduConsumeDeviceController {
private final EduConsumeDeviceService eduConsumeDeviceService;
@ApiOperation("消费机设备列表分页查询")
@GetMapping("/listDevicePage")
public ResultBean<Page<ConsumeDeviceVO>> listDevicePage(
@ApiParam("设备编号或名称") String number,
@ApiParam("设备状态,0-在线,1-离线") Integer state,
@ApiParam("学校id") Long schoolId,
@ApiParam("当前页码") @RequestParam(defaultValue = "1") Integer pageNum,
@ApiParam("页面大小") @RequestParam(defaultValue = "10") Integer pageSize) {
return ResultBean.buildSuccess(eduConsumeDeviceService.listDevicePage(pageNum, pageSize, number, state, schoolId));
}
@ApiOperation("保存消费机设备")
@PostMapping("/saveConsumeDevice")
public ResultBean<String> saveDevice(@RequestBody EduConsumeDevice device) {
eduConsumeDeviceService.saveDevice(device);
return ResultBean.buildSuccess();
}
@ApiOperation("获取设备详情")
@GetMapping("/getDeviceInfo")
public ResultBean<ConsumeDeviceVO> getDeviceInfo(@RequestParam Long deviceId) {
EduConsumeDevice consumeDevice = eduConsumeDeviceService.getById(deviceId);
ConsumeDeviceVO deviceVO = new ConsumeDeviceVO();
if (Objects.nonNull(consumeDevice)) {
BeanUtils.copyProperties(consumeDevice, deviceVO);
}
return ResultBean.buildSuccess(deviceVO);
}
@ApiOperation("批量删除消费机设备")
@PostMapping("/deleteDeviceBatch")
public ResultBean<String> deleteDeviceBatch(@RequestBody List<Long> ids) {
eduConsumeDeviceService.removeByIds(ids);
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,46 @@
package com.yida.data.device.consume.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.device.consume.service.EduConsumeOrderService;
import com.yida.data.device.dto.consume.ConsumeOrderPageDTO;
import com.yida.data.device.vo.consume.ConsumeOrderPageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 消费订单 Controller
*
* @author ZYJ
* @date 2023/4/14
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/consumeOrder")
@Api(tags = "消费订单api")
public class EduConsumeOrderController {
private final EduConsumeOrderService eduConsumeOrderService;
@ApiOperation("消费订单列表分页查询")
@GetMapping("/listConsumeOrderPage")
public ResultBean<Page<ConsumeOrderPageVO>> listConsumeOrderPage(ConsumeOrderPageDTO dto) {
return ResultBean.buildSuccess(eduConsumeOrderService.listConsumeOrderPage(dto));
}
@GetMapping(value = "refundOrder")
@ApiOperation(value = "消费订单退款")
public ResultBean<String> refundOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
eduConsumeOrderService.refundOrder(orderCode);
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,36 @@
package com.yida.data.device.consume.controller;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.consume.EduStudentConsumeCard;
import com.yida.data.device.consume.service.EduStudentConsumeCardService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 学生消费机信息管理Controller
*
* @author ZYJ
* @date 2023-03-14 18:02:27
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("consumeCard")
@Api(tags = "学生消费机信息管理api")
public class EduStudentConsumeCardController {
private final EduStudentConsumeCardService eduStudentConsumeCardService;
@ApiOperation("保存学生消费机信息")
@PostMapping("/saveConsumeCard")
public ResultBean<String> saveConsumeCard(@RequestBody EduStudentConsumeCard eduStudentConsumeCard) {
eduStudentConsumeCardService.saveConsumeCard(eduStudentConsumeCard);
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,107 @@
package com.yida.data.device.consume.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.device.consume.service.H5ConsumeService;
import com.yida.data.device.dto.consume.CreateConsumeOrderDTO;
import com.yida.data.device.dto.consume.H5ConsumeOrderPageDTO;
import com.yida.data.device.dto.consume.H5ConsumeRecordPageDTO;
import com.yida.data.device.vo.consume.ConsumePayInfoVO;
import com.yida.data.device.vo.consume.ConsumeVipVO;
import com.yida.data.device.vo.consume.H5ConsumeOrderPageVO;
import com.yida.data.device.vo.consume.H5ConsumeRecordPageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* 消费机前端controller
*
* @author ZYJ
* @date 2023/3/16
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("h5/consume")
@Api(tags = "消费机前端api")
public class H5ConsumeController {
private final H5ConsumeService h5ConsumeService;
@GetMapping("/checkVip")
@ApiOperation("查询学生消费机会员状态")
public ResultBean<ConsumeVipVO> checkVip(
@ApiParam(value = "学生id", required = true) @RequestParam Long studentId,
@ApiParam(value = "学校id", required = true) @RequestParam Long schoolId) {
return ResultBean.buildSuccess(h5ConsumeService.checkVip(studentId, schoolId));
}
@GetMapping("/reportLoss")
@ApiOperation("挂失")
public ResultBean<String> reportLoss(@ApiParam(value = "学生id", required = true) @RequestParam Long studentId) {
return ResultBean.buildSuccess(h5ConsumeService.reportLoss(studentId));
}
@GetMapping("/unfreeze")
@ApiOperation("解冻")
public ResultBean<String> unfreeze(@ApiParam(value = "学生id", required = true) @RequestParam Long studentId) {
return ResultBean.buildSuccess(h5ConsumeService.unfreeze(studentId));
}
@PostMapping("/createConsumeOrder")
@ApiOperation("生成消费订单(充值)")
public ResultBean<ConsumePayInfoVO> createConsumeOrder(@RequestBody CreateConsumeOrderDTO dto) {
return ResultBean.buildSuccess(h5ConsumeService.createConsumeOrder(dto));
}
@GetMapping("/consumeOrderSuccess")
@ApiOperation("消费订单完成(前台支付成功后调用)")
public ResultBean<String> consumeOrderSuccess(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
h5ConsumeService.consumeOrderSuccess(orderCode);
return ResultBean.buildSuccess();
}
@PostMapping(value = "listH5ConsumeOrderPage")
@ApiOperation(value = "前端查询消费订单列表数据(充值记录)")
public ResultBean<IPage<H5ConsumeOrderPageVO>> listH5ConsumeOrderPage(@RequestBody H5ConsumeOrderPageDTO dto) {
IPage<H5ConsumeOrderPageVO> page = h5ConsumeService.listH5ConsumeOrderPage(dto);
return ResultBean.buildSuccess(page);
}
@GetMapping(value = "getH5ConsumeOrderInfo")
@ApiOperation(value = "前端查询消费订单详情(充值记录)")
public ResultBean<H5ConsumeOrderPageVO> getH5ConsumeOrderInfo(
@ApiParam(value = "订单id") @RequestParam(required = false) Long orderId,
@ApiParam(value = "订单号") @RequestParam(required = false) String orderCode) {
return ResultBean.buildSuccess(h5ConsumeService.getH5ConsumeOrderInfo(orderId, orderCode));
}
@GetMapping("continuePayOrder")
@ApiOperation("继续支付")
public ResultBean<ConsumePayInfoVO> continuePayOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode,
@ApiParam(value = "学校id", required = true) @RequestParam Long deptId) {
ConsumePayInfoVO infoVO = h5ConsumeService.continuePayOrder(orderCode, deptId);
return ResultBean.buildSuccess(infoVO);
}
@GetMapping(value = "cancelOrder")
@ApiOperation(value = "取消订单")
public ResultBean<String> cancelOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
h5ConsumeService.cancelOrder(orderCode);
return ResultBean.buildSuccess();
}
@PostMapping(value = "listH5ConsumeRecordPage")
@ApiOperation(value = "前端查询学生消费记录列表")
public ResultBean<IPage<H5ConsumeRecordPageVO>> listH5ConsumeRecordPage(@RequestBody H5ConsumeRecordPageDTO dto) {
IPage<H5ConsumeRecordPageVO> page = h5ConsumeService.listH5ConsumeRecordPage(dto);
return ResultBean.buildSuccess(page);
}
}
@@ -0,0 +1,80 @@
package com.yida.data.device.consume.controller;
import cn.hutool.json.JSONUtil;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.FebsResponse;
import com.yida.data.device.consume.service.EduConsumeOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Map;
/**
* 消费订单 Controller(不鉴权)
*
* @author ZYJ
* @date 2023/3/23
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("in/consume")
@Api(tags = "消费订单api")
public class InEduConsumeOrderController {
private final EduConsumeOrderService eduConsumeOrderService;
@ApiOperation("微信支付通知结果回调 此接口暂时无用(需手动查询订单支付状态)")
@PostMapping("/wxPayNotify")
public FebsResponse wxPayNotify(@RequestBody Map<String, Object> res) {
return new FebsResponse().put("code", "SUCCESS");
}
@ApiOperation("微信退款通知结果回调 此接口暂时无用(需手动查询订单退款状态)")
@PostMapping("/wxRefundNotify")
public FebsResponse wxRefundNotify(@RequestBody Map<String, Object> res) {
return new FebsResponse().put("code", "SUCCESS");
}
@ApiOperation("银联支付通知结果回调")
@PostMapping("/unionPayNotify")
public String unionPayNotify(@RequestParam Map<String, Object> map) {
log.info("银联支付通知结果回调, result: {}", JSONUtil.toJsonStr(map));
return null;
// return eduConsumeOrderService.unionPayNotify(map);
}
@ApiOperation("收钱吧支付通知结果回调")
@PostMapping("/uPayNotify")
public String uPayNotify(HttpServletRequest request) throws IOException {
BufferedReader bufferReader = new BufferedReader(request.getReader());
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferReader.readLine()) != null) {
sb.append(line);
}
log.info("收钱吧支付通知结果回调, result: {}", sb.toString());
log.info("收钱吧支付通知结果回调签名, sign: {}", request.getHeader("Authorization"));
return eduConsumeOrderService.uPayNotify(sb.toString(), request);
}
@GetMapping(value = "updateOrderStatus")
@ApiOperation(value = "更新超时订单状态")
public ResultBean<String> updateOrderStatus() {
eduConsumeOrderService.updateOrderStatus();
return ResultBean.buildSuccess();
}
@GetMapping(value = "updateRefundStatus")
@ApiOperation(value = "更新退款订单状态")
public ResultBean<String> updateRefundStatus() {
eduConsumeOrderService.updateRefundStatus();
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,35 @@
package com.yida.data.device.consume.controller.out;
import com.yida.data.common.core.entity.FebsResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 消费机 Controller(不鉴权)
*
* @author ZYJ
* @date 2023/3/10
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("out/consume")
@Api(tags = "消费机api")
public class OutConsumeController {
@ApiOperation("海普天消费结果通知")
@PostMapping("/consumeNotify")
public FebsResponse consumeNotify(@RequestBody Map<String, Object> res) {
log.info("结果信息: {}", res);
return new FebsResponse().put("code", "SUCCESS");
}
}
@@ -0,0 +1,21 @@
package com.yida.data.device.consume.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.entity.consume.EduConsumeDevice;
import com.yida.data.device.vo.consume.ConsumeDeviceVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 消费机设备Mapper
*
* @author ZYJ
* @date 2023-03-14 18:02:27
*/
public interface EduConsumeDeviceMapper extends BaseMapper<EduConsumeDevice> {
Page<ConsumeDeviceVO> listDevicePage(Page page, @Param("schoolIds")List<Long> schoolIds,
@Param("number") String number, @Param("state") Integer state);
}
@@ -0,0 +1,80 @@
package com.yida.data.device.consume.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.entity.consume.EduConsumeOrder;
import com.yida.data.device.dto.consume.ConsumeOrderPageDTO;
import com.yida.data.device.dto.consume.H5ConsumeOrderPageDTO;
import com.yida.data.device.vo.consume.ConsumeOrderPageVO;
import com.yida.data.device.vo.consume.ConsumeRefundOrderVO;
import com.yida.data.device.vo.consume.H5ConsumeOrderPageVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 消费订单(充值记录)Mapper
*
* @author ZYJ
* @date 2023/3/23
*/
public interface EduConsumeOrderMapper extends BaseMapper<EduConsumeOrder> {
/**
* 前端查询账单订单列表数据
* 未支付、成功、退款中
*
* @param page 分页数据
* @param dto 消费订单列表请求类(充值记录)
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.device.vo.consume.H5ConsumeOrderPageVO>
* @author ZYJ
* @date 2023/3/24 14:29
*/
IPage<H5ConsumeOrderPageVO> listH5ConsumeOrderPage(Page<EduConsumeOrder> page,
@Param("dto") H5ConsumeOrderPageDTO dto);
/**
* 前端查询消费订单详情(充值记录)
*
* @param orderId 订单id
* @param orderCode 订单号
* @return com.yida.data.device.vo.consume.H5ConsumeOrderPageVO
* @author ZYJ
* @date 2023/3/24 14:45
*/
H5ConsumeOrderPageVO getH5ConsumeOrderInfo(@Param("orderId") Long orderId, @Param("orderCode") String orderCode);
/**
* 查询所有已经超时订单
* 未支付状态
*
* @return java.util.List<com.yida.data.common.core.entity.consume.EduConsumeOrder>
* @author ZYJ
* @date 2023/4/3 13:31
*/
List<EduConsumeOrder> selectTimeOutConsumeOrder();
/**
* 查询退款中状态的消费订单
*
* @return java.util.List<com.yida.data.device.vo.consume.ConsumeRefundOrderVO>
* @author ZYJ
* @date 2023/4/3 16:07
*/
List<ConsumeRefundOrderVO> selectRefundOrder();
/**
* 消费订单后台列表分页查询
*
* @param page 分页信息
* @param schoolIds 学校id集合
* @param dto 消费订单后台列表请求类
* @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.yida.data.device.vo.consume.ConsumeOrderPageVO>
* @author ZYJ
* @date 2023/4/14 17:09
*/
Page<ConsumeOrderPageVO> listConsumeOrderPage(Page page,
@Param("schoolIds") List<Long> schoolIds,
@Param("dto") ConsumeOrderPageDTO dto);
}
@@ -0,0 +1,14 @@
package com.yida.data.device.consume.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.consume.EduConsumeOrderRefund;
/**
* 消费订单退款信息Mapper
*
* @author ZYJ
* @date 2023-04-03 16:12:35
*/
public interface EduConsumeOrderRefundMapper extends BaseMapper<EduConsumeOrderRefund> {
}
@@ -0,0 +1,14 @@
package com.yida.data.device.consume.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.consume.EduConsumeOrderStudent;
/**
* 消费订单(充值)学生详细信息Mapper
*
* @author ZYJ
* @date 2023/3/23
*/
public interface EduConsumeOrderStudentMapper extends BaseMapper<EduConsumeOrderStudent> {
}
@@ -0,0 +1,30 @@
package com.yida.data.device.consume.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.entity.consume.EduConsumeRecord;
import com.yida.data.device.dto.consume.H5ConsumeRecordPageDTO;
import com.yida.data.device.vo.consume.H5ConsumeRecordPageVO;
import org.apache.ibatis.annotations.Param;
/**
* 消费机学生消费记录Mapper
*
* @author ZYJ
* @date 2023-03-24 16:16:49
*/
public interface EduConsumeRecordMapper extends BaseMapper<EduConsumeRecord> {
/**
* 前端查询学生消费记录列表
*
* @param page 分页信息
* @param dto 消费机学生消费记录列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.device.vo.consume.H5ConsumeRecordPageVO>
* @author ZYJ
* @date 2023/3/24 17:18
*/
IPage<H5ConsumeRecordPageVO> listH5ConsumeRecordPage(Page<EduConsumeRecord> page,
@Param("dto") H5ConsumeRecordPageDTO dto);
}
@@ -0,0 +1,14 @@
package com.yida.data.device.consume.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.consume.EduStudentConsumeCard;
/**
* 学生消费机信息管理Mapper
*
* @author ZYJ
* @date 2023-03-20 15:02:20
*/
public interface EduStudentConsumeCardMapper extends BaseMapper<EduStudentConsumeCard> {
}
@@ -0,0 +1,38 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.consume.EduConsumeDevice;
import com.yida.data.device.vo.consume.ConsumeDeviceVO;
/**
* 消费机设备Service接口
*
* @author ZYJ
* @date 2023-03-14 18:02:27
*/
public interface EduConsumeDeviceService extends IService<EduConsumeDevice> {
/**
* 消费机设备列表分页查询
*
* @param pageNum 页码
* @param pageSize 每页数量
* @param number 设备编号或名称
* @param state 设备状态,0-在线,1-离线
* @param schoolId 学校id
* @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.yida.data.device.vo.consume.ConsumeDeviceVO>
* @author ZYJ
* @date 2023/3/15 10:14
*/
Page<ConsumeDeviceVO> listDevicePage(Integer pageNum, Integer pageSize, String number, Integer state, Long schoolId);
/**
* 保存消费机设备
*
* @param device 消费机设备信息
* @author ZYJ
* @date 2023/3/15 10:43
*/
void saveDevice(EduConsumeDevice device);
}
@@ -0,0 +1,13 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.consume.EduConsumeOrderRefund;
/**
* 消费订单退款信息Service接口
*
* @author ZYJ
* @date 2023-04-03 16:12:35
*/
public interface EduConsumeOrderRefundService extends IService<EduConsumeOrderRefund> {
}
@@ -0,0 +1,65 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.consume.EduConsumeOrder;
import com.yida.data.device.dto.consume.ConsumeOrderPageDTO;
import com.yida.data.device.vo.consume.ConsumeOrderPageVO;
import javax.servlet.http.HttpServletRequest;
/**
* 消费订单(充值记录)Service接口
*
* @author ZYJ
* @date 2023/3/23
*/
public interface EduConsumeOrderService extends IService<EduConsumeOrder> {
/**
* 收钱吧支付通知结果回调
*
* @param result 回调值
* @param request 请求信息
* @return java.lang.String
* @author ZYJ
* @date 2023/3/23 16:13
*/
String uPayNotify(String result, HttpServletRequest request);
/**
* 更新超时订单状态
*
* @author ZYJ
* @date 2023/4/3 13:26
*/
void updateOrderStatus();
/**
* 更新退款订单状态
*
* @author ZYJ
* @date 2023/4/3 13:26
*/
void updateRefundStatus();
/**
* 消费订单列表分页查询
*
* @param dto 消费订单后台列表请求类
* @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.yida.data.device.vo.consume.ConsumeOrderPageVO>
* @author ZYJ
* @date 2023/4/14 16:48
*/
Page<ConsumeOrderPageVO> listConsumeOrderPage(ConsumeOrderPageDTO dto);
/**
* 消费订单退款
*
* @param orderCode 订单号
* @author ZYJ
* @date 2023/4/15 15:37
*/
void refundOrder(String orderCode);
}
@@ -0,0 +1,14 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.consume.EduConsumeOrderStudent;
/**
* 消费订单(充值)学生详细信息Service接口
*
* @author ZYJ
* @date 2023-03-23 14:03:58
*/
public interface EduConsumeOrderStudentService extends IService<EduConsumeOrderStudent> {
}
@@ -0,0 +1,14 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.consume.EduConsumeRecord;
/**
* 消费机学生消费记录Service接口
*
* @author ZYJ
* @date 2023-03-24 16:16:49
*/
public interface EduConsumeRecordService extends IService<EduConsumeRecord> {
}
@@ -0,0 +1,22 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.consume.EduStudentConsumeCard;
/**
* 学生消费机信息管理Service接口
*
* @author ZYJ
* @date 2023-03-20 15:02:20
*/
public interface EduStudentConsumeCardService extends IService<EduStudentConsumeCard> {
/**
* 保存学生消费机信息
*
* @param eduStudentConsumeCard 学生消费机信息
* @author ZYJ
* @date 2023/3/20 15:54
*/
void saveConsumeCard(EduStudentConsumeCard eduStudentConsumeCard);
}
@@ -0,0 +1,132 @@
package com.yida.data.device.consume.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.device.dto.consume.CreateConsumeOrderDTO;
import com.yida.data.device.dto.consume.H5ConsumeOrderPageDTO;
import com.yida.data.device.dto.consume.H5ConsumeRecordPageDTO;
import com.yida.data.device.vo.consume.ConsumePayInfoVO;
import com.yida.data.device.vo.consume.ConsumeVipVO;
import com.yida.data.device.vo.consume.H5ConsumeOrderPageVO;
import com.yida.data.device.vo.consume.H5ConsumeRecordPageVO;
import java.time.LocalDateTime;
/**
* 消费机前端service
*
* @author ZYJ
* @date 2023/3/16
*/
public interface H5ConsumeService {
/**
* 查询学生消费机会员状态
*
* @param studentId 学生id
* @param schoolId 学校id
* @return com.yida.data.device.vo.consume.ConsumeVipVO
* @author ZYJ
* @date 2023/3/16 15:52
*/
ConsumeVipVO checkVip(Long studentId, Long schoolId);
/**
* 挂失
*
* @param studentId 学生id
* @return java.lang.String
* @author ZYJ
* @date 2023/3/30 9:38
*/
String reportLoss(Long studentId);
/**
* 解冻
*
* @param studentId 学生id
* @return java.lang.String
* @author ZYJ
* @date 2023/3/30 9:39
*/
String unfreeze(Long studentId);
/**
* 生成消费订单(充值)
*
* @param dto 生成消费订单请求类
* @return com.yida.data.device.vo.consume.ConsumePayInfoVO
* @author ZYJ
* @date 2023/3/22 16:37
*/
ConsumePayInfoVO createConsumeOrder(CreateConsumeOrderDTO dto);
/**
* 消费订单完成(前台支付成功后调用)
*
* @param orderCode 订单号
* @author ZYJ
* @date 2023/3/23 16:43
*/
void consumeOrderSuccess(String orderCode);
/**
* 消费订单支付成功
*
* @param orderCode 订单号
* @param payDate 支付完成时间
* @author ZYJ
* @date 2023/3/23 17:06
*/
void consumeOrderPaySuccess(String orderCode, LocalDateTime payDate);
/**
* 前端查询消费订单列表数据(充值记录)
*
* @param dto 消费订单列表请求类(充值记录)
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.device.vo.consume.H5ConsumeOrderPageVO>
* @author ZYJ
* @date 2023/3/24 14:26
*/
IPage<H5ConsumeOrderPageVO> listH5ConsumeOrderPage(H5ConsumeOrderPageDTO dto);
/**
* 前端查询消费订单详情(充值记录)
*
* @param orderId 订单id
* @param orderCode 订单号
* @return com.yida.data.device.vo.consume.H5ConsumeOrderPageVO
* @author ZYJ
* @date 2023/3/24 14:43
*/
H5ConsumeOrderPageVO getH5ConsumeOrderInfo(Long orderId, String orderCode);
/**
* 继续支付
*
* @param orderCode 订单号
* @param deptId 学校id
* @return com.yida.data.device.vo.consume.ConsumePayInfoVO
* @author ZYJ
* @date 2023/3/24 14:49
*/
ConsumePayInfoVO continuePayOrder(String orderCode, Long deptId);
/**
* 取消订单
*
* @param orderCode 订单号
* @author ZYJ
* @date 2023/3/30 14:14
*/
void cancelOrder(String orderCode);
/**
* 前端查询学生消费记录列表
*
* @param dto 消费机学生消费记录列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.device.vo.consume.H5ConsumeRecordPageVO>
* @author ZYJ
* @date 2023/3/24 16:55
*/
IPage<H5ConsumeRecordPageVO> listH5ConsumeRecordPage(H5ConsumeRecordPageDTO dto);
}
@@ -0,0 +1,74 @@
package com.yida.data.device.consume.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.consume.EduConsumeDevice;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.enums.SysFunctionEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.device.consume.mapper.EduConsumeDeviceMapper;
import com.yida.data.device.consume.service.EduConsumeDeviceService;
import com.yida.data.device.vo.consume.ConsumeDeviceVO;
import com.yida.data.system.feign.RemoteDeptService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 消费机设备Service实现
*
* @author ZYJ
* @date 2023-03-14 18:02:27
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduConsumeDeviceServiceImpl extends ServiceImpl
<EduConsumeDeviceMapper, EduConsumeDevice> implements EduConsumeDeviceService {
private final RemoteDeptService remoteDeptService;
@Override
public Page<ConsumeDeviceVO> listDevicePage(Integer pageNum, Integer pageSize, String number, Integer state, Long schoolId) {
List<Long> schoolIds = new ArrayList<>();
if (Objects.isNull(schoolId)) {
List<Dept> deptList = remoteDeptService.getSchoolByArea(null, "").getData();
if (CollUtil.isEmpty(deptList)) {
schoolIds.add(-1L);
} else {
schoolIds = deptList.stream().map(Dept::getDeptId).collect(Collectors.toList());
}
} else {
schoolIds.add(schoolId);
}
Page<ConsumeDeviceVO> devicePage = baseMapper.listDevicePage(new Page<>(pageNum, pageSize), schoolIds, number, state);
devicePage.getRecords().forEach(consumeDeviceVO -> consumeDeviceVO.setSchoolName(remoteDeptService.getInfoById(consumeDeviceVO.getSchoolId()).getData().getDeptName()));
return devicePage;
}
@Override
public void saveDevice(EduConsumeDevice device) {
// 查询设备号是否重复
EduConsumeDevice eduConsumeDevice = getOne(Wrappers.lambdaQuery(new EduConsumeDevice())
.eq(EduConsumeDevice::getSn, device.getSn())
.ne(Objects.nonNull(device.getId()), EduConsumeDevice::getId, device.getId())
);
if (Objects.nonNull(eduConsumeDevice)) {
throw new FebsException("该设备号已存在,请勿重复添加");
}
if (Objects.isNull(device.getId())) {
device.setDeviceType(SysFunctionEnum.HAI_PU_TIAN.getValue());
}
saveOrUpdate(device);
}
}
@@ -0,0 +1,26 @@
package com.yida.data.device.consume.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.consume.EduConsumeOrderRefund;
import com.yida.data.device.consume.mapper.EduConsumeOrderRefundMapper;
import com.yida.data.device.consume.service.EduConsumeOrderRefundService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 消费订单退款信息Service实现
*
* @author ZYJ
* @date 2023-04-03 16:12:35
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduConsumeOrderRefundServiceImpl extends ServiceImpl
<EduConsumeOrderRefundMapper, EduConsumeOrderRefund> implements EduConsumeOrderRefundService {
}
@@ -0,0 +1,594 @@
package com.yida.data.device.consume.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.constant.UPayConstant;
import com.yida.data.common.core.entity.constant.UnionPayConstant;
import com.yida.data.common.core.entity.constant.WxPayConstant;
import com.yida.data.common.core.entity.consume.DeptConsumeTerminalCache;
import com.yida.data.common.core.entity.consume.EduConsumeOrder;
import com.yida.data.common.core.entity.consume.EduConsumeOrderRefund;
import com.yida.data.common.core.entity.pay.URefund;
import com.yida.data.common.core.entity.pay.UnionRefund;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduPayWxConfig;
import com.yida.data.common.core.entity.system.UPayConfig;
import com.yida.data.common.core.entity.system.UnionPayConfig;
import com.yida.data.common.core.enums.*;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.*;
import com.yida.data.common.service.CommonService;
import com.yida.data.device.consume.mapper.EduConsumeOrderMapper;
import com.yida.data.device.consume.service.EduConsumeOrderRefundService;
import com.yida.data.device.consume.service.EduConsumeOrderService;
import com.yida.data.device.consume.service.H5ConsumeService;
import com.yida.data.device.dto.consume.ConsumeOrderPageDTO;
import com.yida.data.device.vo.consume.ConsumeOrderPageVO;
import com.yida.data.device.vo.consume.ConsumeRefundOrderVO;
import com.yida.data.system.feign.RemoteDeptService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 消费订单(充值记录)Service实现
*
* @author ZYJ
* @date 2023/3/23
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduConsumeOrderServiceImpl extends ServiceImpl
<EduConsumeOrderMapper, EduConsumeOrder> implements EduConsumeOrderService {
private final EduConsumeOrderRefundService eduConsumeOrderRefundService;
@Lazy
@Resource
private H5ConsumeService h5ConsumeService;
private final RemoteDeptService remoteDeptService;
private final CommonService commonService;
private final UnionPayPublicUtil unionPayPublicUtil;
private static final String CONSUME_WX_REFUND_NOTIFY_URL = "mall/in/consume/wxRefundNotify";
@Value("${febs.apiUrl}")
private String apiUrl;
@Override
public String uPayNotify(String result, HttpServletRequest request) {
try {
JSONObject map = JSONUtil.parseObj(result);
// 根据订单号查询对应的订单信息
EduConsumeOrder order = getOne(new LambdaQueryWrapper<>(new EduConsumeOrder())
.eq(EduConsumeOrder::getOrderCode, map.get("client_sn")));
if (Objects.isNull(order)) {
log.error("收钱吧支付回调, 未找到订单信息, orderNO: {}", map.get("client_sn"));
return UPayNotifyResultEnum.FAILED_STATUS.getValue();
}
// 判断支付结果是否处理
if (OrderStatusEnum.PAY_SUCCESS.getStatus().equals(order.getOrderStatus())) {
log.info("收钱吧支付回调, 该订单已经处理: {}", order.getOrderCode());
return UPayNotifyResultEnum.SUCCESS_STATUS.getValue();
}
// 获取收钱吧配置信息
UPayConfig config = commonService.getUPayConfigByDept(order.getDeptId());
if (Objects.isNull(config)) {
log.info("收钱吧支付回调, 该学校没有对应的配置信息: {}", order.getDeptId());
return UPayNotifyResultEnum.FAILED_STATUS.getValue();
}
// 返回的订单状态
String orderStatus = (String) map.get("order_status");
// 新订单和不明确订单直接返回
if (UPayTradeStateEnum.CREATED.getStatus().equals(orderStatus)
|| UPayTradeStateEnum.INVALID_STATUS_CODE.getStatus().equals(orderStatus)) {
log.info("新订单和不明确订单, orderNo: {}", order.getOrderCode());
return UPayNotifyResultEnum.FAILED_STATUS.getValue();
}
// 签名
String signature = request.getHeader("Authorization");
// 验签
boolean checkFlag = UPayUtil.validateSign(result, signature, config.getPublicKey());
if (!checkFlag) {
log.error("收钱吧支付回调, 验签失败");
return UPayNotifyResultEnum.FAILED_STATUS.getValue();
}
// 支付时间
String payTime = (String) map.get("finish_time");
// 修改订单状态
UPayTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UPayTradeStateEnum.class, orderStatus,
UPayTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case PAID:
// h5ConsumeService.consumeOrderPaySuccess(order.getOrderCode(), LocalDateTimeUtil.parse(payTime, DatePattern.NORM_DATETIME_PATTERN));
h5ConsumeService.consumeOrderPaySuccess(order.getOrderCode(), LocalDateTimeUtil.ofUTC(Long.parseLong(payTime)));
break;
// 订单关闭
case CANCELED:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
updateById(order);
break;
default:
break;
}
} catch (Exception e) {
log.error("处理收钱吧支付回调数据失败", e);
return UPayNotifyResultEnum.FAILED_STATUS.getValue();
}
return UPayNotifyResultEnum.SUCCESS_STATUS.getValue();
}
@Override
public void updateOrderStatus() {
// 查询超时订单
List<EduConsumeOrder> list = baseMapper.selectTimeOutConsumeOrder();
if (CollUtil.isNotEmpty(list)) {
for (EduConsumeOrder order : list) {
// 微信订单
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
updateWxOrderStatus(order);
} else if (PayWay.UNION.getValue().equals(order.getPayWay())) {
updateUnionOrderStatus(order);
} else if (PayWay.U_PAY.getValue().equals(order.getPayWay())) {
updateUPayOrderStatus(order);
}
}
}
}
/**
* 更新微信超时消费订单状态
*
* @param order 订单信息
* @author ZYJ
* @date 2023/4/3 13:34
*/
private void updateWxOrderStatus(EduConsumeOrder order) {
try {
// 查询学校微信支付配置信息
EduPayWxConfig config = commonService.getPayWxConfigBySchool(order.getDeptId());
// 主动查询订单支付状态
JSONObject resultJson = JSONUtil.parseObj(WxPayUtil.queryOrder(config, order.getOrderCode()));
log.info("微信消费订单查询返回数据, consumeOrderCode: {}, resultJson: {}", order.getOrderCode(), resultJson);
if (resultJson.containsKey(WxPayConstant.CODE_NAME)
&& WxPayConstant.ORDER_NOT_EXIST.equals(resultJson.getStr(WxPayConstant.CODE_NAME))) {
// 订单不存在 取消订单
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
} else {
String tradeState = resultJson.getStr("trade_state");
// 未支付则关闭订单
if (WxTradeStateEnum.NOT_PAY.getStatus().equals(tradeState)) {
WxPayUtil.closeOrder(config, order.getOrderCode());
}
WxTradeStateEnum wxTradeStateEnum = EnumUtils.valueOf(WxTradeStateEnum.class, tradeState,
WxTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(wxTradeStateEnum)) {
// 支付成功情况
case SUCCESS:
h5ConsumeService.consumeOrderPaySuccess(order.getOrderCode(),
DateUtil.parseLocalDateTime(resultJson.getStr("success_time"),
"yyyy-MM" + "-dd'T" + "'HH:mm" + ":ssXXX"));
break;
// 作废订单
case NOT_PAY:
case CLOSED:
case REVOKED:
case PAY_ERROR:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
break;
default:
break;
}
}
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
baseMapper.updateById(order);
}
} catch (Exception e) {
log.error("更新微信消费订单状态失败, order: {}", order, e);
}
}
/**
* 更新银联超时消费订单状态
*
* @param order 订单信息
* @author ZYJ
* @date 2023/4/3 13:41
*/
private void updateUnionOrderStatus(EduConsumeOrder order) {
try {
// 查询学校银联配置信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(order.getDeptId());
// 主商户信息
UnionPayConfig parentConfig = config.getParentConfig();
// 开发者ID
String appId = Objects.nonNull(parentConfig) ? parentConfig.getAppId() : config.getAppId();
// 开发者key
String appKey = Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : config.getAppKey();
// 主动查询订单支付状态
JSONObject resultJson = UnionPayUtil.queryOrder(config, unionPayPublicUtil.getAccessToken(appId, appKey), order.getOrderCode());
log.info("银联消费订单查询返回数据, consumeOrderCode: {}, resultJson: {}", order.getOrderCode(), resultJson);
// 返回code
String code = (String) resultJson.get(UnionPayConstant.CODE_NAME);
// 无法找到指定的订单 需要直接关闭订单
if (UnionPayConstant.NO_ORDER_CODE.equalsIgnoreCase(code)
|| UnionPayConstant.TARGET_FAIL_CODE.equalsIgnoreCase(code)) {
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
baseMapper.updateById(order);
return;
}
// 支付状态
String status = (String) resultJson.get("status");
// 未支付则关闭订单 (银联云闪付不支付关闭订单)
if (UnionTradeStateEnum.NEW_ORDER.getStatus().equals(status)
&& !UnionPayTypeEnum.UNION_H5_TYPE.getType().equals(order.getPayType())) {
UnionPayUtil.closeOrder(config, unionPayPublicUtil.getAccessToken(appId, appKey), order.getOrderCode());
}
UnionTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UnionTradeStateEnum.class, status,
UnionTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case TRADE_SUCCESS:
h5ConsumeService.consumeOrderPaySuccess(order.getOrderCode(),
LocalDateTimeUtil.parse((String) resultJson.get("payTime"), DatePattern.NORM_DATETIME_PATTERN));
break;
// 作废订单
case NEW_ORDER:
case TRADE_CLOSED:
case WAIT_BUYER_PAY:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
break;
default:
break;
}
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
baseMapper.updateById(order);
}
} catch (Exception e) {
log.error("更新银联消费订单状态失败, order: {}", order, e);
}
}
/**
* 更新收钱吧超时消费订单状态
*
* @param order 订单信息
* @author ZYJ
* @date 2023/4/3 13:48
*/
private void updateUPayOrderStatus(EduConsumeOrder order) {
try {
DeptConsumeTerminalCache terminalCache = commonService.getDeptConsumeTerminal(order.getDeptId());
JSONObject jsonObject = UPayUtil.queryOrder(order.getOrderCode(), terminalCache.getTerminalSn(), terminalCache.getTerminalKey());
log.info("收钱吧消费订单查询返回数据, consumeOrderCode: {}, resultJson: {}", order.getOrderCode(), jsonObject);
JSONObject bizResponse = jsonObject.getJSONObject("biz_response");
// 无法找到指定的订单 需要直接关闭订单
if (UPayConstant.NO_ORDER_CODE.equals(bizResponse.getStr(UPayConstant.ERROR_CODE_NAME))
|| UPayConstant.TRADE_NOT_EXIST.equals(bizResponse.getStr(UPayConstant.ERROR_CODE_NAME))) {
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
baseMapper.updateById(order);
return;
}
JSONObject resultJson = bizResponse.getJSONObject("data");
// 支付状态
String status = (String) resultJson.get("order_status");
// 无法找到指定的订单 需要直接关闭订单
if (UPayTradeStateEnum.CREATED.getStatus().equals(status)
|| UPayTradeStateEnum.INVALID_STATUS_CODE.getStatus().equals(status)) {
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
baseMapper.updateById(order);
return;
}
UPayTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UPayTradeStateEnum.class, status,
UPayTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case PAID:
h5ConsumeService.consumeOrderPaySuccess(order.getOrderCode(), LocalDateTimeUtil.ofUTC(Long.parseLong(resultJson.getStr("finish_time"))));
break;
// 作废订单
case CREATED:
case CANCELED:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
break;
default:
break;
}
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
baseMapper.updateById(order);
}
} catch (Exception e) {
log.error("更新收钱吧消费订单状态失败, order: {}", order, e);
}
}
@Override
public void updateRefundStatus() {
// 查询退款中状态的消费订单
List<ConsumeRefundOrderVO> refundOrderList = baseMapper.selectRefundOrder();
if (CollUtil.isNotEmpty(refundOrderList)) {
refundOrderList.forEach(refundOrderVO -> {
// 微信
if (PayWay.WEI_XIN.getValue().equals(refundOrderVO.getPayWay())) {
updateWxRefundStatus(refundOrderVO);
} else if (PayWay.UNION.getValue().equals(refundOrderVO.getPayWay())) {
updateUnionRefundStatus(refundOrderVO);
} else if (PayWay.U_PAY.getValue().equals(refundOrderVO.getPayWay())) {
updateUPayRefundStatus(refundOrderVO);
}
});
}
}
/**
* 更新微信退款订单状态
*
* @param vo 退款信息
* @author ZYJ
* @date 2023/4/3 16:11
*/
private void updateWxRefundStatus(ConsumeRefundOrderVO vo) {
try {
EduPayWxConfig config = commonService.getPayWxConfigBySchool(vo.getDeptId());
// 主动查询退款状态
JSONObject resultJson = JSONUtil.parseObj(WxPayUtil.queryRefund(config, vo.getRefundCode()));
log.info("账单订单退款查询返回数据, refundOrderCode: {}, resultJson: {}", vo.getRefundCode(), resultJson);
// 状态
String status = resultJson.getStr("status");
WxRefundStatusEnum wxRefundStatusEnum = EnumUtils.valueOf(WxRefundStatusEnum.class, status,
WxRefundStatusEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(wxRefundStatusEnum)) {
case REFUND_SUCCESS:
// 更新订单退款状态
EduConsumeOrder order = getById(vo.getOrderId());
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.REFUND_SUCCESS.getStatus());
order.setIsRefund(RefundStatusEnum.IS_REFUND.getStatus());
baseMapper.updateById(order);
// 更新退款时间
EduConsumeOrderRefund eduBillOrderRefund = eduConsumeOrderRefundService.getById(vo.getRefundId());
eduBillOrderRefund.setRefundTime(DateUtil.parseLocalDateTime(resultJson.getStr("success_time"), "yyyy-MM-dd'T'HH:mm:ssXXX"));
eduConsumeOrderRefundService.updateById(eduBillOrderRefund);
break;
case REFUND_ABNORMAL:
// TODO 2022/6/27 需要后续处理退款失败情况
break;
default:
break;
}
} catch (Exception e) {
log.error("查询微信消费订单退款状态失败, refundOrder: {}", vo, e);
}
}
/**
* 更新银联退款订单状态
*
* @param vo 退款信息
* @author ZYJ
* @date 2023/4/3 16:22
*/
private void updateUnionRefundStatus(ConsumeRefundOrderVO vo) {
try {
// 查询学校银联配置信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(vo.getDeptId());
// 主商户信息
UnionPayConfig parentConfig = config.getParentConfig();
// 开发者ID
String appId = Objects.nonNull(parentConfig) ? parentConfig.getAppId() : config.getAppId();
// 开发者key
String appKey = Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : config.getAppKey();
// 主动查询退款状态
JSONObject resultJson = UnionPayUtil.refundQuery(config, vo.getRefundCode(), unionPayPublicUtil.getAccessToken(appId, appKey));
log.info("银联账单订单退款查询返回数据, refundOrderCode: {}, resultJson: {}", vo.getRefundCode(), resultJson);
// 退款状态
String refundStatus = resultJson.getStr("refundStatus");
UnionRefundStatusEnum refundStatusEnum = EnumUtils.valueOf(UnionRefundStatusEnum.class, refundStatus,
UnionRefundStatusEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(refundStatusEnum)) {
case REFUND_SUCCESS:
// 更新订单退款状态
EduConsumeOrder eduBillOrder = getById(vo.getOrderId());
eduBillOrder.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
eduBillOrder.setPayStatus(PayStatusEnum.REFUND_SUCCESS.getStatus());
eduBillOrder.setIsRefund(RefundStatusEnum.IS_REFUND.getStatus());
baseMapper.updateById(eduBillOrder);
// 更新退款时间
EduConsumeOrderRefund eduBillOrderRefund = eduConsumeOrderRefundService.getById(vo.getRefundId());
eduBillOrderRefund.setRefundTime(LocalDateTimeUtil.parse((String) resultJson.get("responseTimestamp"), DatePattern.NORM_DATETIME_PATTERN));
eduConsumeOrderRefundService.updateById(eduBillOrderRefund);
break;
case REFUND_FAIL:
// TODO 2022/6/27 需要后续处理退款失败情况
break;
default:
break;
}
} catch (Exception e) {
log.error("查询银联消费订单退款状态失败, refundOrder: {}", vo, e);
}
}
/**
* 更新收钱吧退款订单状态
*
* @param vo 退款信息
* @author ZYJ
* @date 2023/4/3 16:26
*/
private void updateUPayRefundStatus(ConsumeRefundOrderVO vo) {
try {
DeptConsumeTerminalCache terminalCache = commonService.getDeptConsumeTerminal(vo.getDeptId());
JSONObject jsonObject = UPayUtil.queryRefundOrder(vo.getOrderCode(), vo.getRefundCode(), terminalCache.getTerminalSn(), terminalCache.getTerminalKey());
log.info("收钱吧消费订单查询返回数据, consumeOrderCode: {}, resultJson: {}", vo.getOrderCode(), jsonObject);
JSONObject resultJson = jsonObject.getJSONObject("biz_response").getJSONObject("data");
// 订单状态
String status = (String) resultJson.get("order_status");
UPayTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UPayTradeStateEnum.class, status,
UPayTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case REFUNDED:
// 更新订单退款状态
EduConsumeOrder eduBillOrder = getById(vo.getOrderId());
eduBillOrder.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
eduBillOrder.setPayStatus(PayStatusEnum.REFUND_SUCCESS.getStatus());
eduBillOrder.setIsRefund(RefundStatusEnum.IS_REFUND.getStatus());
baseMapper.updateById(eduBillOrder);
// 更新退款时间
EduConsumeOrderRefund eduBillOrderRefund = eduConsumeOrderRefundService.getById(vo.getRefundId());
eduBillOrderRefund.setRefundTime(LocalDateTimeUtil.ofUTC(Long.parseLong(resultJson.getStr("finish_time"))));
eduConsumeOrderRefundService.updateById(eduBillOrderRefund);
break;
case REFUND_ERROR:
// TODO 2023/4/3 需要后续处理退款失败情况
break;
default:
break;
}
} catch (Exception e) {
log.error("查询收钱吧消费订单退款状态失败, refundOrder: {}", vo, e);
}
}
@Override
public Page<ConsumeOrderPageVO> listConsumeOrderPage(ConsumeOrderPageDTO dto) {
List<Long> schoolIds = new ArrayList<>();
if (Objects.isNull(dto.getSchoolId())) {
List<Dept> deptList = remoteDeptService.getSchoolByArea(null, "").getData();
if (CollUtil.isEmpty(deptList)) {
schoolIds.add(-1L);
} else {
schoolIds = deptList.stream().map(Dept::getDeptId).collect(Collectors.toList());
}
} else {
schoolIds.add(dto.getSchoolId());
}
return baseMapper.listConsumeOrderPage(new Page<>(dto.getPageNum(), dto.getPageSize()), schoolIds, dto);
}
@Override
public void refundOrder(String orderCode) {
EduConsumeOrder order = getOne(new LambdaQueryWrapper<>(new EduConsumeOrder()).eq(EduConsumeOrder::getOrderCode, orderCode));
// 判断订单能否退款
Asserts.isTrue(OrderStatusEnum.PAY_SUCCESS.getStatus().equals(order.getOrderStatus())
&& PayStatusEnum.PAY_SUCCESS.getStatus().equals(order.getPayStatus()), "该笔订单无法进行退款");
// 保存退款信息
EduConsumeOrderRefund eduConsumeOrderRefund = new EduConsumeOrderRefund();
eduConsumeOrderRefund.setOrderCode(orderCode);
// 生成退款订单号
String refundOrderCode = "";
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
// 微信
refundOrderCode = "R" + orderCode;
} else if (PayWay.UNION.getValue().equals(order.getPayWay())) {
// 银联
// 获取银联商户号相关信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(order.getDeptId());
refundOrderCode = UnionPayUtil.getOrderNumber(Objects.nonNull(config.getParentConfig())
? config.getParentConfig().getSourceNumber() : config.getSourceNumber());
} else if (PayWay.U_PAY.getValue().equals(order.getPayWay())) {
// 收钱吧
refundOrderCode = "R" + orderCode;
}
eduConsumeOrderRefund.setRefundCode(refundOrderCode);
eduConsumeOrderRefund.setRefundSerialNumber(order.getTransactionNumber().replace("P", "R"));
eduConsumeOrderRefundService.save(eduConsumeOrderRefund);
// 修改订单状态
order.setOrderStatus(OrderStatusEnum.USER_REFUNDING.getStatus());
updateById(order);
try {
// 调用退款接口
PayWay payWay = EnumUtils.valueOf(PayWay.class, order.getPayWay(),
PayWay.class.getMethod("getValue"));
switch (Objects.requireNonNull(payWay)) {
// 微信
case WEI_XIN:
// 查询学校微信支付配置
EduPayWxConfig config = commonService.getPayWxConfigBySchool(order.getDeptId());
WxPayUtil.refund(config, eduConsumeOrderRefund.getOrderCode(),
eduConsumeOrderRefund.getRefundReason(),
eduConsumeOrderRefund.getRefundCode(),
NumberUtil.mul(order.getPracticalMoney(), new BigDecimal("100")).longValue(),
NumberUtil.mul(order.getPracticalMoney(), new BigDecimal("100")).longValue(),
apiUrl + CONSUME_WX_REFUND_NOTIFY_URL);
break;
case UNION:
// 查询学校银联云闪付支付配置
UnionPayConfig unionPayConfig = commonService.getUnionPayConfigByDept(order.getDeptId());
UnionPayConfig parentConfig = unionPayConfig.getParentConfig();
UnionPayUtil.refund(unionPayConfig, UnionRefund.builder()
.orderNo(orderCode)
.refundOrderNo(eduConsumeOrderRefund.getRefundCode())
.transactionNumber(eduConsumeOrderRefund.getRefundSerialNumber())
.refundAmount(order.getPracticalMoney())
.build()
, unionPayPublicUtil.getAccessToken(
Objects.nonNull(parentConfig) ? parentConfig.getAppId() : unionPayConfig.getAppId(),
Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : unionPayConfig.getAppKey()
));
break;
case U_PAY:
DeptConsumeTerminalCache terminalCache = commonService.getDeptConsumeTerminal(order.getDeptId());
JSONObject jsonObject = UPayUtil.refund(URefund.builder()
.clientSn(orderCode)
.refundRequestNo(refundOrderCode)
.operator(order.getPhone())
.refundAmount(order.getPracticalMoney())
.build(), terminalCache.getTerminalSn(), terminalCache.getTerminalKey());
JSONObject resultJson = jsonObject.getJSONObject("biz_response").getJSONObject("data");
// 更新订单退款状态
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.REFUND_SUCCESS.getStatus());
order.setIsRefund(RefundStatusEnum.IS_REFUND.getStatus());
baseMapper.updateById(order);
// 更新退款时间
EduConsumeOrderRefund eduBillOrderRefund = eduConsumeOrderRefundService.getById(eduConsumeOrderRefund.getId());
eduBillOrderRefund.setRefundTime(LocalDateTimeUtil.ofUTC(Long.parseLong(resultJson.getStr("finish_time"))));
eduConsumeOrderRefundService.updateById(eduBillOrderRefund);
break;
default:
break;
}
} catch (Exception e) {
log.error("退款失败", e);
throw new FebsException("退款失败");
}
}
}
@@ -0,0 +1,24 @@
package com.yida.data.device.consume.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.consume.EduConsumeOrderStudent;
import com.yida.data.device.consume.mapper.EduConsumeOrderStudentMapper;
import com.yida.data.device.consume.service.EduConsumeOrderStudentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 消费订单(充值)学生详细信息Service实现
*
* @author ZYJ
* @date 2023-03-23 14:03:58
*/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduConsumeOrderStudentServiceImpl extends ServiceImpl
<EduConsumeOrderStudentMapper, EduConsumeOrderStudent> implements EduConsumeOrderStudentService {
}
@@ -0,0 +1,24 @@
package com.yida.data.device.consume.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.consume.EduConsumeRecord;
import com.yida.data.device.consume.mapper.EduConsumeRecordMapper;
import com.yida.data.device.consume.service.EduConsumeRecordService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 消费机学生消费记录Service实现
*
* @author ZYJ
* @date 2023-03-24 16:16:49
*/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduConsumeRecordServiceImpl extends ServiceImpl
<EduConsumeRecordMapper, EduConsumeRecord> implements EduConsumeRecordService {
}
@@ -0,0 +1,38 @@
package com.yida.data.device.consume.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.consume.EduStudentConsumeCard;
import com.yida.data.device.consume.mapper.EduStudentConsumeCardMapper;
import com.yida.data.device.consume.service.EduStudentConsumeCardService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Objects;
/**
* 学生消费机信息管理Service实现
*
* @author ZYJ
* @date 2023-03-20 15:02:20
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduStudentConsumeCardServiceImpl extends ServiceImpl
<EduStudentConsumeCardMapper, EduStudentConsumeCard> implements EduStudentConsumeCardService {
@Override
public void saveConsumeCard(EduStudentConsumeCard eduStudentConsumeCard) {
EduStudentConsumeCard consumeCard = getOne(Wrappers.lambdaQuery(new EduStudentConsumeCard())
.eq(EduStudentConsumeCard::getStudentId, eduStudentConsumeCard.getStudentId()));
if (Objects.isNull(consumeCard)) {
eduStudentConsumeCard.setBalance(new BigDecimal("0.0"));
save(eduStudentConsumeCard);
}
}
}
@@ -0,0 +1,784 @@
package com.yida.data.device.consume.service.impl;
import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.common.ResultMsgType;
import com.yida.data.common.core.common.ResultStatusType;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.Dict;
import com.yida.data.common.core.entity.apply.EduApplyProductOrder;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.UPayConstant;
import com.yida.data.common.core.entity.constant.UnionPayConstant;
import com.yida.data.common.core.entity.consume.*;
import com.yida.data.common.core.entity.pay.UPayOrder;
import com.yida.data.common.core.entity.pay.UnionPayOrder;
import com.yida.data.common.core.entity.system.EduDeptPayType;
import com.yida.data.common.core.entity.system.EduPayWxConfig;
import com.yida.data.common.core.entity.system.UnionPayConfig;
import com.yida.data.common.core.entity.user.EduParent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.entity.user.EduStudentApply;
import com.yida.data.common.core.enums.*;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.*;
import com.yida.data.common.service.CommonService;
import com.yida.data.device.consume.mapper.EduConsumeOrderMapper;
import com.yida.data.device.consume.mapper.EduConsumeRecordMapper;
import com.yida.data.device.consume.service.EduConsumeOrderService;
import com.yida.data.device.consume.service.EduConsumeOrderStudentService;
import com.yida.data.device.consume.service.EduStudentConsumeCardService;
import com.yida.data.device.consume.service.H5ConsumeService;
import com.yida.data.device.dto.consume.CreateConsumeOrderDTO;
import com.yida.data.device.dto.consume.H5ConsumeOrderPageDTO;
import com.yida.data.device.dto.consume.H5ConsumeRecordPageDTO;
import com.yida.data.device.vo.consume.*;
import com.yida.data.user.feign.RemoteStudentApplyService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
/**
* 消费机前端service
*
* @author ZYJ
* @date 2023/3/16
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class H5ConsumeServiceImpl implements H5ConsumeService {
private final EduConsumeOrderService eduConsumeOrderService;
private final EduStudentConsumeCardService eduStudentConsumeCardService;
private final EduConsumeOrderStudentService eduConsumeOrderStudentService;
private final EduConsumeOrderMapper eduConsumeOrderMapper;
private final EduConsumeRecordMapper eduConsumeRecordMapper;
private final RemoteStudentService remoteStudentService;
private final RemoteStudentApplyService remoteStudentApplyService;
private final RedisService redisService;
private final CommonService commonService;
private final UnionPayPublicUtil unionPayPublicUtil;
private static final ExecutorService CONSUME_ORDER_SUCCESS_POOL = ThreadPoolUtil.getThreadPool("consume-order-pool-%d");
private static final Snowflake ORDER_CODE_GENERATOR = new Snowflake(1, 1);
private static final String CONSUME_WX_PAY_NOTIFY_URL = "device/in/consume/wxPayNotify";
private static final String CONSUME_WX_REFUND_NOTIFY_URL = "device/in/consume/wxRefundNotify";
private static final String CONSUME_UNION_PAY_NOTIFY_URL = "device/in/consume/unionPayNotify";
private static final String CONSUME_UNION_PAY_RETURN_URL = "";
@Value("${febs.apiUrl}")
private String apiUrl;
@Value("${febs.pageUrl}")
private String pageUrl;
@Override
public ConsumeVipVO checkVip(Long studentId, Long schoolId) {
Dict dict = commonService.getDictByTypeAndValueOrLabel("apply_type", null, "食堂消费");
// 查询是否是会员
EduStudentApply studentApply = remoteStudentApplyService.getStudentApply(studentId, dict.getValue()).getData();
ConsumeVipVO consumeVipVO = new ConsumeVipVO();
if (Objects.isNull(studentApply)) {
consumeVipVO.setVipFlag(false);
} else {
consumeVipVO.setVipFlag(true);
consumeVipVO.setStartTime(studentApply.getStartTime());
consumeVipVO.setEndTime(studentApply.getEndTime());
EduStudentConsumeCard consumeCard = eduStudentConsumeCardService.getOne(Wrappers.lambdaQuery(new EduStudentConsumeCard())
.eq(EduStudentConsumeCard::getStudentId, studentId));
if (Objects.nonNull(consumeCard)) {
consumeVipVO.setBalance(consumeCard.getBalance());
consumeVipVO.setCardStatus(consumeCard.getCardStatus());
EduStudent student = remoteStudentService.getStudentNoPermission(studentId).getData();
consumeVipVO.setStuCardNum(student.getStuCardNumber());
}
EduDeptPayType deptPayWay = commonService.getDeptPayWay(schoolId);
if (Objects.nonNull(deptPayWay)) {
consumeVipVO.setPayWay(deptPayWay.getPayWay());
consumeVipVO.setPayType(deptPayWay.getSupportType());
}
}
return consumeVipVO;
}
@Override
public String reportLoss(Long studentId) {
EduStudentConsumeCard consumeCard = eduStudentConsumeCardService.getOne(Wrappers.lambdaQuery(new EduStudentConsumeCard())
.eq(EduStudentConsumeCard::getStudentId, studentId));
if (Objects.isNull(consumeCard)) {
throw new FebsException(ResultMsgType.CARD_STATUS_ERROR.getValue());
}
EduStudent eduStudent = remoteStudentService.getStudentNoPermission(studentId).getData();
// 获取学校消费机服务器信息
EduConsumeConfig consumeConfig = commonService.getConsumeConfigByDept(consumeCard.getDeptId());
// 调用消费机挂失接口
ConsumeUtil.lockCard(consumeConfig, ConsumeUtil.getPersonInfo(consumeConfig, eduStudent.getStuCardNumber()).getStr("cardID"));
consumeCard.setCardStatus(EduStudentConsumeCard.LOSS_CARD);
eduStudentConsumeCardService.updateById(consumeCard);
return EduStudentConsumeCard.LOSS_CARD.toString();
}
@Override
public String unfreeze(Long studentId) {
EduStudentConsumeCard consumeCard = eduStudentConsumeCardService.getOne(Wrappers.lambdaQuery(new EduStudentConsumeCard())
.eq(EduStudentConsumeCard::getStudentId, studentId));
if (Objects.isNull(consumeCard)) {
throw new FebsException(ResultMsgType.CARD_STATUS_ERROR.getValue());
}
EduStudent eduStudent = remoteStudentService.getStudentNoPermission(studentId).getData();
// 获取学校消费机服务器信息
EduConsumeConfig consumeConfig = commonService.getConsumeConfigByDept(consumeCard.getDeptId());
// 调用消费机解挂接口
ConsumeUtil.unLockCard(consumeConfig, ConsumeUtil.getPersonInfo(consumeConfig, eduStudent.getStuCardNumber()).getStr("cardID"));
consumeCard.setCardStatus(EduStudentConsumeCard.NORMAL_CARD);
eduStudentConsumeCardService.updateById(consumeCard);
return EduStudentConsumeCard.NORMAL_CARD.toString();
}
@Override
public ConsumePayInfoVO createConsumeOrder(CreateConsumeOrderDTO dto) {
CurrentUser currentUser = FebsUtil.getCurrentUser();
// 查询学生信息
EduStudent student = remoteStudentService.getStudentNoPermission(dto.getStudentId()).getData();
if (Objects.isNull(student)) {
throw new FebsException("学生信息错误");
}
if (NumberUtil.isLessOrEqual(dto.getMoney(), BigDecimal.ZERO)) {
throw new FebsException("请输入正确的充值金额");
}
// 判断是否有下单缓存信息
ConsumeOrderStudentCacheVO existOrderStudent = (ConsumeOrderStudentCacheVO) redisService.get(
CachePrefixConstant.CONSUME_ORDER_STUDENT + dto.getStudentId().toString());
if (Objects.nonNull(existOrderStudent)) {
return ConsumePayInfoVO.builder()
.errorCode(ResultStatusType.FAIL.getValue())
.errorMessage(String.format("%s%s正在支付中, 请耐心等待",
existOrderStudent.getStudentName(), existOrderStudent.getParentType()))
.orderCode(existOrderStudent.getOrderNo())
.build();
}
if (StringUtils.isEmpty(dto.getPayWay()) ||
PayWay.ALIPAY.getValue().equals(dto.getPayWay())) {
throw new FebsException(ResultMsgType.PAY_TYPE_ERROR.getValue());
}
// 家长信息
List<EduParent> parents = student.getParents();
EduParent orderParent = parents.stream().filter(
x -> currentUser.getMobile().equals(x.getMobile())).collect(Collectors.toList()).get(0);
if (Objects.isNull(orderParent)) {
log.error("家长信息错误, studentId: {}, mobile: {}", dto.getStudentId(), currentUser.getMobile());
throw new FebsException("学生信息错误");
}
String orderCode = "";
try {
// 订单号 需要根据支付方式生成不同的订单号
String orderNo = "";
if (PayWay.WEI_XIN.getValue().equals(dto.getPayWay())) {
// 微信
orderNo = String.valueOf(ORDER_CODE_GENERATOR.nextId());
} else if (PayWay.UNION.getValue().equals(dto.getPayWay())) {
// 银联
// 获取银联商户号相关信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(student.getSchoolId());
orderNo = UnionPayUtil.getOrderNumber(Objects.nonNull(config.getParentConfig())
? config.getParentConfig().getSourceNumber() : config.getSourceNumber());
} else if (PayWay.U_PAY.getValue().equals(dto.getPayWay())) {
// 收钱吧
orderNo = String.valueOf(ORDER_CODE_GENERATOR.nextId());
}
if (StringUtils.isEmpty(orderNo)) {
log.error("生成订单号失败!");
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
orderCode = orderNo;
ConsumeOrderStudentCacheVO consumeOrderStudentCacheVO = ConsumeOrderStudentCacheVO.builder()
.studentId(dto.getStudentId())
.studentName(student.getStuName())
.parentId(orderParent.getId())
.parentType(orderParent.getParentType())
.mobile(currentUser.getMobile())
.orderNo(orderNo)
.build();
// 添加学生消费订单缓存
redisService.set(CachePrefixConstant.CONSUME_ORDER_STUDENT + dto.getStudentId().toString(), consumeOrderStudentCacheVO, UPayConstant.ORDER_TIME);
return createOrder(dto, student, orderParent, currentUser, orderNo);
} catch (FebsException e) {
// 删除学生消费订单缓存
redisService.del(CachePrefixConstant.CONSUME_ORDER_STUDENT + dto.getStudentId());
// 删除消费订单对应缓存
if (StringUtils.isNotBlank(orderCode)) {
redisService.del(CachePrefixConstant.CONSUME_ORDER + orderCode);
redisService.del(CachePrefixConstant.CONSUME_ORDER_FLAG + orderCode);
}
throw new FebsException(e.getMessage());
} catch (Exception e) {
// 删除学生消费订单缓存
redisService.del(CachePrefixConstant.CONSUME_ORDER_STUDENT + dto.getStudentId());
// 删除消费订单对应缓存
if (StringUtils.isNotBlank(orderCode)) {
redisService.del(CachePrefixConstant.CONSUME_ORDER + orderCode);
redisService.del(CachePrefixConstant.CONSUME_ORDER_FLAG + orderCode);
}
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
}
/**
* 生成订单并返回支付信息
*
* @param dto 生成消费订单请求类
* @param student 学生信息
* @param orderParent 下单家长
* @param currentUser 登录用户信息
* @param orderNo 订单号
* @return com.yida.data.device.vo.consume.ConsumePayInfoVO
* @author ZYJ
* @date 2023/3/23 15:50
*/
private ConsumePayInfoVO createOrder(CreateConsumeOrderDTO dto, EduStudent student,
EduParent orderParent, CurrentUser currentUser, String orderNo) {
// 生成消费订单信息
EduConsumeOrder eduConsumeOrder = new EduConsumeOrder();
eduConsumeOrder.setOrderCode(orderNo);
// 流水号
eduConsumeOrder.setTransactionNumber(PayUtil.generateSerialNumber("P", dto.getSchoolId(), ""));
eduConsumeOrder.setStudentId(student.getId());
eduConsumeOrder.setTotalMoney(dto.getMoney());
eduConsumeOrder.setPracticalMoney(dto.getMoney());
eduConsumeOrder.setPhone(currentUser.getMobile());
// 订单状态和支付状态
eduConsumeOrder.setOrderStatus(OrderStatusEnum.NOT_PAY.getStatus());
eduConsumeOrder.setPayStatus(PayStatusEnum.NOT_PAY.getStatus());
eduConsumeOrder.setPayWay(dto.getPayWay());
eduConsumeOrder.setPayType(dto.getPayType());
eduConsumeOrder.setDeptId(student.getSchoolId());
// 保存订单主体信息
eduConsumeOrderService.save(eduConsumeOrder);
// 保存学生信息
EduConsumeOrderStudent eduConsumeOrderStudent = new EduConsumeOrderStudent();
BeanUtils.copyProperties(student, eduConsumeOrderStudent);
eduConsumeOrderStudent.setId(null);
eduConsumeOrderStudent.setOrderId(eduConsumeOrder.getOrderId());
eduConsumeOrderStudent.setStudentId(student.getId());
eduConsumeOrderStudent.setStudentName(student.getStuName());
eduConsumeOrderStudent.setStudentNumber(student.getStuNumber());
eduConsumeOrderStudent.setStuCardNumber(student.getStuCardNumber());
eduConsumeOrderStudent.setStudentFamilyType(student.getFamilyType());
eduConsumeOrderStudent.setStudentParentType(orderParent.getParentType());
eduConsumeOrderStudentService.save(eduConsumeOrderStudent);
// 下单返回信息
String result = placeOrder(student, eduConsumeOrder, orderParent);
// 添加消费订单缓存
redisService.set(CachePrefixConstant.CONSUME_ORDER + eduConsumeOrder.getOrderCode(), eduConsumeOrder, UPayConstant.ORDER_TIME);
redisService.set(CachePrefixConstant.CONSUME_ORDER_FLAG + eduConsumeOrder.getOrderCode(), result, UPayConstant.ORDER_TIME);
return getPayInfo(eduConsumeOrder.getOrderCode(), result, eduConsumeOrder.getDeptId(), true,
dto.getPayWay(), dto.getPayType());
}
/**
* 调用第三方接口生成支付信息
*
* @param student 学生信息
* @param eduConsumeOrder 订单信息
* @param orderParent 下单家长
* @return java.lang.String
* @author ZYJ
* @date 2023/3/23 15:43
*/
private String placeOrder(EduStudent student, EduConsumeOrder eduConsumeOrder, EduParent orderParent) {
// 下单返回信息
String result = "";
try {
if (PayWay.WEI_XIN.getValue().equals(eduConsumeOrder.getPayWay())) {
// 微信支付
EduPayWxConfig config = commonService.getPayWxConfigBySchool(student.getSchoolId());
EduApplyProductOrder order = new EduApplyProductOrder();
order.setProductName("");
order.setOrderCode(eduConsumeOrder.getOrderCode());
order.setPraccticalMoney(eduConsumeOrder.getPracticalMoney().doubleValue());
String ip = FebsUtil.getHttpServletRequestIpAddress();
// js api下单
if (WxPayTypeEnum.JS_TYPE.getStatus().equals(eduConsumeOrder.getPayType())) {
result = WxPayUtil.placeOrderJs(config, order, orderParent.getWxPublicOpenId(), ip,
apiUrl + CONSUME_WX_PAY_NOTIFY_URL);
} else {
// h5下单
result = WxPayUtil.placeOrderH5(config, order, ip, apiUrl + CONSUME_WX_PAY_NOTIFY_URL);
}
} else if (PayWay.UNION.getValue().equals(eduConsumeOrder.getPayWay())) {
// 获取对应支付类型枚举
UnionPayTypeEnum unionPayTypeEnum = EnumUtils.valueOf(UnionPayTypeEnum.class, eduConsumeOrder.getPayType(),
UnionPayTypeEnum.class.getMethod("getType"));
// 银联云闪付
result = UnionPayUtil.placeOrder(commonService.getUnionPayConfigByDept(student.getSchoolId()),
UnionPayOrder.builder()
.orderNo(eduConsumeOrder.getOrderCode())
.transactionNumber(eduConsumeOrder.getTransactionNumber())
.payMoney(eduConsumeOrder.getPracticalMoney())
.notifyUrl(apiUrl + CONSUME_UNION_PAY_NOTIFY_URL)
.returnUrl(pageUrl + CONSUME_UNION_PAY_RETURN_URL)
.payTypeEnum(unionPayTypeEnum)
.build());
} else if (PayWay.U_PAY.getValue().equals(eduConsumeOrder.getPayWay())) {
// 收钱吧
DeptConsumeTerminalCache terminalCache = commonService.getDeptConsumeTerminal(eduConsumeOrder.getDeptId());
result = UPayUtil.placeOrder(UPayOrder.builder()
.clientSn(eduConsumeOrder.getOrderCode())
.totalAmount(eduConsumeOrder.getPracticalMoney())
.operator(orderParent.getMobile())
.notifyUrl(apiUrl + UPayConstant.NOTIFY_URL)
// .returnUrl(pageUrl + UPayConstant.RETURN_URL)
.returnUrl("http://zbztest.yd-data.com")
.build(), terminalCache.getTerminalSn(), terminalCache.getTerminalKey());
}
} catch (Exception e) {
log.error("消费下单失败", e);
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
if (StringUtils.isEmpty(result)) {
log.error("消费下单失败, 没有支付信息");
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
return result;
}
/**
* 获取订单支付信息
*
* @param orderCode 订单号
* @param orderFlag 微信js支付prepayId, h5支付跳转地址
* @param deptId 学校id
* @param needToPay 是否需要跳转支付
* @param payWay 支付方式 {@link PayWay}
* @param payType 支付类型
* @return com.yida.data.device.vo.consume.ConsumePayInfoVO
* @author ZYJ
* @date 2023/3/23 15:48
*/
public ConsumePayInfoVO getPayInfo(String orderCode, String orderFlag, Long deptId,
boolean needToPay, String payWay, Integer payType) {
ConsumePayInfoVO consumePayInfoVO = null;
if (PayWay.WEI_XIN.getValue().equals(payWay)) {
// 微信
consumePayInfoVO = getWxJsSign(orderCode, orderFlag, deptId, needToPay, payType);
} else if (PayWay.UNION.getValue().equals(payWay)) {
// 银联
consumePayInfoVO = ConsumePayInfoVO.builder()
.orderCode(orderCode)
.needToPay(needToPay)
.payWay(payWay)
.payType(payType)
.payDomain(UnionPayConstant.URL)
.payUrl(orderFlag)
.build();
} else if (PayWay.U_PAY.getValue().equals(payWay)) {
// 收钱吧
consumePayInfoVO = ConsumePayInfoVO.builder()
.orderCode(orderCode)
.needToPay(needToPay)
.payWay(payWay)
.payType(payType)
.payDomain(UPayConstant.URL)
.payUrl(orderFlag)
.build();
}
return consumePayInfoVO;
}
/**
* 生成微信支付信息
*
* @param orderCode 订单号
* @param orderFlag 微信js支付prepayId, h5支付跳转地址
* @param deptId 学校id
* @param needToPay 是否需要跳转支付
* @param wxPayType 微信支付类型 {@link WxPayTypeEnum}
* @return com.yida.data.device.vo.consume.ConsumePayInfoVO
* @author ZYJ
* @date 2023/3/23 15:47
*/
public ConsumePayInfoVO getWxJsSign(String orderCode, String orderFlag, Long deptId,
boolean needToPay, Integer wxPayType) {
ConsumePayInfoVO infoVO = new ConsumePayInfoVO();
infoVO.setOrderCode(orderCode);
infoVO.setNeedToPay(needToPay);
infoVO.setPayWay(PayWay.WEI_XIN.getValue());
infoVO.setPayType(wxPayType);
// js api类型
if (Objects.isNull(wxPayType) || WxPayTypeEnum.JS_TYPE.getStatus().equals(wxPayType)) {
EduPayWxConfig config = commonService.getPayWxConfigBySchool(deptId);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = RandomUtil.randomString(32);
String packages = "prepay_id=" + orderFlag;
String code = config.getWxPublicId() + "\n" + timestamp + "\n" + nonceStr + "\n" + packages + "\n";
Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, config.getApiCreditPrivateKeyNoHead(),
null);
byte[] res = sign.sign(code.getBytes());
String signRes = Base64.encode(res);
infoVO.setWxAppId(config.getWxPublicId());
infoVO.setWxSign(signRes);
infoVO.setWxTimestamp(timestamp);
infoVO.setWxPackage(packages);
infoVO.setWxNonceStr(nonceStr);
} else {
infoVO.setPayUrl(orderFlag);
}
return infoVO;
}
@Override
public void consumeOrderSuccess(String orderCode) {
CONSUME_ORDER_SUCCESS_POOL.execute(() -> {
EduConsumeOrder order = eduConsumeOrderService.getOne(new LambdaQueryWrapper<>(new EduConsumeOrder())
.eq(EduConsumeOrder::getOrderCode, orderCode));
if (Objects.nonNull(order)
&& (OrderStatusEnum.NOT_PAY.getStatus().equals(order.getOrderStatus())
|| OrderStatusEnum.USER_PAYING.getStatus().equals(order.getOrderStatus()))) {
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
// 微信
wxConsumeOrderSuccess(order);
} else if (PayWay.UNION.getValue().equals(order.getPayWay())) {
// 银联
unionConsumeOrderSuccess(order);
} else if (PayWay.U_PAY.getValue().equals(order.getPayWay())) {
// 收钱吧
uPayConsumeOrderSuccess(order);
}
}
});
}
/**
* 处理微信查询订单
*
* @param order 订单信息
* @author ZYJ
* @date 2023/3/23 16:48
*/
private void wxConsumeOrderSuccess(EduConsumeOrder order) {
boolean flag = false;
// 订单号
String orderCode = order.getOrderCode();
// 查询学校微信配置信息
EduPayWxConfig config = commonService.getPayWxConfigBySchool(order.getDeptId());
while (LocalDateTimeUtil.between(order.getCreateDate(), LocalDateTime.now()).getSeconds() < UPayConstant.ORDER_TIME) {
try {
JSONObject resJson = JSONUtil.parseObj(WxPayUtil.queryOrder(config, orderCode));
String tradeState = resJson.getStr("trade_state");
if (WxTradeStateEnum.NOT_PAY.getStatus().equals(tradeState)) {
continue;
}
WxTradeStateEnum wxTradeStateEnum = EnumUtils.valueOf(WxTradeStateEnum.class, tradeState,
WxTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(wxTradeStateEnum)) {
// 支付成功
case SUCCESS:
consumeOrderPaySuccess(orderCode, DateUtil.parseLocalDateTime(resJson.getStr("success_time"), "yyyy-MM" + "-dd'T" + "'HH:mm" + ":ssXXX"));
flag = true;
break;
// 作废订单
case CLOSED:
case REVOKED:
case PAY_ERROR:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduConsumeOrderService.updateById(order);
flag = true;
break;
default:
break;
}
if (flag) {
break;
}
Thread.sleep(1000L);
} catch (Exception e) {
log.error("消费订单(微信支付方式)完成失败, orderNo: {}", orderCode, e);
}
}
}
/**
* 处理银联查询订单
*
* @param order 订单信息
* @author ZYJ
* @date 2023/3/23 16:50
*/
private void unionConsumeOrderSuccess(EduConsumeOrder order) {
boolean flag = false;
// 订单号
String orderCode = order.getOrderCode();
// 查询学校银联配置信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(order.getDeptId());
// 主商户信息
UnionPayConfig parentConfig = config.getParentConfig();
while (LocalDateTimeUtil.between(order.getCreateDate(), LocalDateTime.now()).getSeconds() < UPayConstant.ORDER_TIME) {
try {
JSONObject resJson = UnionPayUtil.queryOrder(config,
unionPayPublicUtil.getAccessToken(
Objects.nonNull(parentConfig) ? parentConfig.getAppId() : config.getAppId(),
Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : config.getAppKey()
), orderCode);
// 支付状态
String status = (String) resJson.get("status");
if (UnionTradeStateEnum.NEW_ORDER.getStatus().equals(status)
|| UnionTradeStateEnum.UNKNOWN.getStatus().equals(status)
|| UnionTradeStateEnum.WAIT_BUYER_PAY.getStatus().equals(status)) {
return;
}
UnionTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UnionTradeStateEnum.class, status,
UnionTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case TRADE_SUCCESS:
consumeOrderPaySuccess(order.getOrderCode(),
LocalDateTimeUtil.parse((String) resJson.get("payTime"), DatePattern.NORM_DATETIME_PATTERN));
flag = true;
break;
// 订单关闭
case TRADE_CLOSED:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduConsumeOrderService.updateById(order);
flag = true;
break;
default:
break;
}
if (flag) {
break;
}
Thread.sleep(1000L);
} catch (Exception e) {
log.error("消费订单(云闪付支付方式)完成失败, orderNo: {}", orderCode, e);
}
}
}
/**
* 处理收钱吧查询订单
*
* @param order 订单信息
* @author ZYJ
* @date 2023/3/23 17:29
*/
private void uPayConsumeOrderSuccess(EduConsumeOrder order) {
boolean flag = false;
// 订单号
String orderCode = order.getOrderCode();
while (LocalDateTimeUtil.between(order.getCreateDate(), LocalDateTime.now()).getSeconds() < UPayConstant.ORDER_TIME) {
try {
DeptConsumeTerminalCache terminalCache = commonService.getDeptConsumeTerminal(order.getDeptId());
JSONObject jsonObject = UPayUtil.queryOrder(orderCode, terminalCache.getTerminalSn(), terminalCache.getTerminalKey());
JSONObject resJson = jsonObject.getJSONObject("biz_response").getJSONObject("data");
// 支付状态
String status = (String) resJson.get("order_status");
if (UPayTradeStateEnum.CREATED.getStatus().equals(status)
|| UPayTradeStateEnum.INVALID_STATUS_CODE.getStatus().equals(status)) {
return;
}
UPayTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UPayTradeStateEnum.class, status,
UnionTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case PAID:
consumeOrderPaySuccess(order.getOrderCode(), LocalDateTimeUtil.ofUTC(Long.parseLong(resJson.getStr("finish_time"))));
flag = true;
break;
// 订单关闭
case PAY_CANCELED:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduConsumeOrderService.updateById(order);
flag = true;
break;
default:
break;
}
if (flag) {
break;
}
Thread.sleep(1000L);
} catch (Exception e) {
log.error("消费订单(收钱吧支付方式)完成失败, orderNo: {}", orderCode, e);
}
}
}
/**
* 消费订单支付成功
*
* @param orderCode 订单号
* @param payDate 支付时间
* @author ZYJ
* @date 2023/3/23 17:06
*/
@Override
public void consumeOrderPaySuccess(String orderCode, LocalDateTime payDate) {
EduConsumeOrder order = eduConsumeOrderService.getOne(new LambdaQueryWrapper<>(new EduConsumeOrder())
.eq(EduConsumeOrder::getOrderCode, orderCode));
order.setPayDate(payDate);
order.setOrderStatus(OrderStatusEnum.PAY_SUCCESS.getStatus());
order.setPayStatus(PayStatusEnum.PAY_SUCCESS.getStatus());
eduConsumeOrderService.updateById(order);
// 获取学校消费机服务器信息
EduConsumeConfig consumeConfig = commonService.getConsumeConfigByDept(order.getDeptId());
EduStudent student = remoteStudentService.getStudentNoPermission(order.getStudentId()).getData();
// 调用消费机接口
ConsumeUtil.recharge(consumeConfig, Recharge.builder()
.amount(order.getPracticalMoney().toString())
.accountNo(student.getStuCardNumber())
.increase(true)
.walletType(1)
.transactionNumber(order.getTransactionNumber())
.paymentModel(Recharge.PaymentModel.builder()
// 支付方式. 0:现金 1:微信 2:支付宝 4:银行卡 8:其他APP
.payType(1)
.payTime(LocalDateTimeUtil.format(payDate, DatePattern.NORM_DATETIME_PATTERN))
.orderNumber(orderCode)
.build())
.build());
// 处理对应消费机信息金额
EduStudentConsumeCard consumeCard = eduStudentConsumeCardService.getOne(Wrappers.lambdaQuery(new EduStudentConsumeCard())
.eq(EduStudentConsumeCard::getStudentId, order.getStudentId()));
if (Objects.nonNull(consumeCard)) {
consumeCard.setBalance(NumberUtil.add(consumeCard.getBalance(), order.getPracticalMoney()));
eduStudentConsumeCardService.updateById(consumeCard);
}
// 删除学生消费订单缓存
redisService.del(CachePrefixConstant.CONSUME_ORDER_STUDENT + order.getStudentId().toString());
// 删除消费订单对应缓存
redisService.del(CachePrefixConstant.CONSUME_ORDER + orderCode);
redisService.del(CachePrefixConstant.CONSUME_ORDER_FLAG + orderCode);
}
@Override
public IPage<H5ConsumeOrderPageVO> listH5ConsumeOrderPage(H5ConsumeOrderPageDTO dto) {
return eduConsumeOrderMapper.listH5ConsumeOrderPage(dto.toPage(), dto);
}
@Override
public H5ConsumeOrderPageVO getH5ConsumeOrderInfo(Long orderId, String orderCode) {
return eduConsumeOrderMapper.getH5ConsumeOrderInfo(orderId, orderCode);
}
@Override
public ConsumePayInfoVO continuePayOrder(String orderCode, Long deptId) {
EduConsumeOrder order = eduConsumeOrderService.getOne(new LambdaQueryWrapper<>(new EduConsumeOrder())
.eq(EduConsumeOrder::getOrderCode, orderCode));
if (Objects.isNull(order) || OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
throw new FebsException(ResultMsgType.ORDER_INVALID.getValue());
}
// 判断当前订单能否被当前用户支付
ConsumeOrderStudentCacheVO existConsumeOrderStudent = (ConsumeOrderStudentCacheVO) redisService.get(
CachePrefixConstant.CONSUME_ORDER_STUDENT + order.getStudentId().toString());
if (Objects.nonNull(existConsumeOrderStudent)
&& !FebsUtil.getCurrentUser().getMobile().equals(existConsumeOrderStudent.getMobile())) {
throw new FebsException(String.format("%s%s正在支付中, 请耐心等待",
existConsumeOrderStudent.getStudentName(),
existConsumeOrderStudent.getParentType()));
}
// 获取对应待支付信息缓存
Object orderFlag = redisService.get(CachePrefixConstant.CONSUME_ORDER_FLAG + orderCode);
if (Objects.isNull(orderFlag)) {
throw new FebsException("当前订单已失效!");
}
return getPayInfo(orderCode, orderFlag.toString(), deptId,
true, order.getPayWay(), order.getPayType());
}
@Override
public void cancelOrder(String orderCode) {
// TODO 2023/3/31 需要做状态判断能否取消订单
EduConsumeOrder order = eduConsumeOrderService.getOne(new LambdaQueryWrapper<>(new EduConsumeOrder())
.eq(EduConsumeOrder::getOrderCode, orderCode));
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
throw new FebsException(ResultMsgType.ORDER_INVALID.getValue());
}
// 判断当前订单能否被当前用户取消
ConsumeOrderStudentCacheVO existConsumeOrderStudent = (ConsumeOrderStudentCacheVO) redisService.get(
CachePrefixConstant.CONSUME_ORDER_STUDENT + order.getStudentId().toString());
if (Objects.nonNull(existConsumeOrderStudent)
&& !FebsUtil.getCurrentUser().getMobile().equals(existConsumeOrderStudent.getMobile())) {
throw new FebsException(String.format("%s%s正在支付中, 请耐心等待",
existConsumeOrderStudent.getStudentName(), existConsumeOrderStudent.getParentType()));
}
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduConsumeOrderService.updateById(order);
try {
// 判断支付方式
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
// 关闭微信订单
WxPayUtil.closeOrder(commonService.getPayWxConfigBySchool(order.getDeptId()), order.getOrderCode());
} else if (PayWay.UNION.getValue().equals(order.getPayWay())
&& !UnionPayTypeEnum.UNION_H5_TYPE.getType().equals(order.getPayType())) {
// 关闭银联订单 (银联云闪付不支付关闭订单)
UnionPayConfig unionPayConfig = commonService.getUnionPayConfigByDept(order.getDeptId());
UnionPayConfig parentConfig = unionPayConfig.getParentConfig();
UnionPayUtil.closeOrder(unionPayConfig,
unionPayPublicUtil.getAccessToken(
Objects.nonNull(parentConfig) ? parentConfig.getAppId() : unionPayConfig.getAppId(),
Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : unionPayConfig.getAppKey()
), order.getOrderCode());
} else if (PayWay.U_PAY.getValue().equals(order.getPayWay())) {
// 关闭收钱吧订单
DeptConsumeTerminalCache terminalCache = commonService.getDeptConsumeTerminal(order.getDeptId());
UPayUtil.closeOrder(orderCode, terminalCache.getTerminalSn(), terminalCache.getTerminalKey());
}
} catch (Exception e) {
log.error("关闭订单失败, order: {}", order, e);
throw new FebsException("取消订单失败");
}
// 删除学生消费订单缓存
redisService.del(CachePrefixConstant.CONSUME_ORDER_STUDENT + order.getStudentId().toString());
// 删除消费订单对应缓存
redisService.del(CachePrefixConstant.CONSUME_ORDER + orderCode);
redisService.del(CachePrefixConstant.CONSUME_ORDER_FLAG + orderCode);
}
@Override
public IPage<H5ConsumeRecordPageVO> listH5ConsumeRecordPage(H5ConsumeRecordPageDTO dto) {
return eduConsumeRecordMapper.listH5ConsumeRecordPage(dto.toPage(), dto);
}
}
@@ -119,7 +119,7 @@ public class CardRabbitReceiver {
redisService.hset(CachePrefixConstant.STUDENT_DATA, card.getStudentId().toString(), student);
}
EduApp app = commonService
.getAppByCodeAndSchool(AppConstant.ELECTRONIC_PARENT, null, card.getSchoolId());
.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null, card.getSchoolId());
String accessToken = wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret());
TextSchoolNotice notice = new TextSchoolNotice();
notice.setAgentid(app.getWxAgentId());
@@ -2,7 +2,6 @@ package com.yida.data.device.studentCard.controller;
import cc.mrbird.febs.common.redis.service.RedisService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.common.core.annotation.ControllerLog;
import com.yida.data.common.core.common.ModuleName;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.CurrentUser;
@@ -21,12 +20,12 @@ import com.yida.data.device.dto.studentCard.CardWithAddressDTO;
import com.yida.data.device.dto.studentCard.DisturbStatusDTO;
import com.yida.data.device.studentCard.service.EduStudentCardDisturbTimeService;
import com.yida.data.device.studentCard.service.EduStudentCardService;
import com.yida.data.device.vo.OnlineCountVO;
import com.yida.data.device.vo.studentCard.CardInfoVO;
import com.yida.data.device.vo.studentCard.CardPageVO;
import com.yida.data.device.vo.studentCard.CardWithAddressVO;
import com.yida.data.device.vo.studentCard.ListStudentCardVO;
import com.yida.data.device.vo.studentCard.LocationVO;
import com.yida.data.device.vo.OnlineCountVO;
import com.yida.data.device.vo.studentCard.TrackVO;
import com.yida.data.log.annotation.OperationLog;
import com.yida.data.system.feign.RemoteDeptService;
@@ -83,6 +82,7 @@ public class EduStudentCardController {
@ApiOperation("更新学生证")
@PostMapping("/updateCard")
@OperationLog(module = ModuleName.ELECTRONIC_STUDENT_CARD, methods = "更新学生证", type = OperationLogTypeEnum.UPDATE)
public ResultBean updateCard(@RequestBody EduStudentCard card) {
eduStudentCardService.updateCard(card);
return ResultBean.buildSuccess();
@@ -154,9 +154,7 @@ public class EduStudentCardController {
@ApiOperation("家长对应学生列表")
@GetMapping("/listStudentCard")
@ControllerLog(operation = "家长对应学生列表")
public ResultBean<List<ListStudentCardVO>> listStudentCard(@ApiParam("家长id") @RequestParam Long parentId) {
return ResultBean.buildSuccess(eduStudentCardService.listStudentCard(parentId));
}
@@ -182,7 +180,7 @@ public class EduStudentCardController {
@ApiOperation("批量免打扰")
@PostMapping("/setDisturbStatus")
@ControllerLog(operation = "批量免打扰")
@OperationLog(module = ModuleName.ELECTRONIC_STUDENT_CARD, methods = "批量免打扰", type = OperationLogTypeEnum.UPDATE)
public ResultBean setDisturbStatus(@RequestBody DisturbStatusDTO disturbStatusDTO) {
eduStudentCardService.setDisturbStatus(disturbStatusDTO);
return ResultBean.buildSuccess();
@@ -213,6 +211,7 @@ public class EduStudentCardController {
@ApiOperation("下发监听指令")
@GetMapping("/issueMonitor")
@OperationLog(module = ModuleName.ELECTRONIC_STUDENT_CARD, methods = "下发监听指令", type = OperationLogTypeEnum.SELECT)
public ResultBean issueMonitor(@ApiParam("接收监听手机号") String mobile,
@ApiParam("学生证imei号") String imei) {
eduStudentCardService.issueMonitor(mobile, imei);
@@ -2,9 +2,12 @@ package com.yida.data.device.studentCard.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.annotation.ControllerLog;
import com.yida.data.common.core.common.ModuleName;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.card.EduStudentCardPhone;
import com.yida.data.common.core.entity.system.enums.OperationLogTypeEnum;
import com.yida.data.device.studentCard.service.EduStudentCardPhoneService;
import com.yida.data.log.annotation.OperationLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@@ -39,7 +42,6 @@ public class EduStudentCardPhoneController {
@ApiOperation("查询学生证电话")
@GetMapping("/getFamilyPhone")
@ControllerLog(operation = "查询亲情电话")
public ResultBean getFamilyPhone(@ApiParam("iMei号") @RequestParam String imei,
@ApiParam("1是亲情电话,2是sos电话,3是通话白名单") @RequestParam Integer type) {
List<EduStudentCardPhone> list = eduStudentCardPhoneService.list(Wrappers.lambdaQuery(new EduStudentCardPhone())
@@ -50,7 +52,7 @@ public class EduStudentCardPhoneController {
@ApiOperation("保存电话")
@PostMapping("/savePhone")
@ControllerLog(operation = "保存电话")
@OperationLog(module = ModuleName.TELEPHONE, methods = "保存电话", type = OperationLogTypeEnum.SAVE)
public ResultBean savePhone(@RequestBody EduStudentCardPhone phone) {
eduStudentCardPhoneService.savePhone(phone);
return ResultBean.buildSuccess();
@@ -59,7 +61,7 @@ public class EduStudentCardPhoneController {
@ApiOperation("通用删除电话")
@GetMapping("/delPhone")
@ControllerLog(operation = "通用删除电话")
@OperationLog(module = ModuleName.TELEPHONE, methods = "通用删除电话", type = OperationLogTypeEnum.DELETE)
public ResultBean delPhone(@RequestParam Long id) {
eduStudentCardPhoneService.delPhone(id);
return ResultBean.buildSuccess();
@@ -67,7 +69,7 @@ public class EduStudentCardPhoneController {
@ApiOperation("批量修改电话")
@PostMapping("/updateFamilyPhoneBatch")
@ControllerLog(operation = "修改电话")
@OperationLog(module = ModuleName.TELEPHONE, methods = "批量修改电话", type = OperationLogTypeEnum.UPDATE)
public ResultBean updateFamilyPhoneBatch(@RequestBody List<EduStudentCardPhone> phones,
@ApiParam("1-亲情电话,2-sos3-白名单") Integer type, String imei) {
eduStudentCardPhoneService.updatePhoneBatch(phones, type, imei);
@@ -158,7 +158,7 @@ public class EduStudentCardAlarmServiceImpl extends ServiceImpl
}
private void pushSchoolNotice(EduStudent student, EduStudentCardAlarm alarm, Dept school) {
EduApp app = commonService.getAppByCodeAndSchool(AppConstant.ELECTRONIC_PARENT, null, school.getDeptId());
EduApp app = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null, school.getDeptId());
TextSchoolNotice notice = new TextSchoolNotice();
notice.setAgentid(app.getWxAgentId());
notice.setTo_student_userid(Collections.singletonList(student.getWxId()));
@@ -2,9 +2,11 @@ package com.yida.data.device.telephone.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.annotation.ControllerLog;
import com.yida.data.common.core.common.ModuleName;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.enums.OperationLogTypeEnum;
import com.yida.data.common.core.entity.telephone.EduTelephone;
import com.yida.data.common.core.entity.telephone.EduTelephoneBlack;
import com.yida.data.common.core.entity.telephone.EduTelephoneCard;
@@ -19,6 +21,7 @@ import com.yida.data.device.telephone.service.EduTelephoneService;
import com.yida.data.device.vo.OnlineCountVO;
import com.yida.data.device.vo.telephone.DeviceNumberVO;
import com.yida.data.device.vo.telephone.TelephoneVO;
import com.yida.data.log.annotation.OperationLog;
import com.yida.data.system.feign.RemoteDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -84,13 +87,13 @@ public class EduTelephoneController {
*/
@ApiOperation("话机设备数量统计")
@GetMapping("/findDeviceNumber")
@ControllerLog(operation = "话机设备数量统计")
public ResultBean<DeviceNumberVO> findDeviceNumber() throws NoSuchMethodException {
return eduTelephoneService.findDeviceNumber();
}
@ApiOperation("修改或新增")
@PostMapping("/insertTelephone")
@OperationLog(module = ModuleName.TELEPHONE, methods = "修改或新增亲情电话", type = OperationLogTypeEnum.SAVE)
public ResultBean insertTelephone(@RequestBody EduTelephone eduTelephone) {
eduTelephoneService.saveOrUpdate(eduTelephone);
return ResultBean.buildSuccess();
@@ -98,6 +101,7 @@ public class EduTelephoneController {
@ApiOperation("批量设置")
@PostMapping("/updateTelephone")
@OperationLog(module = ModuleName.TELEPHONE, methods = "批量设置亲情电话", type = OperationLogTypeEnum.UPDATE)
public ResultBean updateTelephone(@RequestBody TelephoneDTO telephoneDTO) {
eduTelephoneService.updateTelephone(telephoneDTO);
return ResultBean.buildSuccess();
@@ -112,6 +116,7 @@ public class EduTelephoneController {
@ApiOperation("重置本月通话时间")
@GetMapping("/delTelephoneTime")
@OperationLog(module = ModuleName.TELEPHONE, methods = "重置本月通话时间", type = OperationLogTypeEnum.UPDATE)
public ResultBean delTelephoneTime(@ApiParam("话机Id") @RequestParam Long id) {
EduTelephone eduTelephone = new EduTelephone();
eduTelephone.setId(id);
@@ -122,6 +127,7 @@ public class EduTelephoneController {
@ApiOperation("停运")
@GetMapping("/stopTelephone")
@OperationLog(module = ModuleName.TELEPHONE, methods = "停运亲情电话", type = OperationLogTypeEnum.UPDATE)
public ResultBean stopTelephone(@ApiParam("话机Id") @RequestParam Long id,
@ApiParam("1停运,0正常") @RequestParam Integer status) {
@@ -133,6 +139,7 @@ public class EduTelephoneController {
@ApiOperation("删除和批量删除")
@PostMapping("/delTelephone")
@OperationLog(module = ModuleName.TELEPHONE, methods = "删除和批量删除亲情电话", type = OperationLogTypeEnum.DELETE)
public ResultBean delTelephone(@ApiParam("ids") @RequestBody List<Long> ids) {
eduTelephoneService.removeByIds(ids);
for (Long id : ids) {
@@ -146,6 +153,7 @@ public class EduTelephoneController {
@ApiOperation("批量停运")
@PostMapping("/listStopTelephone")
@OperationLog(module = ModuleName.TELEPHONE, methods = "批量停运亲情电话", type = OperationLogTypeEnum.UPDATE)
public ResultBean listStopTelephone(@ApiParam("话机Id") @RequestBody PhoneStatusDTO phoneStatusDTO) {
List<Long> ids = phoneStatusDTO.getIds();
@@ -4,14 +4,17 @@ import cc.mrbird.febs.common.redis.service.RedisService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.annotation.ControllerLog;
import com.yida.data.common.core.common.ModuleName;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.system.enums.OperationLogTypeEnum;
import com.yida.data.common.core.entity.telephone.EduTelephoneOrder;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.device.dto.telephone.OrderPageDTO;
import com.yida.data.device.telephone.service.EduTelephoneOrderService;
import com.yida.data.device.vo.telephone.OrderInfoVO;
import com.yida.data.device.vo.telephone.OrderPageVO;
import com.yida.data.log.annotation.OperationLog;
import com.yida.data.school.vo.transcation.PayInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -65,17 +68,17 @@ public class EduTelephoneOrderController {
@GetMapping("/listOrder")
public ResultBean<List<EduTelephoneOrder>> listOrder(@ApiParam("卡id") @RequestParam Long cardId) {
return ResultBean.buildSuccess(eduTelephoneOrderService.list(Wrappers.lambdaQuery(new EduTelephoneOrder())
.eq(EduTelephoneOrder::getCardId, cardId).orderByDesc(EduTelephoneOrder::getCreateDate)));
.eq(EduTelephoneOrder::getCardId, cardId).orderByDesc(EduTelephoneOrder::getCreateDate)));
}
@ApiOperation("生成订单")
@GetMapping("/createOrder")
@ControllerLog(operation = "生成订单")
@OperationLog(module = ModuleName.TELEPHONE, methods = "生成订单", type = OperationLogTypeEnum.INSERT)
public ResultBean<PayInfoVO> insertEduProductOrder(@ApiParam("充值金额") Double money,
@ApiParam("ic卡id") Long icCardId,
@ApiParam("支付方式,0-微信jsapi1-微信h5") Integer payType) {
@ApiParam("ic卡id") Long icCardId,
@ApiParam("支付方式,0-微信jsapi1-微信h5") Integer payType) {
return ResultBean.buildSuccess(eduTelephoneOrderService.createOrder(money, icCardId, payType, FebsUtil.getCurrentUser(),
FebsUtil.getHttpServletRequestIpAddress()));
FebsUtil.getHttpServletRequestIpAddress()));
}
@ApiOperation("订单完成(前台支付完成后调用)")
@@ -87,6 +90,7 @@ public class EduTelephoneOrderController {
@ApiOperation("发起支付")
@GetMapping("/payOrder")
@OperationLog(module = ModuleName.TELEPHONE, methods = "发起支付", type = OperationLogTypeEnum.INSERT)
public ResultBean<PayInfoVO> payOrder(String orderCode) {
Object prepay = redisService.get(CachePrefixConstant.ORDER_FLAG + orderCode);
PayInfoVO infoVO = eduTelephoneOrderService.getWxJsSign(orderCode, prepay.toString());
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.device.consume.mapper.EduConsumeDeviceMapper">
<select id="listDevicePage" resultType="com.yida.data.device.vo.consume.ConsumeDeviceVO">
SELECT
*
FROM
edu_consume_device
WHERE
del_flag = 0
AND school_id IN
<foreach collection="schoolIds" open="(" close=")" separator="," item="schoolId">
#{schoolId}
</foreach>
<if test='number != null and number != ""'>
AND ( sn LIKE CONCAT( '%', #{number}, '%' ) OR `name` LIKE CONCAT( '%', #{number}, '%' ) )
</if>
<if test="state != null">
and state = #{state}
</if>
ORDER BY
create_date DESC
</select>
</mapper>
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.device.consume.mapper.EduConsumeOrderMapper">
<!-- 前端查询消费订单列表数据 -->
<select id="listH5ConsumeOrderPage"
resultType="com.yida.data.device.vo.consume.H5ConsumeOrderPageVO">
SELECT o.*,
s.student_name
FROM edu_consume_order o
LEFT JOIN edu_consume_order_student s ON o.order_id = s.order_id
WHERE o.dept_id = #{dto.deptId}
AND o.student_id = #{dto.studentId}
AND o.del_flag = 0
ORDER BY o.create_date DESC
</select>
<!-- 前端查询消费订单详情 -->
<select id="getH5ConsumeOrderInfo"
resultType="com.yida.data.device.vo.consume.H5ConsumeOrderPageVO">
SELECT o.*,
s.student_name
FROM edu_consume_order o
LEFT JOIN edu_consume_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
<if test="orderId != null">
AND o.order_id = #{orderId}
</if>
<if test="orderCode != null and orderCode != ''">
AND o.order_code = #{orderCode}
</if>
</select>
<!-- 查询所有已经超时订单 -->
<select id="selectTimeOutConsumeOrder"
resultType="com.yida.data.common.core.entity.consume.EduConsumeOrder">
SELECT
*
FROM
edu_consume_order
WHERE
order_status = '0'
AND TIMESTAMPDIFF( SECOND, create_date, now( ) ) > 300
</select>
<!-- 查询退款中状态的账单订单 -->
<select id="selectRefundOrder"
resultType="com.yida.data.device.vo.consume.ConsumeRefundOrderVO">
SELECT
b.order_id,
b.order_code,
r.refund_code,
r.id refund_id,
b.pay_way,
b.dept_id
FROM
edu_consume_order b
LEFT JOIN edu_consume_order_refund r ON b.order_code = r.order_code
WHERE
b.del_flag = 0
AND b.order_status = '3'
AND b.pay_status = '1'
</select>
<resultMap id="consumeOrderMap" type="com.yida.data.device.vo.consume.ConsumeOrderPageVO">
<id column="order_id" property="orderId"/>
<result column="order_code" property="orderCode" />
<result column="transaction_number" property="transactionNumber" />
<result column="total_money" property="totalMoney" />
<result column="practical_money" property="practicalMoney" />
<result column="phone" property="phone" />
<result column="pay_date" property="payDate" />
<result column="order_status" property="orderStatus" />
<result column="pay_status" property="payStatus" />
<result column="pay_way" property="payWay" />
<result column="is_refund" property="isRefund" />
<association property="student" javaType="com.yida.data.common.core.entity.consume.EduConsumeOrderStudent">
<id column="order_student_id" property="id" />
<id column="student_id" property="studentId" />
<result column="student_name" property="studentName" />
<result column="student_number" property="studentNumber" />
<result column="student_family_type" property="studentFamilyType" />
<result column="student_parent_type" property="studentParentType" />
<result column="school_id" property="schoolId" />
<result column="school_name" property="schoolName" />
<result column="campus_id" property="campusId" />
<result column="campus_name" property="campusName" />
<result column="section_id" property="sectionId" />
<result column="section_name" property="sectionName" />
<result column="grade_id" property="gradeId" />
<result column="grade_name" property="gradeName" />
<result column="class_id" property="classId" />
<result column="class_name" property="className" />
</association>
</resultMap>
<!-- 消费订单后台列表分页查询 -->
<select id="listConsumeOrderPage" resultMap="consumeOrderMap">
SELECT
o.*,
s.*,
s.id as order_student_id
FROM
edu_consume_order o
LEFT JOIN edu_consume_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
AND o.dept_id IN
<foreach collection="schoolIds" open="(" separator="," close=")" item="schoolId">
#{schoolId}
</foreach>
<if test='dto.orderCode != null and dto.orderCode != ""'>
AND o.order_code LIKE CONCAT( '%', #{dto.orderCode}, '%' )
</if>
<if test='dto.orderStatus != null and dto.orderStatus != ""'>
AND o.order_status = #{dto.orderStatus}
</if>
<if test='dto.searchData != null and dto.searchData != ""'>
AND (
s.student_name LIKE CONCAT( '%', #{dto.searchData}, '%' )
or s.stu_card_number LIKE CONCAT( '%', #{dto.searchData}, '%' )
)
</if>
order by
o.create_date desc
</select>
</mapper>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.device.consume.mapper.EduConsumeOrderRefundMapper">
</mapper>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.device.consume.mapper.EduConsumeOrderStudentMapper">
</mapper>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.device.consume.mapper.EduConsumeRecordMapper">
<!-- 前端查询学生消费记录列表 -->
<select id="listH5ConsumeRecordPage"
resultType="com.yida.data.device.vo.consume.H5ConsumeRecordPageVO">
SELECT
*
FROM
edu_consume_record
WHERE
student_id = #{dto.studentId}
AND school_id = #{dto.deptId}
ORDER BY
create_date DESC
</select>
</mapper>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.device.consume.mapper.EduStudentConsumeCardMapper">
</mapper>