今天继续完善“悦选商城”项目,主要做了两个方向:一个是私域社群和小程序商城,另一个是本地生活即时零售。
这次没有单纯追求页面数量,而是尽量把每个功能做到能操作、能保存、能结算。毕竟页面做出来只是第一步,用户点击之后有没有反应,数据能不能落下来,支付完成后订单能不能正常生成,这些才是电商项目真正麻烦的地方。
一、完成私域社群与小程序商城
今天先把私域社群和小程序商城这一部分补完整了。
私域社群页面目前支持:
- 用户加入社群
- 领取社群专属优惠券
- 查看社群公告
- 预约社群直播
- 跳转小程序商城
- 查看会员专属活动
小程序商城则补上了商品搜索、分类筛选、商品详情和真实加购。
之前有些页面虽然按钮已经放上去了,但点击后并没有真正修改数据。这次把前端操作和后端业务接了起来,用户领取优惠券、预约直播或者加入购物车后,页面状态都会跟着变化,不再只是做一个静态展示。
二、开始实现本地生活即时零售
私域商城完成后,继续按照第 20 张原型图开发“本地生活即时零售”。
这个模块和普通商城不太一样。普通商城通常是跨店铺统一购物车,下单后由商家通过快递发货;即时零售更接近外卖,需要考虑附近门店、起送价、配送费和预计送达时间。
目前已经加入三家附近门店:
- 悦选生活超市(宿职院店)
- 邻里便利店(学府路店)
- 悦选健康药房(宿豫店)
页面会展示门店距离、评分、月销量、配送费、营业时间以及预计送达时间。位置暂时以宿迁职业技术学院为中心,方便后续继续接入校园生活场景。
首页还增加了生鲜、日用、零食、药妆、饮品和便利店等分类,用户可以直接搜索商品,也可以按照分类查看附近门店中的商品。
三、购物车必须按门店隔离
即时零售开发中比较重要的一点,就是不能直接复用普通商城购物车。
如果用户同时购买了超市和药房的商品,两家门店的配送费、起送价和送达时间都不一样,因此不能把商品混在一起结算。
这次单独设计了门店购物车,Redis Key 中同时记录用户编号和门店编号。这样同一个用户在不同门店加购商品时,数据不会互相影响。
购物车已经支持:
- 加入商品
- 增加数量
- 减少数量
- 删除商品
- 限制单件商品最大数量
- 实时重新计算商品金额
- 判断是否达到门店起送价
- 满 99 元免配送费
这里还处理了一个容易忽略的问题:如果购物车没有达到起送价,不能直接禁止用户进入结算页,否则用户连增加商品数量的机会都没有。
现在的处理方式是允许用户进入结算页并继续修改数量,但提交支付按钮会被禁用,同时明确提示还差多少钱达到起送价。
四、结算页面补齐配送信息
结算页面没有直接照搬普通商品订单,而是增加了即时零售需要的信息。
目前支持:
- 选择收货地址
- 使用校园默认地址
- 尽快送达
- 预约配送
- 填写配送备注
- 使用即时零售优惠券
- 计算商品金额
- 计算配送费
- 计算优惠金额
- 显示最终实付金额
即时零售优惠券设置为满 39 元减 5 元,用户领取后会放入自己的优惠券包,达到条件时自动使用。
优惠券抵扣后,支付金额会减少,但积分和成长值仍然按照商品原金额计算。因为优惠券本身也是用户通过活动或者积分获得的,如果再按照优惠后的金额发放积分,相当于重复扣减用户权益。
五、打通支付宝沙箱支付
结算页完成后,把即时零售订单接入了现有的支付宝沙箱支付。
这次没有重新写一套支付逻辑,而是在现有活动支付单的基础上增加了 local_retail 类型。支付单号使用 CMP-LR-* 前缀,方便回调时区分普通订单、营销活动、社区团购和即时零售订单。
支付成功后会依次完成:
- 验证支付宝回调签名和支付金额
- 读取支付前保存的订单草稿
- 创建即时零售订单
- 清空当前门店购物车
- 核销已经使用的优惠券
- 发放积分和成长值
- 创建配送通知
- 跳转即时零售支付成功页面
回调还做了幂等处理。同一个支付单即使被支付宝重复通知,也不会重复创建订单。
支付成功页面增加了“查看即时零售订单”“继续逛附近”和“查看配送消息”三个入口,用户支付结束后不用再自己寻找订单位置。
六、增加配送订单状态
即时零售订单没有复用普通快递订单页面,而是单独做了订单中心。
订单中会展示:
- 门店名称
- 商品信息
- 商品数量
- 配送地址
- 商品金额
- 配送费
- 优惠金额
- 支付交易号
- 配送备注
- 预计送达时间
- 当前配送状态
订单支付完成后进入“配送中”状态,到达预计配送时间后更新为“已送达”。
目前这个状态变化是根据预计送达时间模拟的,后续如果接入真实骑手平台,可以改成通过配送平台的回调更新状态。
七、处理服务地址和启动问题
今天还处理了一次本机网络地址变化。
当前服务地址调整为:
172.20.10.4
之前部分 RPC 客户端在服务并发启动时,会错误地把地址固定成 127.0.0.1,导致服务明明已经启动,但前端调用不到对应的 RPC 服务。
这次给前端、购物车和结算服务补充了显式 RPC 地址,减少启动顺序对服务发现结果的影响。
前端目前运行在:
http://127.0.0.1:8091
公网内网穿透地址为:
https://c671043.r7.cpolar.cn
本地和公网的即时零售页面都已经完成访问验证。
八、测试不只看页面能不能打开
页面开发完成后,执行了前端项目的完整测试:
go test ./...
测试全部通过。
除此之外,还使用真实买家会话走了一遍业务流程:
- 登录买家账号
- 进入即时零售首页
- 选择门店商品
- 加入门店购物车
- 修改商品数量
- 进入结算页面
- 检查地址、优惠券和配送信息
- 打开即时零售订单中心
- 验证公网访问
相比只检查页面是否返回 200,这种验证方式更容易发现“页面能打开,但是按钮不能用”的问题。
九、今天遇到的几个问题
今天开发过程中也踩了一些小坑。
第一个是 PowerShell 的 $HOME 是内置只读变量,创建模板时如果使用 $home 作为变量名,会直接报错。Windows 下变量名不区分大小写,所以后来改成了 $homeTemplate。
第二个是 Go 模板没有注册自定义函数时,不能直接使用 add 和 sub。购物车数量加减改成了在后端提前计算增加后的数量和减少后的数量,模板只负责提交结果。
第三个是 Go 模板嵌套 range 后,当前上下文会发生变化。门店列表中继续遍历商品时,需要先把门店保存到局部变量,否则很容易取到错误的数据。
另外,当前环境没有启动 Consul 和 OpenTelemetry Collector,因此日志中还会出现服务注册和链路上报失败的提示。这两个问题暂时不影响商城业务,但正式部署时还是需要补齐。
十、今天的收获
今天最大的感受是,电商项目里最难的部分往往不是页面,而是状态之间的关系。
加购成功后购物车要变化,优惠券使用后要核销,支付成功后要创建订单,订单生成后还要发放积分和通知。如果其中任何一步没有处理好,用户看到的结果就会前后矛盾。
即时零售模块目前已经具备一条完整的基础链路:
附近门店
→ 商品详情
→ 门店购物车
→ 配送结算
→ 支付宝支付
→ 即时零售订单
→ 配送状态与消息通知
下一步准备继续按照原型图补后续业务,同时逐步替换更符合生鲜、便利店和药房场景的商品数据与图片。等主要业务全部完成后,再统一处理部署、监控和服务治理问题。

301

被折叠的 条评论
为什么被折叠?



