vr-shopxo-plugin/docs/08_SHOPXO_REQUIREMENTS_MAPP...

6.5 KiB
Raw Blame History

vr-shopxo-plugin 需求对照分析

ShopXO 插件机制 vs VR 演唱会票务需求 基于 shopxo-plugin-dev.md 整理


一、票务核心功能 vs ShopXO 机制

1. 商品模型(票 = item_type='ticket'

ShopXO 原生商品表 itemitem_type 字段扩展能力,但票务的特殊性在于:

  • 票有时间场次session普通商品无此概念
  • 票需要观演人信息,普通商品无此字段
  • 票需要 QR 电子票,普通商品无此交付物

结论:票务插件需创建独立表 vr_events + vr_sessions + vr_tickets,与 ShopXO items 表平行存在,通过 item_id 关联。

2. 库存扣减(防超卖)

ShopXO 原生库存扣减SELECT → UPDATE 两步,非原子操作,有超卖风险。

VR 票务方案:在支付回调 api/notify 中,使用 Postgres 风格 SQLShopXO 是 MySQL需换为 MySQL 原子写法):

-- MySQL 原子扣库存FOR UPDATE SKIP LOCKED 等效写法)
START TRANSACTION;
SELECT stock FROM vr_sessions WHERE id=? AND stock>=? FOR UPDATE;
-- 如果库存足够
UPDATE vr_sessions SET stock=stock-? WHERE id=?;
INSERT INTO vr_tickets (...) VALUES (...);
COMMIT;

关键:必须在支付回调的 API 控制器中完成,不能依赖 ShopXO 原有订单流程。

3. 微信支付回调

ShopXO 支持支付插件机制(extend/payment/),但票务插件需要自己的支付回调路由:

POST /plugins/api?pluginsname=vr_ticket&pluginscontrol=api&pluginsaction=notify

ShopXO 原生支付回调由支付插件处理,票务插件的回调是:用户付款成功 → 票务插件生成电子票

注意ShopXO 的微信支付插件本身已处理微信支付回调,我们需要在 Event.php 中监听支付成功事件或在回调路由中自己调用微信API验证。

4. 观演人信息

ShopXO 订单扩展字段能力有限,建议:

  • 创建 vr_attendees 表(姓名、手机、证件号)
  • 在订单 paid 状态的 webhook 或手动触发时写入
  • 通过订单扩展字段 extensionJSON关联 vr_attendees

5. QR 电子票

ShopXO 附件上传/管理能力完善,但 QR 生成需自己实现:

  • PHP QR Codephpqrcode/phpqrcode Composer 包
  • 存储:vr_tickets.qr_data 存 QR 内容AES_EncryptQR 图片可 CDN 化

6. B 端扫码核销

ShopXO 后台有门店核销机制(多门店插件),但票务核销是独立场景:

  • 插件后台:admin/verify 控制器
  • 扫码枪:调用微信扫一扫或直接输入 QR code
  • 核销状态更新:vr_tickets.status = 'used'

二、ShopXO 原有功能借用分析

票务需求 ShopXO 原生能力 插件扩展方式 优先级
商品展示 items 表 创建 vr_events 场次表 P0
会员体系 完善 不需开发 P0
钱包/余额 完善 不需开发 P0
优惠券 完善 不需开发 P0
微信支付 支付插件 直接用(不需改) P0
订单管理 orders 表 扩展 extension 字段 P0
库存扣减 ⚠️ 非原子 支付回调自己写 P0
场次/SKU 独立表 vr_sessions P0
观演人信息 独立表 vr_attendees P0
QR 电子票 phpqrcode + 插件表 P0
B端核销 插件后台 admin 页面 P1
多场馆 vr_events 已有场馆字段 P2
周边商品 items 原生 不需插件 P0

三、插件架构设计

数据库 E-R 图

vr_events (场次)
  └── vr_sessions (场次时间/库存)  1:N
        └── vr_tickets (电子票)  1:N
              └── vr_attendees (观演人)  N:1

items (ShopXO原生) ←── item_id ──→ vr_events (通过 item_id 关联)
orders (ShopXO原生) ←─ extension ──→ vr_attendees (JSON关联)

插件目录

app/plugins/vr_ticket/
├── config.json              # 插件配置(钩子:支付回调)
├── admin/
│   ├── controller/
│   │   ├── Event.php        # 场次管理 CRUD
│   │   ├── Ticket.php        # 电子票管理
│   │   └── Verify.php       # 核销管理
│   └── view/
│       ├── event/            # 场次管理视图
│       ├── ticket/
│       └── verify/           # 核销页面
├── index/
│   ├── controller/
│   │   ├── Index.php         # 前台插件首页
│   │   └── Ticket.php        # 我的票/QR展示
│   └── view/
│       ├── ticket/
│       └── my_tickets.blade.php
├── api/
│   └── controller/
│       └── Notify.php        # ★ 支付回调(最关键)
├── service/
│   └── BaseService.php
├── Event.php                 # 生命周期事件
├── common.php
└── hook/
    └── OrderPaid.php         # 订单支付成功钩子(可选)

支付回调流程

微信支付回调 → /plugins/api?pluginsname=vr_ticket&pluginscontrol=api&pluginsaction=notify
    │
    ├─ 1. 验证签名微信API
    ├─ 2. 查询 ShopXO orders 表确认支付状态
    ├─ 3. 读取订单 extension 中的 vr_session_id + vr_attendees
    ├─ 4. 原子扣库存vr_sessions
    ├─ 5. 生成 vr_ticketsAES_Encrypt QR content
    ├─ 6. 写入 vr_attendees 记录
    └─ 7. 更新 orders.extension票ID列表

四、已知限制与绕过方案

限制 影响 绕过方案
ShopXO 订单流程不可扩展 无法在原生下单流程中插入观演人表单 独立购票页,支付后写入观演人
支付回调由支付插件处理 票务插件无法直接拦截微信回调 支付插件 → Event.PaySuccess → 票务钩子
插件不能 Hook 订单状态变更 无法监听 paid→fulfilled 支付回调中直接处理,或定时轮询
DIY 拖拽装修不可代码化 票务展示页无法 AI 生成 票务页面全部走插件视图,不走 DIY
MySQL 非 Postgres 无 FOR UPDATE SKIP LOCKED START TRANSACTION + SELECT ... FOR UPDATE

五、下一步行动

  1. 先确认支付插件的 PaySuccess 事件 — 从 extend/payment/ 源码确认是否触发 Event.PaySuccess
  2. 创建插件骨架 — config.json + BaseService + Event.php
  3. 设计数据库迁移脚本 — vr_events, vr_sessions, vr_tickets, vr_attendees
  4. 实现支付回调 — api/Notify.php核心链路