ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

代驾平台源码二次开发:从订单状态机到支付回调的实战解析

代驾平台源码二次开发:从订单状态机到支付回调的实战解析 简介一套可直接落地的代驾平台源码包将微信小程序端与后端服务整合在同一工程中适合有小程序开发或Java后端基础的学习者用于项目实战、二次开发或快速部署上线。压缩包内共2000个文件以JavaScript、Vue、TypeScript构建前端逻辑以Java实现后端接口并通过JSON、YAML等配置项串联工程另含WXML/WXSS小程序页面结构、PNG/MP3等视觉音频素材整体约7.63MB目录分层清晰便于按模块查阅。资源已覆盖司机、地图、订单等核心业务场景的后端服务小程序前端页面代码与相关静态资源亦包含在内下载后可直接运行也支持在此基础上扩展业务逻辑。目前已有972人浏览学习对于想要搭建同类平台、仿写代驾业务流程或研究小程序与后端协作方式的开发者来说是一份值得参考的源码合集。1. 代驾平台源码包到底装了什么一个订单从点击到结束要过的关如果你手里正拿着一个「代驾小程序和后端共同开发的代驾平台源码.zip」第一反应多半是解压、改数据库密码、然后把后端跑起来。接过这类项目的人都知道一个代驾订单从用户点击“呼叫代驾”到司机点击“结束行程”中间要过十几道关距离计算、计价、派单、订单状态流转、微信支付回调、司机提现。源码包只是把小程序端和后端代码交到你手上真正让它在你的服务器上跑通、扛住首批用户的并发是另一件事。下面基于这类源码最常见的交付形态——Spring Boot 后端 微信小程序用户端/司机端 MySQL 数据库——把业务拆开、部署跑通、参数调对、坑趟平。这篇内容适合想自建代驾/跑腿/货运平台的人也适合给外包项目做二次开发的工程师。2. 先拆业务流程再写代码订单状态机、后端选型与双端角色边界代驾平台从表面看只有“用户叫车、司机接单”两个动作。拆细之后它会牵出定位、计价、支付、分账、风控五个子系统。拿到一份源码 zip别急着npm install和mvn spring-boot:run先把订单状态机定下来。状态机是后端所有接口的“宪法”状态没定义清楚后面每个接口都会写出各自为政的if/else。2.1 订单状态机是后端的“宪法”九个状态与不可逆的流转规则一份正规的代驾源码订单状态至少包含下面这九个。状态字段通常用tinyint存在订单表里而不是用字符串。状态码状态名触发动作0待接单用户创建订单成功1已接单司机抢单成功2司机赶往起点司机点击“我要接驾”3已上车司机到达起点并接到用户4服务中司机点击“开始行程”5已完成司机点击“结束行程”6待支付用户端生成账单7已支付微信支付回调成功8已取消用户/司机/系统取消先看后端有没有枚举定义没有就自己补public enum OrderStatus { CREATED(0, 待接单), ACCEPTED(1, 已接单), TO_PICKUP(2, 司机赶往起点), PICKED_UP(3, 已上车), IN_SERVICE(4, 服务中), COMPLETED(5, 已完成), PAYMENT_PENDING(6, 待支付), PAID(7, 已支付), CANCELLED(8, 已取消); private final int code; private final String desc; OrderStatus(int code, String desc) { this.code code; this.desc desc; } }这个枚举解决的是代码里到处写魔法数字的问题。有些源码里直接写order.setStatus(2)三周后接手的人根本不知道 2 是什么。有了枚举至少能全局搜OrderStatus.TO_PICKUP。状态流转的校验是另一个重点。最常见的错误是先查订单再判断状态、最后更新这种“先查后改”在并发下一定会出问题。正确的做法是直接在数据库层做条件更新UPDATE t_order SET status 2, driver_id #{driverId} WHERE order_id #{orderId} AND status 0这个 SQL 的含义是只有当前状态还是 0待接单时才允许更新成 2同时把司机 ID 写进订单。如果影响行数是 0说明订单已经被别人抢走或者用户已经取消后端直接返回“抢单失败”即可。这样就不需要SELECT出来做比较也省掉了分布式锁。还有一个细节容易被忽略状态每次流转都要写一条订单日志。代驾的客诉率比普通网约车高用户和司机各执一词时日志是唯一能还原现场的证据。日志表至少要有order_id、from_status、to_status、operator_id、operator_type、create_time六个字段。2.2 后端选型与三个核心模块为什么这个场景用 Spring Boot 最常见这类源码 zip十个里有八个后端是 Spring Boot MyBatis-Plus MySQL Redis。原因不复杂微信支付、高德/腾讯地图、微信登录这些 SDK 的官方示例和踩坑帖子几乎全是 Java 的遇到问题搜得到答案。PHP 方案Laravel、ThinkPHP也有但代驾这种强状态流转、强并发控制的业务Java 的工程化约束能少很多破事。拿到源码先干什么打开pom.xml看版本。Spring Boot 2.x 配 JDK 8Spring Boot 3.x 配 JDK 17版本错位是后面启动失败的排第一的原因。后端三个核心模块必须单独看懂别急着改业务第一个是派单模块。代驾派单本质上是一道“时空检索”用户下单坐标为中心扫描半径内的在线司机。常见做法是 Redis GEO 存司机实时坐标用GEORADIUS检索候选司机// Redis GEO 检索附近在线司机半径默认3公里 SetGeoResultRedisGeoCommands.GeoLocationString results redisTemplate.opsForGeo() .radius(driver:location, new Circle(new Point(userLng, userLat), new Distance(radiusKm, Metrics.KILOMETERS))); ListDriver candidates results.stream() .map(GeoResult::getContent) .map(GeoLocation::getName) .map(this::getDriverInfo) .filter(d - ONLINE.equals(d.getStatus()) !d.isOnOrder()) .sorted(Comparator.comparing(Driver::getScore).reversed()) .limit(5) .collect(Collectors.toList());这段代码的逻辑是Redis GEO 只负责“哪些司机在附近”比完距离之后在线状态、是否正在服务中、评分这些业务过滤条件仍然要自己写。注意.limit(5)是推送给司机端的候选数量上限代驾场景通常同时推 3~5 个司机推太多会让用户等得更久。第二个是计价模块。代驾计价比网约车多一个“等候费”而且夜间费通常从 22 点起算。计价规则不能硬编码在后端 Java 代码里常见做法是放数据库配置表运营改价不用发版。第三个是订单流转模块。它不只是改状态还包括给用户端和司机端推送状态变更通知。代驾小程序里最常见的推送是微信订阅消息也就是服务通知里的“司机已接单”。这个模块里要重点看消息有没有做失败重试订阅消息是一次性的用户取消订阅后就推不进去了不能因为推送失败导致司机白跑一趟。2.3 小程序按角色权限拆用户端、司机端、管理端不能共用一套登录态代驾业务有三类人用户、司机、平台运营。大多数源码把用户端和司机端做成两个独立小程序共用同一个后端 API靠 token 里的角色区分身份。很多二次开发翻车就翻在这里后端接口只做了“有没有登录”的校验没做“是什么角色”的校验。司机拿到自己的 token 去调用户端的“我的钱包”接口居然能返回用户余额。这属于越权漏洞在代驾平台里比订单 bug 更致命。后端需要一个角色拦截器在请求进 Controller 之前就把身份和权限验完Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); LoginUser user jwtUtil.parse(token); if (user null) { response.setStatus(401); return false; } // 方法上的 RequireRole(DRIVER) 注解决定谁能访问这个接口 if (handler instanceof HandlerMethod) { RequireRole requireRole ((HandlerMethod) handler).getMethodAnnotation(RequireRole.class); if (requireRole ! null !Arrays.asList(requireRole.value()).contains(user.getRole())) { response.setStatus(403); return false; } } request.setAttribute(loginUser, user); return true; }这套机制的要点是登录接口本身放行其余接口默认都要带 token需要角色限制的接口在方法上加RequireRole(DRIVER)注解。注意被拦截器放行的OPTIONS预检请求跨域问题在前后端分离项目里迟早会遇到拦截器要显式放行。小程序端的页面结构也按角色拆。用户端首页是“确认位置→选择服务→立即呼叫”司机端首页是“附近订单列表→抢单按钮→开始导航”。如果源码包里一套页面同时给两种角色用只在页面上用if (role DRIVER)做显隐这种代码趁早重构权限控制不能只靠前端隐藏按钮。3. 把「源码.zip」变成能跑的代驾平台数据库初始化、双端联调与一条订单的验证拿到 zip 之后最想知道的一定是“怎么跑起来”。代驾平台和普通管理系统不一样它有两个小程序端加一个后端任何一个环节配置错了都跑不通全链路。这一章按“后端先行、小程序跟上、订单验证收尾”的顺序来每一步都给可以直接抄的命令和配置。3.1 后端先跑起来导入数据库脚本、改配置、启动 Spring Boot解压 zip 后先看目录结构。常见布局是server后端工程、miniapp-user用户端小程序、miniapp-driver司机端小程序、sql数据库初始化脚本。有些压缩包用 uniapp 写小程序目录会是uniapp但数据库脚本一定在。先建库导数据mysql -uroot -p -e CREATE DATABASE daijia DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; mysql -uroot -p daijia ./sql/daijia_init.sql字符集必须用utf8mb4。代驾订单备注里有用户填的地址、门牌号、特殊要求用户在输入框粘贴带 emoji 的内容时用旧版utf8会直接插入失败。这个错很隐蔽日志里只看得到Incorrect string value排查一圈才发现建库语句不对。改后端配置application.yml里这几个值几乎必改spring: datasource: url: jdbc:mysql://localhost:3306/daijia?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的数据库密码 redis: host: 127.0.0.1 port: 6379 wx: appid: wxa1b2c3d4e5f6g7h8 secret: 你的AppSecret mch-id: 测试商户号serverTimezoneAsia/Shanghai必须写在连接串里。MySQL 8.x 的驱动对时区很敏感不写这个参数时间字段会整体偏移 8 小时运营后台看到订单时间全是晚上 8 点下的单。微信支付相关配置先用测试商户号正式商户号等整个链路通了再换不然回调验签必挂。启动后端cd server mvn spring-boot:run看到日志里出现Tomcat started on port 8080才是启动成功。如果报Invalid default value for create_time说明 SQL 脚本是 MySQL 5.7 写的在 8.0 里零日期字段校验更严格要么给create_time都加上DEFAULT CURRENT_TIMESTAMP要么把 MySQL 换回 5.7。3.2 小程序改成你的 AppIDbaseUrl、合法域名与 request 封装后端起来之后小程序端第一步不是写代码而是把全局配置里的baseUrl改掉。原生微信小程序找config.js或utils/config.jsuni-app 写的找config/index.js。改两个地方AppID 和请求地址。// 小程序端全局配置 module.exports { // 开发环境指向本机IP生产环境换成 https 域名 baseUrl: http://192.168.1.100:8080/api, appid: wxa1b2c3d4e5f6g7h8 }这里有个开发期最容易卡的坑微信开发者工具里默认不允许请求 http 接口。解决方法是打开开发者工具右上角「详情」→「本地设置」勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”。不勾选的话模拟器里所有wx.request都会报request:fail而且错误信息很模糊根本看不出来是域名问题。再看一遍源码里有没有统一的请求封装。没有的话自己补一个function request(path, method, data) { return new Promise((resolve, reject) { wx.request({ url: config.baseUrl path, method: method || GET, data: data || {}, header: { Authorization: wx.getStorageSync(token) || , Content-Type: application/json }, success: (res) { if (res.statusCode 401) { // token 过期跳转登录页 wx.navigateTo({ url: /pages/login/login }); return; } if (res.statusCode 200 res.statusCode 300) { resolve(res.data); } else { reject(res.data); } }, fail: reject }); }); }这个封装的核心就一件事让所有接口自动带上Authorization头。代驾后端几乎所有接口都要从 token 里解析 userId 和 role每写一个接口都在页面里手动塞 token 是给自己埋雷。改完配置开发工具里点「编译」用户端首页应该能请求到后端的首页 banner 接口。如果报了跨域错检查后端有没有加 CORS 配置前后端分离项目里这是必踩的一步。3.3 用一条测试订单打通全链路从创建订单到支付回调两端都能跑起来之后别急着写功能先用一条测试订单把全链路打通。用一个真实的订单把“创建→派单→接单→开始行程→支付回调”整条流水线验证一遍比写十个接口更值。先在后端把测试用户和测试司机的 token 拿好然后直接调接口创建订单# 用户端创建代驾订单 curl -X POST http://localhost:8080/api/order/create \ -H Authorization: Bearer {USER_TOKEN} \ -H Content-Type: application/json \ -d { startLng: 116.397, startLat: 39.908, endLng: 116.500, endLat: 39.950, userPhone: 13800138000 }返回的orderId记下来。然后用司机端小程序或直接调司机抢单接口接受这个订单再回到用户端看状态有没有从“待接单”变成“已接单”。全链路验证时重点看三个地方。第一创建订单后 Redis GEO 里有没有司机坐标。很多源码包靠司机端定时上报位置如果你只启动了用户端、没跑司机端派单接口永远找不到候选人。这也是很多人反馈“订单创建成功了但司机端收不到”的最常见原因——不是代码错是司机端压根没启动位置上报。第二司机接单后用户端有没有收到状态推送。代驾的推送大多走微信订阅消息用户必须点过一次“允许订阅”才会推得进去。测试时先在用户端触发一次订阅授权再模拟司机接单。第三订单结束后的支付回调。这一步最容易出问题建议直接看后端日志里有没有pay/notify的请求记录。微信支付回调是微信服务器主动请求你的后端本地开发环境下微信服务器访问不到localhost必须先内网穿透或部署到测试服务器这也是本地联调支付环节最大的阻碍。没有公网地址的话先用后端的模拟支付接口把状态推到“已支付”等部署到服务器再验真实回调。4. 代驾后端必调的5个参数定位距离、计价规则、派单并发、订单超时、支付幂等代驾后端启动起来只是第一步。真正决定这个平台能不能用的是下面这些参数。它们分散在计价模块、派单模块、支付模块里改错一个用户侧感知到的就是“预估价和实际价差一倍”“司机抢不到单”或者“司机余额不对”。这些参数调好平台才算从“能跑”变成“能用”。4.1 距离怎么算才对Haversine 公式、坐标系与地图SDK的取舍代驾计价的第一输入是距离。源码里最常见的是后端直接用 Haversine 公式算球面距离因为不依赖第三方 API没有费用也没有 QPS 限制。private static final double EARTH_RADIUS 6371.0; public static double distance(double lng1, double lat1, double lng2, double lat2) { double dLat Math.toRadians(lat2 - lat1); double dLng Math.toRadians(lng2 - lng1); double a Math.sin(dLat / 2) * Math.sin(dLat / 2) Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2); double c 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return EARTH_RADIUS * c; }这段代码算出来的是球面直线距离单位是公里。它的问题是完全不管红绿灯、单行道、绕路。用户从小区北门下单司机在南门直线距离只有 300 米但实际开车要绕 1.2 公里。那这个公式到底用在哪用在“起步价内的距离判定”是够用的。比如起步价覆盖 3 公里用户只要在半径 3 公里内按起步价计费没问题。但“预估价”千万别用直线距离建议调高德或腾讯地图的“驾车路线规划”接口拿到真实的路线里程。不然用户看到的预估价是 30 块实际账单 48 块客诉直接翻倍。这里还藏着一个玄学问题坐标系的坑。微信wx.getLocation不传参数时默认返回 WGS-84 坐标传type: gcj02才返回国测局坐标。高德地图和腾讯地图用的是 GCJ-02百度地图是 BD-09。三个坐标系混用距离能偏出几公里。排查方法很简单把用户下单坐标和司机上报坐标都打出来扔到在线地图工具上对比偏离超过 100 米就说明坐标系不统一。4.2 计价规则落库起步价、里程费、等候费、夜间费分城市配置代驾计价最大的特点是“分城市、分时段”两套规则。一线城市起步价和二三线城市不一样夜间 22 点到次日 6 点的费率也不一样。计价规则写死在代码里是这份源码最大的债务每改一次价格就要发一次版。正确的做法是建立一张计价规则表按城市和时间段存配置CREATE TABLE t_price_rule ( id BIGINT AUTO_INCREMENT PRIMARY KEY, city_code VARCHAR(10) NOT NULL COMMENT 城市编码, base_price DECIMAL(10,2) NOT NULL COMMENT 起步价(元), base_distance INT NOT NULL COMMENT 起步里程(公里), unit_price DECIMAL(10,2) NOT NULL COMMENT 超起步里程单价(元/公里), night_start VARCHAR(5) NOT NULL COMMENT 夜间时段开始 22:00, night_end VARCHAR(5) NOT NULL COMMENT 夜间时段结束 06:00, night_surcharge DECIMAL(10,2) DEFAULT 0 COMMENT 夜间服务费(元), wait_price DECIMAL(10,2) DEFAULT 0 COMMENT 等候费(元/分钟), status TINYINT DEFAULT 1, UNIQUE KEY uk_city (city_code) );价格字段全部用DECIMAL(10,2)别用FLOAT。金额这种字段用浮点数是给自己找后悔药累计到月底分账的时候小数误差会让你想砸电脑。计价逻辑的要点在于“当前生效的规则”。用户下单时是白天但订单结束在晚上 10 点以后夜间费怎么算代驾行业的通行做法是以司机点击“开始行程”的时间为准使用那一刻的计价规则快照。快照要存到订单表里不能只存金额。否则运营调完价格历史订单全对不上账财务对账的时候全是一笔糊涂账。4.3 派单与超时并发抢单的乐观锁、派单半径与自动取消时间窗代驾平台第一个并发高峰出现在“司机同时抢同一单”。用户刚下单的几秒内附近 5 个司机同时点了抢单按钮后端如果处理不好就会出现“两个司机都以为抢到了”的客诉。解决这个问题的不是分布式锁而是前面第 2.1 节那条带条件状态的 UPDATE 语句。PostMapping(/driver/accept) public ResultBoolean accept(RequestBody AcceptOrderReq req) { int rows orderMapper.casAccept(req.getOrderId(), req.getDriverId()); if (rows 0) { throw new BizException(订单已被抢走或已取消); } // 抢单成功后给用户端推送订阅消息 wxSubscribeMessage.pushToUser(req.getOrderId(), DRIVER_ACCEPTED); return Result.ok(true); }casAccept的背后就是UPDATE t_order SET status 1, driver_id ? WHERE order_id ? AND status 0。在 InnoDB 引擎下同一行记录只有一个事务能拿到行锁后面的请求拿到锁后看到的 status 已经不是 0影响行数为 0直接返回失败。这种方式的优点是不引入额外组件一个语句就解决了并发问题。派单相关的参数通常有四个建议放进配置表而不是写死在代码里。参数推荐值说明初始派单半径3 公里用户下单后的第一轮派单范围半径扩展步长1 公里无司机应答后每 10 秒扩一圈最大派单半径8 公里超出后不再扩大避免司机跑太远订单自动取消时间120 秒超过 120 秒无司机接单订单自动取消推送给用户这几个参数里订单自动取消时间最容易引起客诉。设太短用户会觉得平台没司机设太长用户在雨里等得烦躁。常见做法是 120 秒同时每 30 秒给用户推一条“正在为您寻找司机”的服务通知。4.4 支付回调与余额提现幂等更新、金额单位与账户冻结支付模块是代驾平台里“风险最高”的部分而且风险出在你看不见的细节上。微信支付的回调是异步的而且为了确保通知送达微信服务器会重复通知多次。设计得不好就会出现“同一笔订单被结算了两次、司机余额多了一倍”的严重翻车现场。回调处理代码的关键是幂等PostMapping(/pay/notify) public String wxPayNotify(RequestBody String xmlData) throws Exception { // 1. 验签 MapString, String result WxPayUtil.xmlToMap(xmlData); if (!WxPayUtil.verifySign(result, mchKey)) { return xmlreturn_code![CDATA[FAIL]]/return_code/xml; } // 2. 金额校验回调金额(分)必须等于订单应付金额(分) Order order orderMapper.selectByOrderNo(result.get(out_trade_no)); if (order.getAmountFen() ! Integer.parseInt(result.get(total_fee))) { return xmlreturn_code![CDATA[FAIL]]/return_code/xml; } // 3. 幂等更新status从6(待支付)改为7(已支付) int rows orderMapper.updateStatusByNo(order.getOrderNo(), 6, 7); if (rows 0) { // 说明已处理过直接返回成功 return xmlreturn_code![CDATA[SUCCESS]]/return_code/xml; } // 4. 给司机账户加可提现余额扣除平台抽成 accountService.settleToDriver(order); return xmlreturn_code![CDATA[SUCCESS]]/return_code/xml; }这段代码里最容易写错的是第 3 步。很多新手写成“先查订单状态如果是待支付就更新”但两个并发线程同时查到的都是待支付结果更新了两次。条件更新WHERE status 6就保证了只有一次能成功后面那次影响行数为 0直接返回成功给微信服务器让微信停止重试。这是支付幂等最基本的实现方式。金额单位的坑也在这里。数据库里用DECIMAL(10,2)存的是“元”但微信支付传的是“分”。回调里拿到的total_fee单位是分必须显式转换。少乘 100 的话订单收的钱会少 100 倍这个 bug 一旦上线损失是按小时计的。司机提现接口还要多做一层校验司机是否有进行中的订单。代驾司机接单后用户还没付钱司机余额里显示的是“待结算金额”不能提现。等订单完成、用户支付成功后走上面的结算逻辑把“可分账余额”加进去。提现时再校验“可分账余额 ≥ 提现金额”双保险。5. 代驾平台源码实战避坑前后端联调最常遇到的6个问题这一章专门讲坑。每一个都是真实项目里反复出现的问题按“现象 → 原因 → 解决”的顺序写。你在跑这份源码时迟早会撞上一两个提前知道能省一晚上。5.1 真机预览时所有请求全部失败request 合法域名没配现象开发工具里一切正常一用手机扫码预览所有接口全部request:fail。原因微信小程序生产环境强制校验域名。baseUrl还是开发阶段的http://192.168.x.x:8080既不是 https也没有在小程序后台配置到“request 合法域名”列表里。微信的机制是只要域名不合法连请求都发不出去错误信息里只有一行request:fail根本看不出是网络问题还是域名问题。解决开发阶段在微信开发者工具「详情」→「本地设置」勾选“不校验合法域名”。上线阶段必须准备一个备案过的 https 域名后端部署在域名后面然后在小程序后台「开发管理」→「服务器域名」里把域名加进request合法域名。注意这个配置修改后有小概率延迟生效设置完等几分钟再试。5.2 司机端能查用户手机号角色鉴权漏配现象用司机账号登录后直接调用户端的“我的钱包”接口居然返回了用户余额。原因后端接口只做了登录校验——检查 token 里有没有 userId没校验角色。源码里的RequireRole注解只加在了几个核心接口上钱包、订单详情、用户资料这些接口全漏了。解决全量梳理一遍 Controller凡是涉及隐私数据手机号、钱包余额、历史订单、家庭地址的接口全部加上角色注解。不放心的做法是给拦截器加一个“默认拒绝”开关包路径下所有接口默认只允许 USER 角色访问需要司机访问的接口才显式加RequireRole({USER, DRIVER})。5.3 预估价和实际价格差一倍坐标系混用现象用户端预估价 30 元司机结束行程后账单 58 元用户直接投诉。原因用户下单坐标是微信返回的 WGS-84 坐标司机端地图 SDK 上报的是 GCJ-02 坐标后端没做转换直接算距离多算了好几公里。解决全链路统一用 GCJ-02。微信wx.getLocation要显式传type: gcj02后端经纬度字段加注释标明坐标系排查时把同一订单的用户坐标和司机位置坐标画到地图上看两个本该重合的点如果差了几百米坐标系就不对。高德和腾讯地图的 SDK 都有坐标转换工具类后端入库前统一过一道。5.4 解压后按 README 启动直接报错JDK 版本和 MySQL 时区现象mvn spring-boot:run刚启动就抛异常报错内容千奇百怪有Invalid default value for create_time也有com.mysql.cj.exceptions.InvalidConnectionAttributeException。原因源码是在 JDK 8 MySQL 5.7 的环境下写的你本机装的是 JDK 17 MySQL 8.0。JDK 版本不符会导致编译报错或运行时不兼容MySQL 8.0 对时间字段的默认值校验比 5.7 严格得多。解决先装一个 JDK 8把JAVA_HOME指过去再看pom.xml里java.version是不是 1.8。MySQL 连接串加serverTimezoneAsia/ShanghaiSQL 脚本里所有datetime字段检查一遍create_time统一补DEFAULT CURRENT_TIMESTAMP。这套组合解决九成启动失败。5.5 支付回调重复入账状态更新没用条件 WHERE现象一笔订单司机端显示“已收款 58 元”运营后台查出同一笔订单结算了两次金额对不上。原因支付回调接口用“先查再改”的逻辑。第一次回调把状态改成已支付并给司机加钱第二次回调微信重试时又查了一遍发现状态已经是“待支付”以外的状态没有条件限制直接再次执行加钱逻辑。解决改成条件更新UPDATE t_order SET status 7 WHERE order_no ? AND status 6影响行数为 0 时直接返回 SUCCESS。同时在订单流水表加唯一索引uk_order_no_pay_channel让数据库做第二层兜底。改完这两处重复回调就是无害的。5.6 联调时接口老是 400字段命名风格不统一现象前端传driverId后端接口定义的是driver_id结果RequestBody反序列化失败前端报 400后端日志里一堆HttpMessageNotReadableException。原因小程序端 JavaScript 习惯驼峰命名driverId后端 Java 也习惯驼峰但数据库字段是下划线driver_id MyBatis 映射时忘了配置驼峰转换接口的参数对象里就出现了下划线命名。解决统一约定后端接收参数的 DTO 字段全部用驼峰在application.yml里配置spring.jackson.property-naming-strategySNAKE_CASE或保持默认驼峰并让 MyBatis-Plus 开启map-underscore-to-camel-case: true。更省事的办法是后端把接口文档用 Swagger 导出前端直接按照文档里的字段定义生成请求参数类型不靠群里口头对字段。6. 上线前最后一步用验证清单检查这套代驾源码再补两个进阶功能跑通全链路、调完参数之后别急着买服务器部署。用下面这份清单过一遍每一项都达标了再谈上线。验证项操作方式通过标准订单全链路用户创建订单→司机抢单→开始行程→结束行程→支付→提现状态依次流转日志完整并发抢单用脚本模拟 10 个司机同时抢同一订单只有 1 人成功其余返回“订单已被抢走”支付幂等用测试商户号向回调接口推送 3 次同一订单的支付通知司机余额只加一次弱网恢复小程序端开启弱网模拟订单创建请求超时后重试不产生重复订单金额精度分别用起步价内、超起步价、夜间 3 种场景计算账单精确到分无浮点误差权限隔离司机 token 调用户端敏感接口返回 403这份清单过完源码包本身的质量就有底了。下一步如果平台想跑得比“演示版”更远建议优先补两个进阶功能。第一个进阶方向是把派单从“抢单”升级为“指派抢单”混合模式。代驾和网约车不同用户对司机的要求不仅仅是“近”更看重“稳”。可以在派单模块里加一个综合分距离权重 40%、历史完单率 30%、好评率 20%、当日听单时长 10%。系统先把订单指派给综合分最高的司机司机在 15 秒内未接单再进入广播抢单。这个改动不需要动底层状态机只需要在派单模块的排序逻辑里加一个分值计算。第二个进阶方向是加行程录音与驾驶行为分析。录音在代驾客诉里是决定性的证据车上两个人各执一词时录音能还原谁说的才是真的。实现上不复杂司机端小程序在“开始行程”时获取录音权限分段上传到后端对象存储订单结束后 24 小时自动删除。驾驶行为分析则依赖手机加速度传感器急加速、急刹车、急转弯都能被识别出来跑完一单给司机一个安全分。这个分数反向影响派单权重形成“开得好→单更多”的正循环。我自己接过一个代驾平台的二次开发对方上线三个月后最大的客诉不是慢而是司机绕路说不清。后来补了行程轨迹回放——用的是源码里本来就有的坐标上报表只是把坐标点连成线展示给用户。所以拿到源码之后先别急着加新功能把已有的数据用起来往往比新做东西更能解决问题。希望这套流程和避坑清单帮到你拿到任何一份代驾平台源码包都能少走几步弯路。本文还有配套的精品资源点击获取
返回列表