vr-shopxo-plugin/docs/07_SHOPXO_PLUGIN_MECHANISM.md

489 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# ShopXO 插件开发文档
> 来源doc.shopxo.net 官方文档 + PluginsService.php 源码 + CSDN/搜索补充
> 版本ShopXO v2.2.0+(基于 ThinkPHP 8
> 整理:西莉雅
---
## 一、目录结构
### 系统结构v2.2.0+
```
www/ # WEB部署目录或子目录
├─ app/ # 应用目录
│ ├─ plugins/ # 插件目录
│ │ ├─ {plugins_name}/ # 插件目录(目录名 = config.json 的 plugins 字段)
│ │ │ ├─ config.json # ★ 插件配置(核心文件)
│ │ │ ├─ admin/ # 后台管理
│ │ │ │ ├─ controller/ # 控制器
│ │ │ │ └─ view/ # Blade 视图app/plugins/{name}/view/admin/
│ │ │ ├─ index/ # 前台用户端
│ │ │ │ ├─ controller/
│ │ │ │ └─ view/
│ │ │ ├─ api/ # API接口端
│ │ │ │ └─ controller/
│ │ │ ├─ service/
│ │ │ │ └─ BaseService.php # ★ 基础服务类(配置处理、菜单等)
│ │ │ ├─ Event.php # ★ 生命周期事件类
│ │ │ ├─ common.php # 公共函数
│ │ │ └─ hook/ # 钩子类目录(可选)
│ │ └─ ...
│ ├─ admin/ # 后台管理模块
│ ├─ index/ # 前台模块
│ ├─ api/ # API接口模块
│ ├─ common.php # 公共函数文件
│ └─ event.php # 事件定义文件
├─ config/ # 全局配置
├─ public/ # WEB目录对外访问
│ ├─ index.php # 前端入口
│ ├─ admin.php # 后台入口
│ └─ api.php # API入口
└─ vendor/ # Composer依赖
```
### 插件静态资源路径
```
public/static/plugins/{plugins_name}/ # JS/CSS/图片
├─ index/ # 前台静态资源
└─ admin/ # 后台静态资源
```
---
## 二、config.json — 插件配置文件(核心)
### 标准结构
```json
{
"base": {
"name": "插件显示名称",
"version": "1.0.0",
"author": "作者名",
"desc": "插件描述",
"plugins": "vr_ticket", // ★ 必须与目录名一致(唯一标识)
"is_apps_ten_pay": 0
},
"element": [
{
"element": "input",
"type": "text",
"name": "api_key",
"title": "API密钥",
"value": "",
"message": "请输入API密钥"
}
],
"hook": {
"app_init": ["\\app\\plugins\\vr_ticket\\hook\\AppInit"]
},
"backend_hook": {
"admin_user_view_right": ["\\app\\plugins\\vr_ticket\\hook\\AdminUserViewRight"]
}
}
```
### element 支持的表单类型
| element | 说明 | 关键参数 |
|---------|------|---------|
| `input` | 单行文本 | `type`: text/password/number |
| `textarea` | 多行文本 | |
| `radio` | 单选 | `data`: `[{name, value}]` |
| `checkbox` | 多选 | `data`: 同上 |
| `select` | 下拉选择 | 同上 |
| `upload` | 文件上传 | |
### hook vs backend_hook
- `hook`:前端/全局钩子,在用户端触发
- `backend_hook`:后台管理钩子,在 admin 模块触发
---
## 三、钩子系统Hook
ShopXO 基于 ThinkPHP 6 的 Event/Facade 机制实现插件钩子。
### 已知系统钩子(从源码/文档整理)
| 钩子名称 | 触发时机 | 常见用途 |
|---------|---------|---------|
| `app_init` | 应用初始化(最早) | 全局预处理 |
| `app_begin` | 应用开始 | 初始化扩展 |
| `module_init` | 模块初始化 | 模块级别扩展 |
| `action_begin` | 操作开始执行前 | 权限校验、前置处理 |
| `view_filter` | 视图内容过滤 | 输出内容处理 |
| `log_write` | 日志写入 | 自定义日志 |
| `app_end` | 应用结束 | 收尾处理 |
| `admin_user_view_right` | 管理员查看用户详情右侧 | 扩展用户信息面板 |
| `plugins_view_welcome` | 插件欢迎页 | 自定义插件首页 |
> **重要**:开启开发者模式后,后台应用管理页面会显示所有可用钩子的提示名称。
> 路径:`config/shopxo.php` → `is_develop: true`
### 前端钩子注册方式
`config.json` 中:
```json
"hook": {
"钩子名称": ["\\app\\plugins\\{name}\\hook\\HookClass"]
}
```
### 后台钩子注册方式
```json
"backend_hook": {
"钩子名称": ["\\app\\plugins\\{name}\\hook\\HookClass"]
}
```
### 钩子类示例
```php
<?php
// app/plugins/vr_ticket/hook/AppInit.php
namespace app\plugins\vr_ticket\hook;
class AppInit
{
public function handle($params = [])
{
// 处理逻辑
return ['code' => 0, 'msg' => 'success'];
}
}
```
---
## 四、插件生命周期事件Event
插件可以通过 `Event.php` 响应系统生命周期回调。
### 生命周期事件列表
| 事件方法 | 触发时机 | 返回值意义 |
|---------|---------|-----------|
| `Upload` | 上传插件包时 | |
| `BeginInstall` | 安装前(验证) | 非0 → 阻止安装 |
| `Install` | 执行安装 | |
| `Uninstall` | 卸载插件 | |
| `Download` | 下载插件 | |
| `BeginUpgrade` | 更新前(验证) | 非0 → 阻止更新 |
| `Upgrade` | 执行更新 | |
| `Delete` | 删除插件 | |
### Event.php 示例
```php
<?php
// app/plugins/vr_ticket/Event.php
namespace app\plugins\vr_ticket;
class Event
{
// 安装前验证
public function BeginInstall($params = [])
{
// 检查依赖等
return DataReturn('可以安装', 0);
}
// 执行安装
public function Install($params = [])
{
// 创建数据库表等
return DataReturn('安装成功', 0);
}
// 卸载
public function Uninstall($params = [])
{
// 清理数据等
return DataReturn('卸载成功', 0);
}
// 支付回调事件(需配合支付插件使用)
public function PaySuccess($params = [])
{
// $params 包含 order_id, pay_price, payment 等
return DataReturn('处理成功', 0);
}
}
```
---
## 五、控制器与路由
### URL 路由格式
```
/plugins/{group}?pluginsname={plugins}&pluginscontrol={control}&pluginsaction={action}
```
示例:
```
/plugins/index?pluginsname=vr_ticket&pluginscontrol=index&pluginsaction=index
/plugins/admin?pluginsname=vr_ticket&pluginscontrol=admin&pluginsaction=index
/plugins/api?pluginsname=vr_ticket&pluginscontrol=api&pluginsaction=notify
```
### 控制器命名规范
```
app/plugins/{name}/{group}/controller/{Control}.php
```
- `group`: `index`(前台)| `admin`(后台)| `api`API
- `Control`: 首字母大写,如 `Index`, `Admin`, `Order`
### 控制器基类结构
```php
<?php
// app/plugins/vr_ticket/index/controller/Index.php
namespace app\plugins\vr_ticket\index\controller;
class Index
{
// 前台首页
public function index($params = [])
{
return MyView('', ['data' => $data]);
}
// JSON API
public function detail($params = [])
{
return DataReturn('success', 0, $data);
}
}
```
```php
<?php
// app/plugins/vr_ticket/admin/controller/Index.php
namespace app\plugins\vr_ticket\admin\controller;
class Index
{
public function index($params = [])
{
IsLogin(); // 后台需登录校验
return MyView('', []);
}
}
```
---
## 六、BaseService — 基础服务类
```php
<?php
// app/plugins/vr_ticket/service/BaseService.php
namespace app\plugins\vr_ticket\service;
use think\facade\Db;
class BaseService
{
// 附件字段(配置中涉及文件上传的字段名)
public static $base_config_attachment_field = [];
// 私有字段(不返回给前端的敏感字段)
public static $base_config_private_field = ['secret_key'];
// 后台权限菜单(可选)
public static function AdminPowerMenu()
{
return [
['name' => '场次管理', 'url' => MyUrl('plugins/admin', ['pluginsname' => 'vr_ticket', 'pluginscontrol' => 'event', 'pluginsaction' => 'index'])],
['name' => '门票核销', 'url' => MyUrl('plugins/admin', ['pluginsname' => 'vr_ticket', 'pluginscontrol' => 'verify', 'pluginsaction' => 'index'])],
];
}
// 配置数据处理(可选)
public static function BaseConfigHandle($config)
{
return $config;
}
}
```
### 读取插件配置
```php
use app\service\PluginsService;
$data = PluginsService::PluginsData('vr_ticket');
// 返回 ['code' => 0, 'msg' => 'success', 'data' => [...配置数据]]
```
### 保存插件配置
```php
PluginsService::PluginsDataSave([
'plugins' => 'vr_ticket',
'data' => $params
], $attachment_field);
```
---
## 七、模板引擎Blade
ShopXO 使用 Blade 模板(.blade.php
### 前台视图路径
```
app/plugins/vr_ticket/view/index/index.blade.php # 前台
app/plugins/vr_ticket/view/admin/index.blade.php # 后台
```
### 视图中引用静态资源
```blade
<img src="{{ \app\common.phpStaticAttachmentUrl('logo.png', 'images', 'vr_ticket') }}" />
<!-- 或直接写死路径 -->
<link href="/static/plugins/vr_ticket/index/css/style.css" rel="stylesheet">
<script src="/static/plugins/vr_ticket/index/js/app.js"></script>
```
### 视图渲染
```php
// 渲染插件视图自动读取插件view目录
return MyView('index', ['data' => $data]);
// 路径app/plugins/vr_ticket/view/index/index.blade.php
// 渲染后台视图
return MyView('admin/index', ['data' => $data]);
```
### 公共模板变量
`app/plugins/vr_ticket/common.php` 中定义函数,可供所有视图调用。
---
## 八、调试与开发模式
### 开启开发者模式
路径:`config/shopxo.php`
```php
'is_develop' => true, // 从 false 改为 true
```
开启后后台应用管理页面会显示钩子名称提示。
### 日志文件
```
runtime/log/{年份}/{月份}.log
runtime/log/2025/09.log
```
### 调试模式
`.env` 中设置:
```env
APP_DEBUG=true
```
---
## 九、支付插件extend/ 方式)
ShopXO 的支付插件放在 `extend/payment/` 目录,与通用插件不同。
```
extend/
└─ payment/
├─ Alipay.php # 支付宝支付
└─ Weixin.php # 微信支付
```
支付插件实现支付接口集成,订单支付成功后会触发事件通知。
---
## 十、与 vr-shopxo-plugin 需求对应的关键点
### VR 票务插件需要对接的核心功能
#### 1. 票务场次管理(后台)
- **路由**`/plugins/admin?pluginsname=vr_ticket&pluginscontrol=event&pluginsaction=index`
- **数据库**:需创建 `vr_events`(场次)、`vr_sessions`(场次时间/库存)、`vr_tickets`(电子票)
- **后台菜单**:通过 `BaseService::AdminPowerMenu()` 注册
#### 2. 支付回调处理API
- **路由**`/plugins/api?pluginsname=vr_ticket&pluginscontrol=api&pluginsaction=notify`
- **触发方式**:支付插件在支付成功后调用此接口
- **关键逻辑**
1. 验证支付签名
2. 创建 `vr_tickets` 记录AES_Encrypt 防伪造 QR
3. 更新 `vr_sessions` 库存
#### 3. 观演人信息收集
- **触发时机**:订单 `pending``paid` 过渡阶段
- **实现方式**:可在订单扩展字段或 `OrderService` 中 hook
- **字段**:姓名、手机号、身份证(可选)
#### 4. QR 电子票展示(前台)
- **路由**`/plugins/index?pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=detail`
- **数据源**`vr_tickets` 表
- **展示**:票面信息 + QR 码图片
#### 5. B 端扫码核销(后台)
- **路由**`/plugins/admin?pluginsname=vr_ticket&pluginscontrol=verify&pluginsaction=index`
- **方式**:微信扫码枪或管理员扫码页面
- **逻辑**`vr_tickets.status = 'used'` + 核销时间戳
### 关键开发顺序
```
Phase 1: 插件骨架config.json + BaseService + Event
Phase 2: 数据库迁移vr_events, vr_sessions, vr_tickets
Phase 3: 后台场次管理 CRUDadmin/controller
Phase 4: 前台购票流程 + 支付回调api/controller + notify
Phase 5: QR 票生成 + 观演人信息
Phase 6: B 端核销页面
```
---
## 十一、参考资源
| 资源 | URL |
|------|-----|
| 官方文档站 | https://doc.shopxo.net/ |
| 插件开发索引 | https://doc.shopxo.net/article/3.html |
| 目录结构 | https://doc.shopxo.net/article/4/265292898306621440.html |
| 应用商店 | https://store.shopxo.net/ |
| GitHub 源码 | https://github.com/gongfuxiang/shopxo |
| Gitee 源码 | https://gitee.com/zongzhige/shopxo |
| ThinkPHP 8 文档 | https://www.kancloud.cn/manual/thinkphp6_0/ |