Browse Source

Merge branch 'dev' of http://gogs.gzzzyd.com/pangqijun/vending-machine-api into dev

pangqijun 7 months ago
parent
commit
2385937f2c

+ 15 - 0
src/main/java/org/springblade/common/aspect/VendingFlag.java

@@ -0,0 +1,15 @@
+package org.springblade.common.aspect;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * redis锁
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface VendingFlag {
+
+}

+ 112 - 0
src/main/java/org/springblade/common/aspect/VendingFlagAspect.java

@@ -0,0 +1,112 @@
+package org.springblade.common.aspect;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.http.ContentType;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springblade.common.utils.RedisTool;
+import org.springblade.modules.api.response.VendingOrderRes;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 设备调用接口限流
+ */
+@Aspect
+@Component
+@Slf4j
+public class VendingFlagAspect {
+
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private HttpServletResponse response;
+    @Resource
+    private RedisTool redisTool;
+
+    @Around("@annotation(org.springblade.common.aspect.VendingFlag)")
+    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
+        //获取请求路径
+        String requestURI = request.getRequestURI();
+        //获取请求参数
+        JSONObject reqParam = this.readReqParam(request);
+        String machine_id =  reqParam.get("machine_id").toString();
+        if (Objects.isNull(machine_id)) {
+            return joinPoint.proceed();
+        } else {
+            boolean redisLock = redisTool.getRedisLock(machine_id + ":" + requestURI, "1");
+            if (!redisLock) {
+                VendingOrderRes vendingOrderRes = new VendingOrderRes();
+                vendingOrderRes.setMachine_id(machine_id);
+                vendingOrderRes.setSaleSn("");
+                vendingOrderRes.setChannelNum("0");
+                vendingOrderRes.setSaledata(new HashMap<>());
+                this.notifyReturn(response, vendingOrderRes);
+                log.info("设备:" + machine_id + "请求接口:" + requestURI + "被限流!");
+                return response;
+            }
+            Object proceed;//请求过程
+            try {
+                proceed = joinPoint.proceed();
+            } finally {
+                //移除redis标识
+                redisTool.unRedisLock(machine_id + ":" + requestURI);
+            }
+            return proceed;
+        }
+
+    }
+
+    private JSONObject readReqParam(HttpServletRequest request) {
+        BufferedReader br = null;
+        StringBuilder sb = new StringBuilder("");
+        try {
+            br = request.getReader();
+            String str;
+            while ((str = br.readLine()) != null) {
+                sb.append(str);
+            }
+            br.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (null != br) {
+                try {
+                    br.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        JSONObject jsonObject = JSONUtil.parseObj(sb.toString());
+        return jsonObject;
+    }
+
+
+    /**
+     * 硬件接口通用响应
+     *
+     * @param response        HttpServletResponse
+     * @param vendingOrderRes 返值
+     */
+    private void notifyReturn(HttpServletResponse response, VendingOrderRes vendingOrderRes) throws IOException {
+        Map<String, Object> map = BeanUtil.beanToMap(vendingOrderRes);
+        response.setHeader("Content-type", ContentType.JSON.toString());
+        response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
+        response.flushBuffer();
+    }
+
+}

+ 11 - 5
src/main/java/org/springblade/modules/api/controller/ApiGoodsController.java

@@ -16,7 +16,9 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import org.springblade.common.constant.CommonConstant;
-import org.springblade.common.enums.*;
+import org.springblade.common.enums.AuditStatusEnum;
+import org.springblade.common.enums.GoodsStateEnum;
+import org.springblade.common.enums.YesOrNoEnum;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
@@ -29,13 +31,14 @@ import org.springblade.modules.mall.entity.CategoryInfo;
 import org.springblade.modules.mall.entity.GoodsInfo;
 import org.springblade.modules.mall.service.ICategoryInfoService;
 import org.springblade.modules.mall.service.IGoodsInfoService;
-import org.springblade.modules.mall.service.IGoodsParamsService;
 import org.springblade.modules.mall.vo.GoodsInfoVO;
 import org.springblade.modules.mall.wrapper.GoodsInfoWrapper;
 import org.springframework.util.Assert;
-import org.springframework.web.bind.annotation.*;
+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;
 
-import javax.annotation.Resource;
 import java.util.List;
 
 /**
@@ -116,7 +119,10 @@ public class ApiGoodsController extends BladeController {
         FacilityCargoWay cargoWay = iFacilityCargoWayService.getById(goodsInfo.getCargoWayId());
         Assert.notNull(cargoWay, "未查询到货道信息");
         detail.setSalePrice(cargoWay.getSalePrice());
-        return R.data(GoodsInfoWrapper.build().entityVO(detail));
+        GoodsInfoVO goodsInfoVO = GoodsInfoWrapper.build().entityVO(detail);
+        goodsInfoVO.setCargoWayId(cargoWay.getId());
+        goodsInfoVO.setCargoWayNo(cargoWay.getCargoNo());
+        return R.data(goodsInfoVO);
     }
 
 }

+ 96 - 0
src/main/java/org/springblade/modules/api/controller/ApiVendingController.java

@@ -0,0 +1,96 @@
+package org.springblade.modules.api.controller;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.http.ContentType;
+import cn.hutool.json.JSONUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.common.aspect.VendingFlag;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.modules.api.request.VendingOrderReq;
+import org.springblade.modules.api.response.VendingOrderRes;
+import org.springblade.modules.api.service.VendingOrderService;
+import org.springblade.modules.finance.vo.OrderGoodsVO;
+import org.springblade.modules.finance.vo.OrderVO;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 售货机硬件对接接口
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping(CommonConstant.API_URL + "/vending")
+@Api(value = "售货机硬件对接接口", tags = "售货机硬件对接接口")
+public class ApiVendingController {
+
+    private final VendingOrderService vendingOrderService;
+
+
+    @VendingFlag
+    @ApiOperation(value = "查询订单信息", notes = "传入售货机编号")
+    @PostMapping("/getOrder")
+    public void getOrder(@Valid @RequestBody VendingOrderReq vendingOrderReq, HttpServletResponse response) throws IOException {
+        List<OrderGoodsVO> vendingOrderVOs = vendingOrderService.getVendingOrder(vendingOrderReq);
+
+        //封装返回
+        VendingOrderRes vendingOrderRes = new VendingOrderRes();
+        vendingOrderRes.setMachine_id(vendingOrderReq.getMachine_id());
+        if (CollectionUtil.isEmpty(vendingOrderVOs)) {
+            vendingOrderRes.setSaleSn("");
+            vendingOrderRes.setChannelNum("0");
+            vendingOrderRes.setSaledata(new HashMap<>());
+            this.notifyReturn(response, vendingOrderRes);
+        } else {
+            //一次只返回一个订单
+            //按订单分组
+            Map<Long, List<OrderGoodsVO>> vendingOrderGoodMap = vendingOrderVOs.stream().collect(Collectors.groupingBy(OrderGoodsVO::getOrderId));
+            OrderVO backOrder = vendingOrderService.getBackOrder(vendingOrderReq);
+            List<OrderGoodsVO> orderGoodsVOS = vendingOrderGoodMap.get(backOrder.getId());
+            vendingOrderRes.setSaleSn(backOrder.getId() + "");
+            vendingOrderRes.setChannelNum(orderGoodsVOS.size() + "");
+
+            Map<String, String> saledataMap = new HashMap<>();
+
+            //按货道分组
+            Map<String, List<OrderGoodsVO>> orderGoodsMap = orderGoodsVOS.stream().collect(Collectors.groupingBy(OrderGoodsVO::getCargoWayNo));
+            for (Map.Entry<String, List<OrderGoodsVO>> rderGoodsEntry : orderGoodsMap.entrySet()) {
+                saledataMap.put(rderGoodsEntry.getKey(), rderGoodsEntry.getValue().size() + "");
+            }
+
+            vendingOrderRes.setSaledata(saledataMap);
+            this.notifyReturn(response, vendingOrderRes);
+        }
+
+    }
+
+    @ApiOperation(value = "出货成功回调", notes = "出货成功回调")
+    @PostMapping("callback")
+    public void callback() {
+
+    }
+
+    /**
+     * 硬件接口通用响应
+     *
+     * @param response        HttpServletResponse
+     * @param vendingOrderRes 返值
+     */
+    private void notifyReturn(HttpServletResponse response, VendingOrderRes vendingOrderRes) throws IOException {
+        Map<String, Object> map = BeanUtil.beanToMap(vendingOrderRes);
+        response.setHeader("Content-type", ContentType.JSON.toString());
+        response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
+        response.flushBuffer();
+    }
+
+}

+ 18 - 0
src/main/java/org/springblade/modules/api/mapper/VendingOrderMapper.java

@@ -0,0 +1,18 @@
+package org.springblade.modules.api.mapper;
+
+import org.apache.ibatis.annotations.Param;
+import org.springblade.modules.api.request.VendingOrderReq;
+import org.springblade.modules.finance.vo.OrderGoodsVO;
+import org.springblade.modules.finance.vo.OrderVO;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface VendingOrderMapper {
+
+    List<OrderGoodsVO> getVendingOrder(@Param("param") VendingOrderReq vendingOrderReq);
+
+    public List<OrderVO>  getBackOrder(@Param("param")VendingOrderReq vendingOrderReq);
+
+}

+ 23 - 0
src/main/java/org/springblade/modules/api/mapper/VendingOrderMapper.xml

@@ -0,0 +1,23 @@
+<?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="org.springblade.modules.api.mapper.VendingOrderMapper">
+
+    <select id="getVendingOrder" resultType="org.springblade.modules.finance.vo.OrderGoodsVO">
+        select a.*
+        from t_order_goods a
+                 left join t_order b on a.order_id = b.id
+        where b.order_state = 2
+          and a.device_id = #{param.machine_id}
+        order by b.create_time asc
+    </select>
+
+    <select id="getBackOrder" resultType="org.springblade.modules.finance.vo.OrderVO">
+        select a.*
+        from t_order a
+                 left join t_order_goods b on a.id = b.order_id
+        where a.order_state = 2
+          and b.device_id = #{param.machine_id}
+        order by a.create_time asc
+    </select>
+
+</mapper>

+ 6 - 1
src/main/java/org/springblade/modules/api/request/SubmitOrderRequest.java

@@ -19,8 +19,8 @@ package org.springblade.modules.api.request;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import org.springblade.modules.mall.entity.GoodsInfo;
 
+import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 import java.util.List;
@@ -94,6 +94,11 @@ public class SubmitOrderRequest implements Serializable {
 	private Long shopId;
 
 	@ApiModelProperty(value = "货道id")
+	@NotNull(message = "货道id不能为空")
 	private Long cargoWayId;
 
+	@ApiModelProperty(value = "货道编号")
+	@NotBlank(message = "货道编号不能为空")
+	private String cargoWayNo;
+
 }

+ 20 - 0
src/main/java/org/springblade/modules/api/request/VendingOrderReq.java

@@ -0,0 +1,20 @@
+package org.springblade.modules.api.request;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ *
+ */
+@Data
+@ApiModel(value = "售货机获取订单请求参数", description = "售货机获取订单请求参数")
+public class VendingOrderReq {
+
+    @NotBlank(message = "机器id不能为空")
+    @ApiModelProperty(value = "机器id")
+    private String machine_id;
+
+}

+ 32 - 0
src/main/java/org/springblade/modules/api/response/VendingOrderRes.java

@@ -0,0 +1,32 @@
+package org.springblade.modules.api.response;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+@ApiModel(value = "售货机订单返回", description = "售货机订单返回")
+public class VendingOrderRes {
+
+//    machine_id=001;//机器码
+//    SaleSn=1234567890;//订单号
+//    ChannelNum=3;//出货的货道数量
+//    Saledata;//出货信息。Saledata后面跟着货道号和对应的数量,下面例子中1货道1个,3货道2个,6货道1个。
+//
+//    {"machine_id":"001","SaleSn":"1234567890","ChannelNum":"3","Saledata":{"1":"1","3":"2","6":"1"}}
+
+    @ApiModelProperty(value = "机器码")
+    private String machine_id;
+
+    @ApiModelProperty(value = "订单号")
+    private String SaleSn;
+
+    @ApiModelProperty(value = "出货的货道数量")
+    private String ChannelNum;
+
+    @ApiModelProperty(value = "出货信息")
+    private Map<String, String> Saledata;
+
+}

+ 20 - 0
src/main/java/org/springblade/modules/api/service/VendingOrderService.java

@@ -0,0 +1,20 @@
+package org.springblade.modules.api.service;
+
+
+import org.springblade.modules.api.request.VendingOrderReq;
+import org.springblade.modules.finance.vo.OrderGoodsVO;
+import org.springblade.modules.finance.vo.OrderVO;
+
+import java.util.List;
+
+/**
+ * 售货机调用服务(无实体)
+ */
+
+public interface VendingOrderService {
+
+    List<OrderGoodsVO> getVendingOrder(VendingOrderReq vendingOrderReq);
+
+    public OrderVO getBackOrder(VendingOrderReq vendingOrderReq);
+
+}

+ 39 - 0
src/main/java/org/springblade/modules/api/service/impl/VendingOrderServiceImpl.java

@@ -0,0 +1,39 @@
+package org.springblade.modules.api.service.impl;
+
+
+import org.springblade.modules.api.mapper.VendingOrderMapper;
+import org.springblade.modules.api.request.VendingOrderReq;
+import org.springblade.modules.api.service.VendingOrderService;
+import org.springblade.modules.finance.vo.OrderGoodsVO;
+import org.springblade.modules.finance.vo.OrderVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 售货机调用服务(无实体)
+ */
+@Service("vendingOrderServiceImpl")
+public class VendingOrderServiceImpl implements VendingOrderService {
+
+    @Autowired
+    private VendingOrderMapper vendingOrderMapper;
+
+    @Override
+    public List<OrderGoodsVO> getVendingOrder(VendingOrderReq vendingOrderReq) {
+        return vendingOrderMapper.getVendingOrder(vendingOrderReq);
+    }
+
+    /**
+     * 获取最远的未出货订单
+     *
+     * @param vendingOrderReq
+     * @return
+     */
+    @Override
+    public OrderVO getBackOrder(VendingOrderReq vendingOrderReq) {
+        List<OrderVO> backOrder = vendingOrderMapper.getBackOrder(vendingOrderReq);
+        return backOrder.get(0);
+    }
+}

+ 11 - 5
src/main/java/org/springblade/modules/finance/entity/OrderGoods.java

@@ -1,13 +1,14 @@
 package org.springblade.modules.finance.entity;
 
-import java.math.BigDecimal;
-import org.springblade.common.base.BaseEntity;
 import com.baomidou.mybatisplus.annotation.TableName;
-import java.time.LocalDateTime;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.common.base.BaseEntity;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
 
 /**
  * 商品订单表实体类
@@ -88,6 +89,11 @@ public class OrderGoods extends BaseEntity {
 	*/
 	@ApiModelProperty(value = "货道id")
 	private Long cargoWayId;
+	/**
+	 * 货道id
+	 */
+	@ApiModelProperty(value = "货道编号")
+	private String cargoWayNo;
 	/**
 	* 出货时间
 	*/

+ 1 - 0
src/main/java/org/springblade/modules/finance/service/impl/OrderGoodsServiceImpl.java

@@ -91,6 +91,7 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
 		orderGoods.setDeviceId(request.getDeviceId());
 		orderGoods.setGoodsName(goods.getGoodsName());
 		orderGoods.setCargoWayId(request.getCargoWayId());
+		orderGoods.setCargoWayNo(request.getCargoWayNo());
 		orderGoods.setGoodsNo(goods.getGoodsNo());
 		orderGoods.setGoodsImage(goods.getGoodsCover());
 		orderGoods.setGoodsId(request.getGoodsInfoId());

+ 1 - 0
src/main/resources/application.yml

@@ -272,6 +272,7 @@ blade:
       - /v1/article-detail
       - /v1/shop/all
       - /groupon/groupon/gen
+      - /v1/vending/**
     #授权认证配置
     auth:
       - method: ALL