问:介绍一下你做个实习项目吧?
我的实习项目呢,他是基于微服务框架体系的物流项目中,主要负责人,货,车三者之间的调度关系。主要的黄金链路就是用户下单 -> 快递员揽收->通过一系列的调度完成商品运单的运输->再到快递员派送商品->用户签收的整个流程。主要的模块主要就是调度模块,通过调度模块来异步的调度其他模块,包括运单模块,订单模块,路线规划模块等等。
问:讲讲用户支付流程吧?(应届生不要讲该模块,支付涉及的问题太多了,讲出来也很假。涉及的表:交易单表,退款单表,渠道表)
在用户下单前主要就是填写,起点和终点的地址,及快递员取件时间(先保存在前端)。在下单(此时还未付款)后会就会发送一次消息到调度执行,调度中心发送对应的延迟消息到快递员服务找到对应的快递快递员进行取件,在快递员取件后会计算对应的体积和重量,此时我们需要计算出对应的快递费用,我们主要根据用户填写省/市匹配对应的计费模板,模板主要就是包括,同城寄,省内寄,经济区互寄,配合模板计算出费用,最终展示给前端。用户点击支付,就会生成订单数据并调用easySDK生成对应的字符二维码。在这个过程中,我们需要考虑支付的幂等性,防止用户多次支付问题,最常见的解决方法就是使用交易单唯一ID来做判断,但是,在这个业务场景中我们还需要考虑用户更换支付方式的问题,更换支付方式时交易单ID也是一样的。所以我们这里的解决方案就是使用分布式锁+判断订单状态来实现的。我们使用redisson实现分布式锁锁住订单id,并判断订单的状态,如果是已支付就直接报错,如果是支付中,我们就要判断支付方式是否发生改变,如果改变就重新生成交易ID,否则报错。如果是取消订单的话修改交易单状态。
用户完成支付后,会调用回调函数发送订单数据到调度中心,修改订单的支付状态。我们orderId主要就是通过雪花算法生成的。这边需要考虑的就是网络波动得问题,网络波动就可能不会调用回调函数。所以我们会有一个兜底策略。主要就是使用定时任务定时查看支付状态在发送并修改订单状态和发送消息。哦对了,这边还做了个小小的优化,最开始的时候我们生成二维码直接通过hutool来生成的,但是呢,在后续进行测试的时候,当吞吐量表较高的时候,生成二维码的效率明显很低,那我不如直接将生成二维码的操作交给客户端,通过前端来生成二维码,主要就是通过QRCode.js来实现的,效率上明显就提高了。
我们支付模块中主要用两种支付方式,但是呢在后续可能会增加其他的饿支付方式,所以我们将这个做了个支付中台。主要就是通过自定义注解+工厂模式+ioc+反射实现支付模板切换。我给您介绍一下大概的流程,您看行吗?
不同的支付类都会实现一个工厂接口,支付类的主要方法就是支付,退款等等。都会配置到ioc中,支付模板表主要就是支付标签,appId,密钥,私钥,商户id等等。调对应的工厂类就会通过反射获取ioc中的所有的实现支付类(主要就是提高hutool.getBean(.class)来实现的),通过自定义注解的支付标签进行匹配返回对应的支付类。
问:如果用户下单的是到付的话,是怎么实现的呢?
我们会在用户下单的时候发送取件消息,在快递员取件成功后,直接发送消息生成运单,完成对应的调度后,在快递员完成派送且用户签收前生成对应的订单数据,最终生成支付二维码完成支付操作。
问:你们这个地图状态是怎么匹配出负责网点的呢?
用户会提供起点和终点,且会选择对应的省,市,区。我们通过调用高德地图接口计算出对应的经纬度。服务网点的作用范围我们使用Mongdb进行存储的,主要就是通过经纬度集合做交集来判断网点的负责范围。最终返回对应的负责网点id,如果没有找到就直接报错。
问:退款是怎么做的呢?
有支付的话,肯定就需要退款的业务,退款对应一张退款表,退款表的主要字段就订单idÿ