太空舱开门动作cmd 生成

This commit is contained in:
qjq
2024-11-04 15:41:48 +08:00
parent 215af32d9e
commit 9f46db9565
14 changed files with 276 additions and 17 deletions

View File

@ -118,11 +118,13 @@ public interface ErrorCodeConstants {
ErrorCode STORE_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_007_904_006,"商品订单详情不存在");
//========== 用户余额明细 1-004-014-000 =============
ErrorCode SPACE_CAPSULE_NOT_EXISTS = new ErrorCode(1_004_014_001, "太空舱不存在");
ErrorCode SPACE_CAPSULE_NOT_FAULT = new ErrorCode(1_004_014_002, "太空舱故障,暂时不能使用");
//========== 用户余额明细 1-004-015-000 =============
ErrorCode COMBO_NOT_EXISTS = new ErrorCode(1_004_015_001, "套餐不存在");
//========== 用户余额明细 1-004-016-000 =============
ErrorCode ORDER_SPACE_CAPSULE_NOT_EXISTS = new ErrorCode(1_004_016_001, "太空舱订单不存在");
ErrorCode ORDER_SPACE_CAPSULE_ERREO = new ErrorCode(1_004_016_002, "太空舱订单状态非法");
ErrorCode ORDER_SPACE_CAPSULE_CLOSE = new ErrorCode(1_004_016_003, "太空舱订单已结束,不可再开门");
ErrorCode STORE_BUSINESS_NOT_EXISTS = new ErrorCode(1_004_017_001, "超市营业统计不存在");

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Schema(description = "小程序 - 太空舱管理员 vo")
@Data
public class OrderSpaceCapsuleAdminVo {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23511")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "太空舱支付编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotBlank(message = "太空舱支付编码不能为空")
private String zfCode;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Schema(description = "小程序 - 太空舱订单操作")
@Data
public class OrderSpaceCapsuleOperateVo {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23511")
@NotNull(message = "太空舱订单编号不能为空")
private Long id;
@Schema(description = "太空舱支付编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotBlank(message = "太空舱支付编码不能为空")
private String zfCode;
}

View File

@ -72,4 +72,15 @@ public class OrderSpaceCapsulePageReqVO extends PageParam {
*/
@Schema(description = "退款金额")
private BigDecimal refundMoney;
@Schema(description = "门店名称")
private String carteenName;
@Schema(description = "cmd 执行命令")
private String cmd;
@Schema(description = "二维码,base64")
private String qrCode;
@Schema(description = "支付编号")
private Integer payNum;
@Schema(description = "机器编号")
private String machineNum;
}

View File

@ -31,6 +31,9 @@ public class OrderSpaceCapsuleRespVO {
@Schema(description = "门店id", requiredMode = Schema.RequiredMode.REQUIRED, example = "5246")
@ExcelProperty("门店id")
private Long carteenId;
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "5246")
@ExcelProperty("门店名称")
private String carteenName;
@Schema(description = "0未使用1使用中2已完成3已退款", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("0未使用1使用中2已完成3已退款")
@ -87,4 +90,13 @@ public class OrderSpaceCapsuleRespVO {
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("退款金额")
private BigDecimal refundMoney;
@Schema(description = "cmd 执行命令")
private String cmd;
@Schema(description = "二维码,base64")
private String qrCode;
@Schema(description = "支付编号")
private Integer payNum;
@Schema(description = "机器编号")
private String machineNum;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo;
import cn.hutool.core.date.DatePattern;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
@ -74,4 +75,15 @@ public class OrderSpaceCapsuleSaveReqVO {
*/
@Schema(description = "退款金额")
private BigDecimal refundMoney;
@Schema(description = "门店名称")
private String carteenName;
@Schema(description = "cmd 执行命令")
private String cmd;
@Schema(description = "二维码,base64")
private String qrCode;
@Schema(description = "支付编号")
private Integer payNum;
@Schema(description = "机器编号")
private String machineNum;
}

View File

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "小程序 - 调用第三方 req vo")
@Data
public class SpaceCapsuleThreePointsReqVo {
private String UUID;
private Integer device_id;
private Long charge_id;
private Integer minute;//如果需要按秒的可换参数second;如果minute和second都传0则为中断通电
}

View File

@ -3,9 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.orderspacecapsule;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsulePageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsuleRespVO;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsuleSaveReqVO;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.orderspacecapsule.OrderSpaceCapsuleDO;
import cn.iocoder.yudao.module.member.service.orderspacecapsule.OrderSpaceCapsuleService;
import io.swagger.v3.oas.annotations.Operation;
@ -64,7 +62,16 @@ public class AppOrderSpaceCapsuleController {
PageResult<OrderSpaceCapsuleDO> pageResult = orderSpaceCapsuleService.getOrderSpaceCapsulePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, OrderSpaceCapsuleRespVO.class));
}
@PostMapping("/open/cmd")
@Operation(summary = "生成太空舱cmd")
public CommonResult<OrderSpaceCapsuleRespVO> getOpenCmd(@Valid @RequestBody OrderSpaceCapsuleOperateVo operateVo) {
OrderSpaceCapsuleDO orderSpaceCapsuleDO = orderSpaceCapsuleService.openDoor(operateVo);
return success(BeanUtils.toBean(orderSpaceCapsuleDO, OrderSpaceCapsuleRespVO.class));
}
@PostMapping("/open/cmd/admin")
@Operation(summary = "超级管理员跳过订单验证.打开太空舱")
public CommonResult<OrderSpaceCapsuleRespVO> getCmdAdmin(@Valid @RequestBody OrderSpaceCapsuleAdminVo adminVo) {
OrderSpaceCapsuleDO orderSpaceCapsuleDO = orderSpaceCapsuleService.openCmdAdmin(adminVo);
return success(BeanUtils.toBean(orderSpaceCapsuleDO, OrderSpaceCapsuleRespVO.class));
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.member.dal.dataobject.orderspacecapsule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.math.BigDecimal;
@ -93,5 +94,12 @@ public class OrderSpaceCapsuleDO extends BaseDO {
* 退款金额
*/
private BigDecimal refundMoney;
/**
* 门店名称
*/
private String carteenName;
private String cmd;
private String qrCode;
private Integer payNum;
private String machineNum;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.member.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum SpaceCapsuleOperateEnum {
SPACE_CAPSULE_OPERATE_SWEEP_IT(0,"扫一扫"),
SPACE_CAPSULE_OPERATE_BLUETOOTH(1,"蓝牙"),
SPACE_CAPSULE_OPERATE_QR_CODE(2,"二维码");
/**
* 编码
*/
private final Integer code;
/**
* 类型
*/
private final String name;
}

View File

@ -1,9 +1,12 @@
package cn.iocoder.yudao.module.member.service.orderspacecapsule;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsuleAdminVo;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsuleOperateVo;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsulePageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsuleSaveReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.orderspacecapsule.OrderSpaceCapsuleDO;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.*;
@ -52,4 +55,16 @@ public interface OrderSpaceCapsuleService {
*/
PageResult<OrderSpaceCapsuleDO> getOrderSpaceCapsulePage(OrderSpaceCapsulePageReqVO pageReqVO);
/**
* 太空舱开门动作
* @param operateVo
*/
OrderSpaceCapsuleDO openDoor(@Valid OrderSpaceCapsuleOperateVo operateVo);
/**
* 超级管理员 不限时间
* @param adminVo
* @return
*/
OrderSpaceCapsuleDO openCmdAdmin(@Valid @RequestBody OrderSpaceCapsuleAdminVo adminVo);
}

View File

@ -1,32 +1,47 @@
package cn.iocoder.yudao.module.member.service.orderspacecapsule;
import cn.hutool.core.lang.UUID;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsulePageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.OrderSpaceCapsuleSaveReqVO;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.member.controller.admin.orderspacecapsule.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.orderspacecapsule.OrderSpaceCapsuleDO;
import cn.iocoder.yudao.module.member.dal.dataobject.spacecapsule.SpaceCapsuleDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.orderspacecapsule.OrderSpaceCapsuleMapper;
import cn.iocoder.yudao.module.member.enums.CostTypeEnum;
import cn.iocoder.yudao.module.member.enums.PayMethodsEnum;
import cn.iocoder.yudao.module.member.enums.SpaceCapsuleEnum;
import cn.iocoder.yudao.module.member.enums.SpaceCapsuleOrderEnum;
import cn.iocoder.yudao.module.member.enums.*;
import cn.iocoder.yudao.module.member.service.amount.DeductionService;
import cn.iocoder.yudao.module.member.service.carteenmoney.CarteenMoneyService;
import cn.iocoder.yudao.module.member.service.spacecapsule.SpaceCapsuleService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.system.api.carteen.CarteenApi;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.validation.Valid;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import org.springframework.web.bind.annotation.RequestBody;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ORDER_SPACE_CAPSULE_ERREO;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ORDER_SPACE_CAPSULE_NOT_EXISTS;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
/**
* 太空舱订单 Service 实现类
@ -45,7 +60,9 @@ public class OrderSpaceCapsuleServiceImpl implements OrderSpaceCapsuleService {
private SpaceCapsuleService spaceCapsuleService;
@Resource
private MemberUserService userService;
@Resource
private CarteenApi carteenApi;
private static final String URL="https://gateway.biandianxia.com/encrypt/sharedevice";
@Override
@Transactional(rollbackFor = Exception.class)
public Long createOrderSpaceCapsule(OrderSpaceCapsuleSaveReqVO createReqVO) {
@ -70,6 +87,9 @@ public class OrderSpaceCapsuleServiceImpl implements OrderSpaceCapsuleService {
orderSpaceCapsule.setEndMoney(initialMoney.subtract(orderSpaceCapsule.getMoney()));
// 设置支付方式
orderSpaceCapsule.setPayMethods(PayMethodsEnum.WX_LITE.getName());
//设置门店名称
String storesName = carteenApi.getCarteenById(orderSpaceCapsule.getCarteenId()).getStoresName();
orderSpaceCapsule.setCarteenName(storesName);
// 插入订单数据
orderSpaceCapsuleMapper.insert(orderSpaceCapsule);
// 返回订单 ID
@ -139,7 +159,7 @@ public class OrderSpaceCapsuleServiceImpl implements OrderSpaceCapsuleService {
long minutesUsed = Duration.between(orderStartTime, now).toMinutes();
int remainingMinutes = Math.toIntExact(comboMinutes - minutesUsed);
// 计算每分钟的价格
BigDecimal pricePerMinute = comboPrice.divide(BigDecimal.valueOf(comboMinutes), 2, RoundingMode.HALF_UP);
BigDecimal pricePerMinute = comboPrice.divide(BigDecimal.valueOf(comboMinutes), 2, RoundingMode.HALF_UP);
// 计算剩余价格并向下取整
return pricePerMinute.multiply(BigDecimal.valueOf(remainingMinutes)).setScale(0, RoundingMode.FLOOR);
}
@ -174,5 +194,95 @@ public class OrderSpaceCapsuleServiceImpl implements OrderSpaceCapsuleService {
public PageResult<OrderSpaceCapsuleDO> getOrderSpaceCapsulePage(OrderSpaceCapsulePageReqVO pageReqVO) {
return orderSpaceCapsuleMapper.selectPage(pageReqVO);
}
@Override
public OrderSpaceCapsuleDO openDoor(OrderSpaceCapsuleOperateVo operateVo) {
Long id = operateVo.getId();
String zfCode = operateVo.getZfCode();
SpaceCapsuleDO payNum = spaceCapsuleService.getPayNum(zfCode);
validateSpaceCapsuleStatus(payNum);
OrderSpaceCapsuleDO orderSpaceCapsuleDO = orderSpaceCapsuleMapper.selectById(id);
validateOrderStatus(orderSpaceCapsuleDO);
if (isFirstOpening(orderSpaceCapsuleDO, payNum)) {
handleFirstOpening(orderSpaceCapsuleDO, payNum);
}
orderSpaceCapsuleDO.setPayNum(payNum.getPayNum());
orderSpaceCapsuleDO.setMachineNum(payNum.getMachineNum());
orderSpaceCapsuleMapper.updateById(orderSpaceCapsuleDO);
return orderSpaceCapsuleDO;
}
@Override
public OrderSpaceCapsuleDO openCmdAdmin(OrderSpaceCapsuleAdminVo adminVo) {
MemberUserDO user = userService.getUser(adminVo.getUserId());
SpaceCapsuleDO payNum = spaceCapsuleService.getPayNum(adminVo.getZfCode());
OrderSpaceCapsuleDO capsuleDO=new OrderSpaceCapsuleDO();
capsuleDO.setComboNum(9999);
capsuleDO.setComboMinutes(9999);
handleFirstOpening(capsuleDO,payNum);
return capsuleDO;
}
private void validateSpaceCapsuleStatus(SpaceCapsuleDO payNum) {
if (payNum.getStatus().equals(SpaceCapsuleEnum.SPACE_CAPSULE_ENUM_FAULT.getCode())) {
throw exception(SPACE_CAPSULE_NOT_FAULT);
}
}
private void validateOrderStatus(OrderSpaceCapsuleDO orderSpaceCapsuleDO) {
Integer status = orderSpaceCapsuleDO.getStatus();
if (status.equals(SpaceCapsuleOrderEnum.SPACE_CAPSULE_ORDER_ENUM_REFUNDED.getCode()) ||
status.equals(SpaceCapsuleOrderEnum.SPACE_CAPSULE_ORDER_ENUM_DONE.getCode())) {
throw exception(ORDER_SPACE_CAPSULE_CLOSE);
}
}
private boolean isFirstOpening(OrderSpaceCapsuleDO orderSpaceCapsuleDO, SpaceCapsuleDO payNum) {
return orderSpaceCapsuleDO.getStatus().equals(SpaceCapsuleOrderEnum.SPACE_CAPSULE_ORDER_ENUM_UNUSED.getCode()) &&
payNum.getStatus().equals(SpaceCapsuleEnum.SPACE_CAPSULE_ENUM_FREE_TIME.getCode());
}
private void handleFirstOpening(OrderSpaceCapsuleDO orderSpaceCapsuleDO, SpaceCapsuleDO payNum) {
SpaceCapsuleThreePointsReqVo reqVo = new SpaceCapsuleThreePointsReqVo();
reqVo.setUUID(payNum.getMachineNum());
reqVo.setCharge_id(System.currentTimeMillis() / 1000);
reqVo.setDevice_id(payNum.getPayNum());
int minute = orderSpaceCapsuleDO.getComboMinutes() * orderSpaceCapsuleDO.getComboNum();
reqVo.setMinute(minute);
String body = HttpRequest.post(URL)
.body(JSONUtil.toJsonStr(reqVo))
.execute().body();
JSONObject jsonObject = JSONUtil.parseObj(body);
if (jsonObject.getInt("status") != 1) {
throw exception(new ErrorCode(1_004_016_004, jsonObject.getStr("error")));
}
String cmd = jsonObject.getStr("cmd");
orderSpaceCapsuleDO.setCmd(cmd);
String qrCode = createQrCode("~" + cmd + "~");
if (qrCode != null) {
orderSpaceCapsuleDO.setQrCode(qrCode);
}
}
public static String createQrCode(String content){
// 生成二维码,指定大小
BufferedImage qrImage = QrCodeUtil.generate(content, 300, 300);
// 转换为 Base64
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(qrImage, "png", baos);
byte[] imageBytes = baos.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -53,4 +53,10 @@ public interface SpaceCapsuleService {
*/
PageResult<SpaceCapsuleDO> getSpaceCapsulePage(SpaceCapsulePageReqVO pageReqVO);
/**
* 支付编码查询
* @param payNum
* @return
*/
SpaceCapsuleDO getPayNum(String payNum);
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.member.service.spacecapsule;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.controller.admin.spacecapsule.vo.SpaceCapsulePageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.spacecapsule.vo.SpaceCapsuleSaveReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.spacecapsule.SpaceCapsuleDO;
@ -73,4 +74,10 @@ public class SpaceCapsuleServiceImpl implements SpaceCapsuleService {
return spaceCapsuleMapper.selectPage(pageReqVO);
}
@Override
public SpaceCapsuleDO getPayNum(String payNum) {
return spaceCapsuleMapper.selectOne(new LambdaQueryWrapperX<SpaceCapsuleDO>()
.eq(SpaceCapsuleDO::getPayNum,payNum).last(" limit 1"));
}
}