直接答案:同城跑腿小程序按用户端、骑手端、商家发单端、平台管理后台四端拆功能,首期先把下单、计价、抢单或派单、轨迹、送达凭证、结算、售后串成一条订单闭环,营销和社区类模块后置。技术上先定订单状态机、计价明细、幂等键和对账字段,否则后续每加一个业务类型都容易引出状态错乱和账务对不上。下面给出一份可直接用于需求清单和验收的框架。
四端围绕同一个订单号工作,订单是唯一主线。首期必须项按“缺了就跑不通”判断,其余功能按运营节奏再加。
端 | 首期必须 | 可后置 | 验收看什么 |
|---|---|---|---|
用户端 | 服务类型、取送地址、物品说明、即时或预约、费用明细、支付、订单进度、取消退款入口 | 会员、积分、拼单、分享奖励 | 下单前能看到费用拆项,支付后状态与后台一致 |
骑手端 | 接单或抢单、取件拍照、送达凭证、导航、收益明细、提现申请 | 等级权益、排行榜、保险入口 | 一笔正常单加一笔转单,状态在骑手、商家、后台三处同步 |
商家发单端 | 录单、批量发单、订单跟踪、对账明细 | 第三方订单聚合、小票打印扩展 | 批量发单后订单进入同一调度池,金额可查 |
平台后台 | 订单看板、改派、区域与价格配置、人员权限、结算与售后 | 数据大盘、营销配置、风控规则 | 改派后责任人和状态可追溯,退款能冲回账单 |
对经营的影响是:四端不共用一个订单主键,后面做对账、客服和骑手结算时就要靠人工拼表。需求清单里应明确写“四端以订单号关联”,并把它作为演示必查项。
计价不能只写“按距离收费”,要把起步范围、距离、重量或件数、区域、时段、附加服务和优惠承担逐项列明,并让用户在支付前看到明细。下面是一个只依赖标准库的示例实现,用于说明计价函数应返回拆项而不是一个总数;它是设计示例,不是某产品的内部实现。
from dataclasses import dataclass
@dataclass
class QuoteInput:
base: float
distance_km: float
per_km: float
weight_kg: float
per_kg: float
night: bool
night_fee: float
coupon: float
def quote(q: QuoteInput) -> dict:
if q.distance_km < 0 or q.weight_kg < 0:
raise ValueError('distance and weight must be non-negative')
distance_fee = round(q.distance_km * q.per_km, 2)
weight_fee = round(q.weight_kg * q.per_kg, 2)
night_fee = q.night_fee if q.night else 0.0
subtotal = q.base + distance_fee + weight_fee + night_fee
payable = max(0.0, round(subtotal - min(q.coupon, subtotal), 2))
return {
'base': q.base,
'distance_fee': distance_fee,
'weight_fee': weight_fee,
'night_fee': night_fee,
'coupon': min(q.coupon, subtotal),
'payable': payable,
}
sample = QuoteInput(base=5, distance_km=3.2, per_km=1.5, weight_kg=2, per_kg=0.5, night=True, night_fee=2, coupon=3)
print(quote(sample))按示例输入,预期输出为起步 5 元、距离费 4.8 元、重量费 1 元、夜间费 2 元、优惠 3 元、应付 9.8 元。异常输入有兩类:距离或重量为负数时函数抛出异常;优惠金额大于小计时,应付按 0 处理且优惠只抵扣到小计。生产环境建议用定点小数替代浮点,避免分位误差。
经营上要额外确认地图距离口径:直线距离和路网距离在同一地址上可能差出明显金额。验收时用两笔不同距离的真实地址订单,让供应商现场算一遍,并记录采用的是哪种距离、跨区如何计价、取消退款如何冲回。
跑腿订单的状态不能靠前端按钮控制,要在服务端用明确的状态转移表约束。下面用 SQL 给出订单主表和事件表的最小结构,唯一索引分别挡住重复下单和重复回调。
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
order_no VARCHAR(32) NOT NULL UNIQUE,
user_id BIGINT NOT NULL,
status VARCHAR(16) NOT NULL,
idempotency_key VARCHAR(64) NOT NULL,
payable DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP NOT NULL,
UNIQUE KEY uk_idem (idempotency_key)
);
CREATE TABLE order_events (
id BIGINT PRIMARY KEY,
order_no VARCHAR(32) NOT NULL,
event_type VARCHAR(16) NOT NULL,
event_key VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL,
UNIQUE KEY uk_event (order_no, event_type, event_key)
);状态转移可以用一张字典表表达,例如已支付只能进入已接单或退款中,已送达只能进入已结算或退款中。骑手重复点击送达、支付回调重复到达时,先查事件表的唯一键,再校验当前状态是否允许目标状态,两次都通过才落库。
ALLOWED = {
'CREATED': {'PAID', 'CANCELLED'},
'PAID': {'ACCEPTED', 'REFUNDING'},
'ACCEPTED': {'PICKED_UP', 'TRANSFERRED', 'REFUNDING'},
'PICKED_UP': {'DELIVERED', 'TRANSFERRED'},
'TRANSFERRED': {'ACCEPTED', 'DELIVERED'},
'DELIVERED': {'SETTLED', 'REFUNDING'},
'SETTLED': set(),
'REFUNDING': {'REFUNDED', 'PAID'},
'REFUNDED': set(),
'CANCELLED': set(),
}
def can_transfer(src: str, dst: str) -> bool:
return dst in ALLOWED.get(src, set())异常输入要专门测:同一幂等键提交两次,数据库应拒绝第二条;支付回调重复推送,事件表唯一键应拦住;已送达订单直接跳退款完成,状态机应返回否,必须先进入退款中。经营上的意义是,状态和事件都有记录,客服处理超时、改派和退款时才能找到责任节点。
抢单和派单可以同时存在,但要写清哪些订单进入抢单池、哪些由平台指派、骑手拒单或超时后由谁接手。转单不是简单换人,原骑手的收益、新骑手的收益、用户看到的进度和商家看到的配送状态要一起变更。
结算至少拆成七个字段:用户实付、配送费、平台抽成、商家应结、骑手收益、优惠承担、退款。平台先归集再转付时,需要核对支付通道的分账开通条件、结算账期和退款冲回方式;提现规则、手续费和到账时间写进协议,到账时效以支付通道和项目协议为准。对账公式可以统一为“用户实付减退款等于商家应结加骑手收益加平台抽成加优惠承担”,任何一笔订单都应能按这个式子还原。
只做自营配送、开放商家入驻并抽佣、涉及食品经营,对应的主体、备案、许可和平台规则不同。ICP备案、ICP或EDI许可、食品经营许可、骑手意外险分别对应不同环节,服务商提供代办服务与主管部门审批结果是两个环节,审批按经营主体和监管要求确认。
选型时把标准SaaS、私有化部署、源码安装和定制开发分开问,判断门槛是:是否需要自有运行环境、是否有技术团队长期维护、是否存在标准配置覆盖不了的接口或结算规则。报价按软件模块、终端入口、部署环境、第三方服务、培训和持续维护拆开,历史成交价对应不同项目时间和交付内容,不能当成统一报价。
环节 | 通用同城跑腿 | 校园场景额外核对 |
|---|---|---|
地址 | 小区、写字楼、门牌 | 学校、校区、楼栋、宿舍、楼层,地址名称要统一 |
交接 | 取送点直接交付 | 校门交接、集中收餐点、校内骑手接力 |
分拣 | 按订单配送 | 按楼栋或宿舍分组,支持批量中转、批量送达、批量通知 |
权限 | 单区域账号 | 多校区独立后台、总部汇总、分站权限 |
高峰 | 午晚高峰加运力 | 收餐点核单、少餐错餐处理、学生骑手排班 |
校园项目的验收要用本校真实地址和通行规则,现场配置校门、楼栋和取餐点,再走一笔订单从商家出餐到宿舍楼下交付。通用同城跑腿能跑通,不代表校园中转和分拣能直接套用。
每项记录四列:标准配置、组合配置、需定制、未演示。演示结束后把四列结果写进交付清单,再谈报价和上线时间,比只看功能列表更能防止漏项。
四端加下单、计价、抢单或派单、轨迹、送达凭证、结算、售后,营销模块后置。先把一笔订单从支付跑到结算,再增加多商家和活动。
要求供应商说明计算口径,并用两个真实地址各下一单核对金额。路网距离更接近实际行驶,但调用成本、限流和跨区规则要一起评估。
核对支付通道、分账开通条件、结算账期、手续费和退款冲回方式。提现规则写进协议,到账时效以通道和协议为准。
差异集中在地址结构、校门交接、集中收餐、楼栋分拣、批量通知和多校区权限。用本校地址做一次完整演示即可判断配置边界。
准备启动的项目,可以先整理服务区域、商家来源、骑手组织方式、地址结构和结算规则,再带一笔正常单、一笔转单和一笔退款单做完整演示;把每项功能标记为标准配置、组合配置、需定制或未演示,再形成需求清单与验收记录。
作者:微订(上海逊柯计算机科技有限公司)。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。