微信小程序客户端登陆
一 总体流程
前段携带code发送请求给后端,后端利用微信小程序相关api解析这个code,获取能唯一认证登陆身份的openid。接着先到数据库查询是否有这个id,如果没有就保存用户信息实现注册,并返回token到前端,如果有就直接返回token到前端
二 前置准备
因为我们要用到微信相关api,所以我们需要用到微信的客户端。微信客户端需要我们微信小程序的id以及密钥,我们需要将他放到配置文件里面。
首先我们要设置好配置类和配置文件。
我们要在nacos中的设置关于微信小程序中的配置
然后设置配置类读取信息
再将微信小程序客户端注册到spring容器内
乘客端登录:获取登录用户信息接口
总体流程
web端从请求头获取token,先判断是否是登陆状态:如果redis有对应的数据就是登陆。远程调用,传入id,获取用户信息并返回。service根据远程调用传来的id查询数据库中乘客的信息并返回。
乘客端登录:登录校验
一 分析过程
1 如何判断是否登录状态?
-- 判断请求头里面是否包含token字符串
-- 根据token查询redis
2 如何实现?
-- 原始方式:在需要判断登录的controller进行上面判断(token和redis)
-- 如果使用原始方式,功能肯定可以实现的,但是造成有大量重复代码
-- 对这样方式进行优化
3 如何优化?
-- 使用 自定义注解+ aop 进行优化
二 具体实现
首先先创建一个注解,用于加在要登陆校验的方法上,实现登陆校验。然后创建一个切面类,去实现登陆校验:判断请求头是否有token,根据token查询redis是否存在。如果不存在就是没有登陆。如果存在就查询数据库,将用户的id存到threadlocal里面。
乘客端登录:获取微信手机号
因为我们是在微信小程序实现登陆的,我们是直接登陆,不需要去输入个人的信息,那么我们的个人信息来源于我们的微信。我们需要通过微信小程序解析一下微信传过来的相关参数来获取我们的用户信息。
在这里我们用微信小程序的api来解析微信传过来的code来获取微信的信息,获取电话号码,然后存到我们的数据库中
司机端登录与认证
总体流程
司机端登陆
和乘客端的很像,这里就直接赋值粘贴
获取登录司机信息
也是和乘客端很像,就cv了
腾讯云对象存储上传接口
1 主要概述
* 我们项目基于腾讯云对象存储服务COS,存储司机认证相关资料(身份证、驾驶证)
* 要使用腾讯云对象存储服务,首先进行开通,注册腾讯云之后,开通就可以了
* 使用对象存储服务,可以在控制台里面进行操作,也可以使用Java代码进行操作,这些操作,腾讯云官方提供详细文档说明,按照文档就方便进行操作
* 官方文档地址
https://cloud.tencent.com/document/product/436/10199
2 开发流程
当我们司机端点击开始接单的时候,我们会要求司机录取自己的个人信息。比如说身份证,驾驶证等。
我们乘客接收到这些图片的path之后,会将图片存储到腾讯云中,好方便我们后面利用腾讯云来实现验证照片合法性的功能。
我们web端接收到前端传来的文件本身和他的地址,将文件本身和他的地址作为参数远程调用service,然后service将他们存储到腾讯云cos存储桶里面
每上传一张照片就调用一次接口,接口一次只能上传一张照片
腾讯云身份证认证接口
1 需求
司机注册成功之后,应该引导他去做实名认证,这就需要用到腾讯云身份证识别和云存储功能了
2 流程
web端获取上传的文件之后远程调用service来验证上传的文件,这里也就是身份证。service端获取到身份证后调用腾讯的api来实现认证并返回认证的信息
腾讯云驾驶证识别接口
流程和上面一样的
获取司机的认证信息
1 需求分析
司机进行操作首先进行登录,登录成功之后,进行认证,跳转到认证页面完成认证
* **查看认证信息**,进入到认证页面时候,回显证件信息
2 具体实现
我们登陆校验会获取司机的id存到threadLocal中,我们可以获取司机id远程调用service获取司机认证信息。service根据id查询数据库,并且填充没有信息的字段
3 BUG:文件上传使用openfeign要加参数
bug:
feign 传 MultipartFile Error converting request body 序列化 错误
feign 传 MultipartFile Error converting request body 序列化 错误-CSDN博客
在请求注解中加入参数
修改司机认证信息
1 功能分析
**认证状态:**
0:未认证 【刚注册完为未认证状态】
1:审核中 【提交了认证信息后变为审核中】
2:认证通过 【后台审核通过】
-1:认证未通过【后台审核不通过】
* **第一次登录时候,完成用户注册,注册时候,当前认证状态值是0(未认证)**
* **上传认证信息(填写认证资料)之后,进行提交,提交之后,当前认证状态值1(审核中)**
* **司机端提交审核资料之后,后台管理员对提交资料进行审核,审核通过,认证状态值2,审核没有通过,认证状态值-1**
**司机开启接单的条件:**
1、登录
2、认证通过
3、建立了腾讯云人员库人员
4、当日验证了人脸识别
2 流程
就是前端将司机要修改的信息传到后端,后端做修改操作。
开通人脸识别
新注册的司机进行人脸信息采集,类似于在公司里面进行人脸录入,每天进行人脸打卡
实现思路
前端传入司机的id和司机人脸的图片到后端,后端创建一个人脸模型进人员库中管理.人员库要提前创建,并且将人员库的id在后端配置好,使用。
预估订单数据
预估驾驶线路
开发腾讯地图服务接口
* 封装地图服务接口:代驾路线距离,线路规划,时间
* 修改Nacos配置文件,修改腾讯位置服务key
实现思路
前端传开始代驾的经纬度和结束代驾的经纬度到后端,后端调用腾讯云的api计算最佳路线。
预估订单金额
乘客选择了出发和结束的地点,计算预估金额是多少,根据约定规则进行金额计算。
预估订单数据接口
前面计算了预估驾驶线路与预估订单金额,当前就可以编写web端乘客端预估订单数据接口了。
我们前端订单数据传入后端,后端进入web层。web的service调用预估驾驶线路与预估订单金额,获取预估订单的信息,实现预估订单的接口
乘客下单(一)
乘客下单时,我们拿到的订单费用都是预估费用,不是实际费用,因此下单时我们不插入账单信息,实际的账单信息是在代驾结束后产生的,实际的代驾里程会根据代驾过程中实时上传的金纬度计算获取,代驾过程中可能还要产生一些未知的费用,如:等时费、停车费、路桥费等。
主要实现:保存订单信息到数据库;查询订单状态,供前端轮训查到司机接单后跳转页面
保存订单信息
我们在司机结束订单之后会根据实际情况计算相应的金额,路线等信息,我们要先将这部分信息保存到数据库中
乘客端查询订单状态
乘客下完单后,订单状态为1,乘客端小程序会轮询订单状态,当订单状态为2时,说明已经有司机接单了,那么页面进行跳转,进行下一步操作
乘客下单(二)
前面我们创建了订单,但是略过了寻找附近适合接单的司机。接下来完善这部分功能
搜索附近司机
假设司机端的小程序实时把自己的GPS定位上传,然后定位信息缓存到Redis里面。咱们怎么能利用Redis计算出,上车点方圆几公里的司机都有谁呢?这就需要使用Redis的Geo功能。
既然Redis的GEO命令可以帮我们提取出某个坐标点指定距离以内的景点,如果Redis里面缓存的是司机的定位信息,那么我们用代驾单的起点坐标来查询附近几公里以内的司机,是不是也可以?而且Redis的Geo计算是在内存中完成的,比MySQL的Geo计算快了上千倍。
实现流程
司机开启接单服务后,司机端小程序就会实时上传经纬度信息到后端。后端将这些位置信息储存到redis的GEO。
关闭接单服务我们就要清空GEO数据,我们在web端定义一个删除的方法。供后续的api使用
获取司机个性化设置消息
司机针对接单,有一些个性化设置,只有满足了这些条件,才可以接单,如:“实时更新司机位置信息”,只有开启了接单服务,接口才可以更新数据
**说明:**
service_status:服务状态,司机开启了接单,才能进行接单后的一些列操作;
order_distance:订单程设置,如:order_distance=0(不限制);order_distance=50(只接代驾里程在50公里范围内的订单);
accept_distance:接单里程设置,司机起始点距离司机的位置,如:accept_distance=3(只接收3公里范围内的订单);
is_auto_accept:是否自动接单,开启后,系统自动抢单,不需要手动点接单按钮;
实现
定义一个接口,前端调用该接口。接口查询司机的个性化设置后返回给web。我们司机端web对上面搜索附近司机进行修改,获取了司机的个性化信息,判断司机是否接单。如果司机开始接单之后,才上传司机的位置信息
搜索附近适合接单的司机
需求
司机端的小程序开启接单服务后,开始实时上传司机的定位信息到redis的GEO缓存,前面乘客已经下单,现在乘客端就要查找附近适合接单的司机,如果有对应的司机,那就给司机发送新订单消息。
流程
乘客端通过对个性化信息的获取,来获取附近适合接单的司机
任务调度
前面乘客端已经下单了,附近的司机我们也能搜索了,接下来我们就要看怎么把这两件事给关联上?
乘客下单,搜索附近的司机,但是可能当时附近有司机,也有可能当时附近没有司机,乘客下单的一个等待时间为15分钟(15分钟后系统自动取消订单),那么下单与搜索司机怎么关联上呢?答案肯定是任务调度。
乘客下单了,然后启动一个任务调度,每隔1分钟执行一次搜索附近司机的任务调度,只要在15分钟内没有司机接单,那么就必须一直查找附近适合的司机,直到15分钟内有司机接单为止。
任务调度搜索到满足条件的司机后,会在服务器端给司机建立一个临时队列(1分钟过期),把新订单数据放入队列,司机小程序端开启接单服务后,每隔几秒轮询获取临时队列里面的新订单数据,在小程序前端进行语音播报,司机即可进行抢单操作。
流程
我们乘客下单,要搜索附近合适的司机。我们在dispatch服务中去做这些逻辑。
在乘客下单时,会请求我们的dispatch来开启调度服务。dispatch会判断该订单是否有调度服务。如果没有就用代码创建我们的任务。任务主要内容是查询附近合适的司机,将订单信息放在为每一个司机创建的一分钟临时的订单队列里面。
司机接单
1 需求
* 乘客下单之后,新订单信息已经在司机临时队列
* 下面司机可以开始进行接单了
首先,司机登录,认证(身份证、驾驶证、创建人脸模型)
第二,司机进行人脸识别(每天司机接单之前都需要进行人脸识别)
第三,司机开始接单了,更新司机接单状态
第四,当司机开始接单之后,删除司机之前存储到Redis里面位置信息
第五,当司机开始接单之后,清空司机临时队列新订单信息
判断司机在当日是否人脸识别
前端发请求给后端,后端在threadlocal中得到司机的id,查询数据库,返回司机在当日是否人脸识别的结果给前端
人脸识别接口
* 之前创建人脸识别模型,基于之前创建人脸模型完成当前识别功能。这个人脸模型是司机当时人脸输入的时候创建的。
前面我们已经做了人员库人员信息录入,现在我们要做人脸验证,为了防止司机作弊,我们还要对司机上传的人脸信息做人脸静态活体检测。
人脸静态活体检测可用于对用户上传的静态图片进行防翻拍活体检测,以判断是否是翻拍图片。
* 找到腾讯云文档1:照片比对
https://console.cloud.tencent.com/api/explorer?Product=iai&Version=2020-03-03&Action=VerifyFace
* 找到腾讯云文档2:人脸静态活体检测
https://console.cloud.tencent.com/api/explorer?Product=iai&Version=2020-03-03&Action=DetectLiveFace
实现
在判断司机当日人脸识别情况之后,我们对司机进行人脸识别。前端将司机的id和图片传到后端。后端调用腾讯云两个api来实现司机的人脸识别,并返回人脸识别成功与否给前端
开启接单服务web接口
调用前面所写的端口,完成开始接单服务的功能
停止接单服务web接口
前端发送停止接单的请求,后端修改司机的信息,比如接单状态等。
司机抢单
当前司机已经开启接单服务了,实时轮流司机服务器端临时队列,只要有合适的新订单产生,那么就会轮回获取新订单数据,进行语音播放,如果司机对这个订单感兴趣就可以抢单,大家注意,同一个新订单会放入满足条件的所有司机的临时队列,谁先抢到就是谁的。
我们前端传入司机的id和订单的id,后端基于redisson在司机抢到单之后修改订单的状态和司机的状态,将抢单的成功与否传给前端
订单执行(一)
乘客端查找当前订单
无论是司机端,还是乘客端,遇到页面切换,重新登录小程序等,只要回到首页面,查看当前是否有正在执行订单,如果有跳转到当前订单执行页面
* 之前这个接口已经开发,为了测试,临时跳过去,默认没有当前订单的
实现
前端发送请求后端,后端从threadlocal得到乘客的id,根据乘客id查询订单数据库,看是否有正在执行的订单。
司机端查找当前订单
和乘客端一致
获取订单信息
进入首页,在有执行中订单的情况下,我们需要获取订单信息,才能加载订单的信息。
实现
前端传入订单的id到后端,后端根据订单的id查询订单的信息。司机和乘客端都是一样
司机端司乘同显
司机端司乘同显要简单一些,司机的地点就是司乘同显的起始点,代驾起点就是司乘同显的终点,知道起点与终点,我们就可以计算出最佳线路,根据最佳线路在小程序地图组件上一渲染就可以了
实现
前面我们在地图微服务已经实现过了“计算最佳驾驶线路”接口,这里只需要在提供司机端web接口即可。前端传入司机的经纬度和目的地的经纬度,调用接口计算最佳路线。
更新司机位置到Redis缓存
司机赶往代驾点,会实时更新司机的经纬度位置到Redis缓存,这样乘客端才能看见司机的动向,司机端更新,乘客端获取。
实现
前端将司机的id和经纬度传给后端,后端储存到redis中
获取司机基本信息
乘客端进入司乘同显页面,需要加载司机的基本信息,显示司机的姓名、头像及驾龄等信息
实现
前端传入订单的id到后端,后端获取乘客的id,先判断是否是这个乘客的订单,在调用司机端的接口来查询司机的信息
乘客端获取司机经纬度位置
乘客端要实时了解司机代驾的动向。乘客端的事成同显,显示司机的驾驶路线,也就是两点之间的最佳路线。我们前端传入起始和终止的坐标到后端,我们后端再调用腾讯云的api来计算最佳的路线
司机到达起始点
司机到达代驾起始点,司机手动触发“到达乘客起点”按钮,更新订单状态
* 司机到达代驾起始点之后,更新当前代驾订单数据
* 更新订单状态:司机到达
* 更新订单到达时间
实现
前端传入订单的id和司机的id,我们后端获取后修改该订单的状态和到达时间
司机更新代驾车辆信息
司机到达代驾起始点,联系了乘客,见到了代驾车辆,要拍照与录入车辆信息
实现
前端传入车辆的信息,比如司机的id,车辆前后的照片等。后端负责录入这些信息进数据库
订单执行(二)
开始代驾
代驾开始,我们要更新订单状态及相关信息
就是修改订单状态
批量保存订单位置信息
司机开始代驾后,为了减少请求次数,司机端会实时收集变更的GPS定位信息,定时批量上传到后台服务器。
获取订单服务最后一个位置信息
司机开始代驾后,乘客端要获取司机的动向,就必须定时获取上面更新的最后一个位置信息。
这里执行mongodb的条件查询
Minio上传接口
司机代驾过程中,司机端小程序实时采集录音,把录音和对话文本上传到后台服务,把录完的监控保存Minio
上传,我们基于官方代码稍微修改
保存订单监控记录数据
只要开始代驾,司机端小程序就要录制司乘对话,直到代驾结束,才停止录音。
司机端小程序怎么录音呢?同声传译插件可以实现录音,并且把录音中的语音部分转换成文本。这是前端小程序实现的功能,我们只做了解。
开通数据万象服务CI
数据万象(Cloud Infinite,CI)是依托腾讯云对象存储的数据处理平台,涵盖图片处理、内容审核、媒体处理、AI 识别、文档预览等功能,为客户提供一站式的专业数据处理解决方案,满足您多种业务场景的需求。
我们项目中很多业务都可以使用腾讯云的数据万象服务,比如审核司机上传的身份证、驾驶证照片与手持证件照片等是否包含暴力色情的内容,还有审核代驾过程对话记录是否含有暴力色情等等。如果用人工审核,速度太慢,所以我们需要用数据万象的AI引擎来帮我们审核。
腾讯云COS图片审核
凡是上传到腾讯云COS私有桶的图片,我都需要审核一下。
更新订单监控记录
前面我们保存了司乘之间的对话文字内容,接下来我们要对文字内容加以审核,看看对话的内容是否包含色情或者暴力的成分,我们要对聊天内容做一个安全评级。如果用人工去监视司机和乘客之间的对话,那成本可太高了,而且也雇不起那么多人,所以我们要用AI去监控对话的内容。
上面我们封装了腾讯云数据万象文本审核接口,数据万象可以对用户上传的文本进行内容安全识别,能够做到识别准确率高、召回率高,多维度覆盖对内容识别的要求,并实时更新识别服务的识别标准和能力。
订单监控统计
我们必须对司乘之间的对话内容做监控,保障乘客人身安全是我们首要的任务。腾讯的数据万象服务可以审核文本内容,咱们要把这个功能利用起来。我们调用腾讯万象的接口,审核司乘之间的对话内容,看看是否包含色情或者暴力的成分。审核的结果咱们要更新到order_monitor数据表中,每个订单一条记录。
订单执行(三)
结束代驾
司机到达代驾终点,就可以结束代驾了,结束代驾我们要输入其他费用(路桥费、停车费与其他费用)、计算订单实际里程、计算代驾实际费用、系统奖励、分账信息与生成账单。
订单实际里程其实就是把MongoDB中该订单的GPS定位坐标都给取出来,以时间排序,连接成连线,这个线的距离就是时间里程。
计算系统奖励
系统奖励
每天完成5单后 每单奖励2元
每天完成10单后 每单奖励5元
每天完成20单后 每单奖励10元
根据时间段获取订单
计算分账信息
* 结束代驾之后,计算分账信息,平台按照一定规则抽成处理,将分账信息记录数据库表
结束代驾更新账单
* 更新订单数据:订单状态、订单实际距离、订单实际金额等
* 添加实际账单信息
* 添加分账信息
智能判断司机刷单行为
判断司机刷单的办法也很简单,司机点击到达上车点按钮的时候,司机端小程序通过腾讯地图服务的API,计算当前定位到上车点的距离。如果超过1公里,那就不可以。司机必须距离上车点在1公里以内,点击到达上车点才有效。当司机想要结束代驾的时候,距离代驾终点必须在2公里以内才可以,否则就无法结束代驾。
只是上面的限制也是不够的,我们后面还可以加上预期的里程与实际的里程的一个距离差来进一步判断。
* **司机到达代驾开始位置判断**
-- 通过腾讯地图,获取司机当前位置,当前位置到代驾开始位置距离
-- 如果距离超过1公里,没有到达开始位置
* **司机到达代驾结束位置判断**
-- 通过腾讯地图,获取司机当前位置,当前位置到代驾结束位置距离
-- 如果距离超过2公里,没有到达开始位置