微信点餐系统

模板消息推送

一、微信推送模板消息

1、首先需要在公众号中添加消息模板,记住在白名单添加IP:

image

2、代码实现,使用第三方SDK
@Service
@Slf4j
public class PushMessageServiceImpl implements PushMessageService{
    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private WechatAccountConfig accountConfig;

    @Override
    public void orderStatus(OrderDTO orderDTO) {
        WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
        //设置模板id
        templateMessage.setTemplateId(accountConfig.getTemplateId().get("orderStatus"));
        templateMessage.setToUser(orderDTO.getBuyerOpenid());//opneid
        List<WxMpTemplateData> data = Arrays.asList(new WxMpTemplateData(
                "first","亲,记得收货"),
                new WxMpTemplateData("keyword1","微信点餐"),
                new WxMpTemplateData("keyword2","18766666666"),
                new WxMpTemplateData("keyword3",orderDTO.getOrderId()),
                new WxMpTemplateData("keyword4",orderDTO.getOrderStatusEnum().getMessage()),

                new WxMpTemplateData("keyword5","¥"+orderDTO.getOrderAmount()),
                new WxMpTemplateData("remark","欢迎再次光临"));
        templateMessage.setData(data);
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (WxErrorException e) {
            e.printStackTrace();
            log.error("【微信模板消息推送】{}",e);
        }
    }
}



3、然后在其他业务代码中选择推送模板消息,在此项目中选择在完结订单时推送:
    @Override
    @Transactional
    public OrderDTO finish(OrderDTO orderDTO) {

        //判断订单状态
        if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【完结订单】,订单状态不正确 orderId={},orderStatus={}",orderDTO.getOrderId(),orderDTO.getOrderStatus());
            throw new SellException(ResultEums.ORDER_STATUS_ERROR);
        }

        //修改订单状态
        OrderMaster orderMaster = new OrderMaster();
        orderDTO.setOrderStatus(OrderStatusEnum.FINISH.getCode());
        BeanUtils.copyProperties(orderDTO,orderMaster);

        OrderMaster result = orderMasterRepository.save(orderMaster);
        if (result==null) {
            log.error("【完结订单】订单状态更新失败 orderId={},orderStatus={}",orderMaster.getOrderId(),orderMaster.getOrderStatus());
        }

        //推送模板消息
        pushMessageService.orderStatus(orderDTO);
        return orderDTO;
    }


    注意:在推送模板消息中,如果模板消息推送失败,只是捕获异常,没有抛出,因为推送模板消息与其他业务相比,并不算是多重要的功能,就是推送失败,也是可以接受的范围之内,不能影响其他的业务实现。

二、webSocket实现消息提醒

1、前台页面的处理:在订单列表页面,当有新的订单生成的弹窗提醒,并伴有提示音
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<html>
<#include "../common/head.ftl">
<body>
<div id="wrapper" class="toggled">
<#-- 边栏-->
<#include "../common/nav.ftl">

<#--主要内容-->
<div id="page-content-wrapper">
....
</div>




<!--弹窗-->
<div class="modal fade" id="myModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">
提醒
</h4>
</div>
<div class="modal-body">
您有新的订单
</div>
<div class="modal-footer">
<!--点击关闭,关闭音乐播放-->
<button onclick="javascript:document.getElementById('notice').pause()" type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button onclick="location.reload()" type="button" class="btn btn-primary">查看新的订单</button>
</div>
</div>

</div>

</div>
<#--b播放音乐-->
<audio id="notice" loop="loop">
<source src="/sell/mp3.notify.mp3" >
</audio>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<!--websocket-->
<script>
var websocket = null;
if ('WebSocket' in window) {
websocket = new WebSocket('ws://wxorder.natapp1.cc/sell/webSocket');

}else {
alert('该浏览器不支持webSocket!');
}
websocket.onopen = function (event) {
console.log('建立连接');
}

websocket.onclose = function (event) {
console.log('连接关闭');
}

websocket.onmessage = function (event) {
console.log('收到消息'+event.data);
//弹出提醒,播放音乐
$('#myModal').modal('show');
document.getElementById('notice').play();


}
window.onbeforeunload = function () {
websocket.close();
}
</script>
</body>
</html>
2、后台消息的发送:

配置:
@Component
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}


@Component
@ServerEndpoint("/webSocket")
@Slf4j
public class WebSocket {
    private Session session;

    private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);

        log.info("【websocket消息】有新的连接,总数:{}",webSocketSet.size());
    }

    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        log.info("【webSocket消息】 连接断开,总数:{}",webSocketSet.size());
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("【websocket消息】 收到客户端发来的消息",message);
    }

    public void sendMessage(String message) {
        for (WebSocket webSocket:webSocketSet) {
            log.info("【websocket消息】 广播消息,message={}",message);
            try {
                webSocket.session.getBasicRemote().sendText(message);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}




3、在创建订单时发送消息:
  @Override
@Transactional
public OrderDTO create(OrderDTO orderDTO) {

    String orderId = KeyUtils.genUniqueKey();
    BigDecimal ordrAmount = new BigDecimal(BigInteger.ZERO);
    //查询商品,从前台传来得OrderDTO中获取商品详细列表,遍历列表得中得所有OrderDetail,
    for (OrderDetail orderDetail:orderDTO.getOrderDetailList()) {
        //计算订单总价:(1)、从orderDetail中获取商品Id,查出商品信息,主要是为了获取ProducePrie和ProductQuantity
        ProductInfo productInfo = productInfoService.findOne(orderDetail.getProductId());
        if (productInfo==null) {
            throw new SellException(ResultEums.PRODUCT_NOT_EXIST);
        }
        //(2)、根据获取得到得ProducePrie和ProductQuantity计算商品总价ordrAmount
        ordrAmount = productInfo.getProductPrice().multiply(new BigDecimal(orderDetail.getProductQuantity()))
                .add(ordrAmount);

        //订单详情入库:要将从数据库中查出得productInfo复制到orderDetail,productInfo必须从数据库获取,
        // 并且设置detailId与orderId

        BeanUtils.copyProperties(productInfo,orderDetail);
        orderDetail.setDetailId(KeyUtils.genUniqueKey());
        orderDetail.setOrderId(orderId);

        orderDetailRepository.save(orderDetail);
    }
    //写入订单数据库:将订单信息,即OrderMaster信息入库,要将OrderDTO中的信息复制到OrderMaster对象中
    // ,同时设置orderId,总金额ordrAmount,支付状态,订单状态,并保存入库
    OrderMaster orderMaster = new OrderMaster();
    orderDTO.setOrderId(orderId);
    BeanUtils.copyProperties(orderDTO,orderMaster);
    orderMaster.setOrderAmount(ordrAmount);
    orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode());
    orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
    orderMasterRepository.save(orderMaster);

    //扣库存
    List<Cart> cartList = orderDTO.getOrderDetailList().stream()
            .map(e ->new Cart(e.getProductId(),e.getProductQuantity()))
            .collect(Collectors.toList());
    productInfoService.decreStock(cartList);


    //发送websocket消息
    webSocket.sendMessage(orderDTO.getOrderId());
    return orderDTO;
}
文章目录
  1. 1. 一、微信推送模板消息
  2. 2. 二、webSocket实现消息提醒