本地电竞服务交易系统架构设计与实战:从同城服务撮合到订单履约

首段:本地电竞服务交易系统是一套面向同城电竞服务供需撮合的技术平台,覆盖电竞馆座位/包间预约、陪练约战、赛事报名、设备租赁、组局拼桌等场景。它和普通电商的区别在于:服务发生在本地、履约时间强、位置敏感、供需双方需要即时沟通。因此设计重点不是商品详情页,而是 LBS 检索、订单状态机、支付分账、履约核销与风控。下文给出可落地的架构、表结构、核心代码与部署步骤。

一、需求抽象与领域建模

  • 角色:用户、服务者/场馆、平台运营、财务/客服? 不要公司。

  • 核心实体:服务项目、SKU? 服务时段、场地、设备、陪练档期、赛事名额。

  • 交易对象是"服务时段+本地履约"。

  • 关键能力:LBS、日历库存、订单、支付、退款、核销、评价、IM。

  • 表结构:user, merchant? 避免商户?可以 `service_provider`,`venue`, `service_item`, `service_slot`, `order`, `order_item`, `payment_record`, `verification_code`。

代码块:

java 复制代码
```sql
CREATE TABLE service_slot (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  provider_id BIGINT NOT NULL,
  venue_id BIGINT NOT NULL,
  title VARCHAR(128) NOT NULL,
  start_time DATETIME NOT NULL,
  end_time DATETIME NOT NULL,
  latitude DECIMAL(10,6) NOT NULL,
  longitude DECIMAL(10,6) NOT NULL,
  geo_hash VARCHAR(12) NOT NULL,
  status TINYINT NOT NULL DEFAULT 0,
  version INT NOT NULL DEFAULT 0,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY idx_geo_status_time (geo_hash, status, start_time),
  KEY idx_provider_time (provider_id, start_time)
);
```

注意 `DECIMAL(10,6)` 是经纬度,没问题。

二、技术架构与模块拆分

推荐:用户端 uniapp(Vue 语法)覆盖 H5/APP/小程序;服务者端 uniapp 或单独;管理后台 Vue + Element UI;后端 Spring Boot + MyBatis Plus + MySQL;Redis 做缓存/分布式锁;WebSocket/IM 做沟通;对象存储存凭证;消息队列异步通知。

模块:网关、用户、服务资源、交易、支付、履约、消息、运营后台。

部署:Nginx + 前端静态,后端 jar,MySQL 主从,Redis。提供技术文档、资料准备、部署文档。不要营销。

可以写代码:MyBatis Plus 分页查询附近服务时段。用 GeoHash 粗筛 + Haversine 精算。SQL:

java 复制代码
```sql
SELECT id, provider_id, venue_id, title, start_time, end_time, latitude, longitude,
       (6371000 * ACOS(
         COS(RADIANS(#{lat})) * COS(RADIANS(latitude)) *
         COS(RADIANS(longitude) - RADIANS(#{lng})) +
         SIN(RADIANS(#{lat})) * SIN(RADIANS(latitude))
       )) AS distance_m
FROM service_slot
WHERE status = 0
  AND start_time BETWEEN #{start} AND #{end}
  AND geo_hash LIKE CONCAT(#{geoHashPrefix}, '%')
HAVING distance_m <= #{radius}
ORDER BY distance_m ASC
LIMIT 50;
```

MySQL HAVING 可以用别名? MySQL 允许 HAVING 别名。可以。

三、核心实现:LBS 检索、订单状态机与履约

订单状态机:待支付、已支付/待履约、履约中、待核销、已完成、已取消、退款中、已退款。用枚举和状态迁移表。

Java:

java 复制代码
```java
public enum OrderStatus {
    WAIT_PAY, PAID, SERVING, WAIT_VERIFY, FINISHED, CANCELED, REFUNDING, REFUNDED
}
```

状态迁移:

java 复制代码
```java
private static final Map<OrderStatus, Set<OrderStatus>> FLOW = Map.of(
    WAIT_PAY, Set.of(PAID, CANCELED),
    PAID, Set.of(SERVING, REFUNDING, CANCELED),
    SERVING, Set.of(WAIT_VERIFY, REFUNDING),
    WAIT_VERIFY, Set.of(FINISHED, REFUNDING),
    REFUNDING, Set.of(REFUNDED),
    FINISHED, Set.of(),
    CANCELED, Set.of(),
    REFUNDED, Set.of()
);
public boolean canTransfer(OrderStatus from, OrderStatus to) {
    return FLOW.getOrDefault(from, Set.of()).contains(to);
}
```

注意 Java Map.of 多 10 对,这里 8 对 OK。但 `Map.of` 需要 Java 9+。可以。下单防超卖:索引 + 乐观锁。SQL:

java 复制代码
```sql
UPDATE service_slot
SET status = 1, version = version + 1
WHERE id = #{slotId} AND status = 0 AND version = #{version};
```
如果影响行 0,重试或提示。订单创建与库存锁定放本地事务,支付回调再更新状态。

核销:生成一次性核销码,Redis 记录 `verify:code:{code}`,TTL 到服务结束。核销接口用 Lua 原子删除。代码:
```lua
if redis.call('GET', KEYS[1]) == ARGV[1] then
    redis.call('DEL', KEYS[1])
    return 1
else
    return 0
end
```

Java 调用。

IM:WebSocket 或第三方?不要第三方品牌。可以用 WebSocket + 离线消息表。

四、支付回调、幂等与数据一致性

支付回调必须幂等:交易号 + 状态机。伪代码:

java 复制代码
```java
@Transactional
public void handlePayCallback(String tradeNo, String channelOrderNo) {
    PaymentRecord record = paymentMapper.selectByTradeNoForUpdate(tradeNo);
    if (record == null) throw new IllegalArgumentException();
    if (record.getStatus() == PaymentStatus.SUCCESS) return;
    record.setStatus(PaymentStatus.SUCCESS);
    record.setChannelOrderNo(channelOrderNo);
    paymentMapper.updateById(record);
    orderService.markPaid(record.getOrderId(), tradeNo);
}
```

注意 `for update` 悲观锁。也可以用索引。消息队列终一致。退款:状态机 + 异步重试 + 对账。

分账/结算:按服务完成事件触发,记录分账明细,不写具体金额。

风控:频率限制、实名、地理位置校验、核销码短时有效、黑名单。

FAQ

Q1 本地电竞服务交易系统和普通商城有什么区别?

A:本地、时效、位置、履约。

Q2 如何做附近服务检索?

A:GeoHash 粗筛 + Haversine 精算,Redis GEO 可选,MySQL 空间索引可选。

Q3 订单超卖怎么避免?

A:索引、乐观锁、Redis 分布式锁、状态机。

Q4 支付回调重复通知怎么办?

A:幂等表 + 交易号 + 状态机 + 锁。

Q5 技术栈如何选型?

A:后端 Spring Boot + MyBatis Plus + MySQL,前端 uniapp + Vue + Element UI,缓存 Redis,消息队列异步。

Q6 部署文档应包含什么?

A:环境依赖、数据库初始化、配置项、启动脚本、Nginx、日志、备份、回滚。

注意字数。我们可以扩展每个部分,确保 1200-2500。不要,不要

标题

首段直接回答。

一、需求抽象与领域建模

介绍角色、核心实体、表结构、SQL。

二、技术架构与模块拆分

推荐技术栈、模块、部署步骤。

三、核心链路:LBS 检索与订单状态机

SQL、Java、防超卖、核销 Lua。

四、支付回调、幂等与数据一致性

伪代码、消息队列、退款、风控。

FAQ

5-6 问答。

可以加小标题?不能超过 5 个二级标题。可以加三级标题?要求包含 3-5 个二级标题。三级标题可以吗?没有禁止。但可能增加结构。可以少量使用 `###`。但二级标题数 5。可以。三级标题不算?可以。但为简洁,用列表和代码。

注意首段直接回答问题。开头不要"本文"。直接:"本地电竞服务交易系统是一套..."。可以。

字数:估算 2200。

让我们写。

需要代码块与步骤清晰。可以写部署步骤:

  1. 初始化 MySQL,执行建表 SQL,配置 InnoDB 与字符集。

  2. 配置 Redis,用于会话、库存锁、核销码、附近检索缓存。

  3. 后端打包 Spring Boot,MyBatis Plus 配置分页插件与乐观锁插件。

  4. 前端 uniapp 与 Vue 管理后台分别构建,Nginx 托管。

  5. 配置支付回调白名单、日志采集、备份与回滚。

可以。

支付回调伪代码没有金额。

订单状态枚举。

LBS SQL。

核销 Lua。

MyBatis Plus 乐观锁插件?

相关推荐
daidaidaiyu9 小时前
ThingsBoard 集群的核心逻辑源码分析
java
2601_962885729 小时前
如何用 Python 自动识别股票的支撑位与压力位?
开发语言·python
爱吃奥利奥_wen9 小时前
面向对象三板斧:封装、继承、多态,到底在“装“什么、“承“什么、“变“什么?
开发语言·经验分享·c#
我可能是个假开发9 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong10 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
WL学习笔记11 小时前
日期类(C++)
开发语言·c++·日期类实现
【JAVA】玩家11 小时前
Spring核心原理全解析:从零到生产实战
java·后端·spring
Wang's Blog11 小时前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
谢亮_vipxieliang11 小时前
Go map与结构体的正确使用
开发语言·golang·哈希算法
H.莓飛12 小时前
【C++】命名空间、缺省参数、函数重载与引用
linux·开发语言·c++·visual studio