简介
本规范面向 DouPHP 的插件开发,聚焦于 plugin 目录下的插件组织方式、必需与可选文件、配置元数据(manifest.php)、以及 Provider/Service 的职责划分与协作关系。文档同时给出标准插件目录模板,涵盖配置文件、核心逻辑、资源文件的放置位置,并说明版本管理、依赖声明、权限配置等元数据的定义方法。
项目结构
DouPHP 的插件统一位于根目录下的 plugin 目录中,每个插件一个独立子目录。根据实现方式不同,插件可分为两类:
- 现代类式插件:以 manifest.php + Provider + Service 为核心,遵循命名空间与接口契约,便于系统统一管理生命周期与配置。
- 传统脚本式插件:以 setting.plugin.php、work.plugin.php、inc.plugin.php 等脚本为主,通过全局变量和约定路径进行交互。
graph TB
subgraph "插件根目录"
M["manifest.php<br/>现代插件"]
P["Provider.php<br/>现代插件"]
S["Service.php<br/>现代插件"]
A["inc.plugin.php<br/>传统插件入口"]
B["setting.plugin.php<br/>传统插件配置表单"]
C["work.plugin.php<br/>传统插件工作逻辑"]
D["notify_url.php / return_url.php<br/>回调与跳转"]
E["icon.png / sdk / images / qrcode.php<br/>资源与SDK"]
end
M --> P
P --> S
A --> B
A --> C
C --> D
E -.-> C
核心组件
- manifest.php(现代插件必需)
- 作用:声明插件分组、提供器类名等元数据,供系统加载与识别。
- 关键字段:
- plugin_group:插件所属组(如 payment)。
- provider:Provider 类的完全限定类名。
- Provider(现代插件必需)
- 作用:对外暴露插件能力(如支付开始、通知、完成、查询),负责参数校验与调用 Service。
- 典型方法:pluginId、meta、start、notify、finish、query。
- Service(现代插件推荐)
- 作用:封装具体业务逻辑(如对接第三方 SDK、构建请求、处理回调、状态机推进)。
- 与 Provider 的关系:Provider 仅做薄封装与路由,Service 承载复杂逻辑。
架构总览
现代插件采用“配置驱动 + 接口契约”的方式,由系统根据 manifest.php 找到 Provider,再由 Provider 委托 Service 执行具体流程。
sequenceDiagram
participant Sys as "系统"
participant Prov as "Provider"
participant Svc as "Service"
participant Ext as "第三方SDK/服务"
Sys->>Prov : 调用 start()
Prov->>Svc : 委托 start(request)
Svc->>Ext : 发起支付请求
Ext-->>Svc : 返回支付链接/结果
Svc-->>Prov : 返回结果
Prov-->>Sys : 返回响应
Sys->>Prov : 调用 notify()/finish()
Prov->>Svc : 委托处理回调
Svc->>Ext : 验签/查询
Ext-->>Svc : 返回验证结果
Svc-->>Prov : 返回处理结果
Prov-->>Sys : 返回响应
详细组件分析
现代插件:支付宝示例
- manifest.php
- 声明插件分组为 payment,并提供 Provider 类名。
- AlipayProvider
- 实现支付相关接口,提供 meta 描述与配置字段,将 start/notify/finish/query 委托给 Service。
- AlipayService
- 封装支付宝 SDK 调用、配置组装、回调验签、订单状态推进、主动对账查询等。
classDiagram
class AlipayProvider {
+pluginId() string
+meta() array
+start(PaymentRequest) string
+notify(PaymentCallbackPayload) string
+finish(PaymentCallbackPayload) string
+query(PaymentQueryRequest) PaymentQueryResult
-service : AlipayService
}
class AlipayService {
+start(PaymentRequest) string
+notify(PaymentCallbackPayload) string
+finish(PaymentCallbackPayload) string
+query(PaymentQueryRequest) PaymentQueryResult
-buildConfig() array
-encodeRaw(data) string
-responseToArray(response) array|null
}
AlipayProvider --> AlipayService : "组合使用"
传统插件:余额支付示例
- inc.plugin.php
- 插件入口,初始化环境、读取插件配置、设置回调地址。
- setting.plugin.php
- 定义插件唯一ID、名称、描述、版本、分组及配置表单字段。
- work.plugin.php
- 渲染支付界面、校验登录与模块启用、计算余额、输出提交表单至 notify_url.php。
flowchart TD
Start(["进入插件"]) --> LoadCfg["加载插件配置"]
LoadCfg --> CheckMoney{"是否启用钱包模块?"}
CheckMoney -- 否 --> ShowWarn["提示未启用钱包"]
CheckMoney -- 是 --> CheckLogin{"是否已登录?"}
CheckLogin -- 否 --> ShowLogin["提示先登录"]
CheckLogin -- 是 --> CalcBal["计算用户余额与应付金额"]
CalcBal --> Enough{"余额是否充足?"}
Enough -- 否 --> ShowShort["显示差额与充值引导"]
Enough -- 是 --> RenderForm["渲染支付表单(含token)"]
RenderForm --> Submit["POST 到 notify_url.php"]
其他现代插件示例
- 微信支付(wxpay)
- manifest.php 声明分组与 Provider 类名。
- 货到付款(cod)
- manifest.php 声明分组与 Provider 类名。
依赖关系分析
- 现代插件依赖
- 系统提供的 Provider 接口与 DTO(PaymentRequest、PaymentCallbackPayload、PaymentQueryRequest、PaymentQueryResult)。
- 系统服务 PaymentService 用于推进支付状态机。
- 第三方 SDK(如支付宝 SDK)在 Service 内按需引入。
- 传统插件依赖
- 全局对象(如 $dou、$_OPEN、$_GLOBAL_USER)与框架常量(ROOT_URL、PLUGIN_PATH)。
- 通过 setting/plugin/work 三件套完成配置、渲染与回调。
graph LR
Manifest["manifest.php"] --> Provider["Provider"]
Provider --> Service["Service"]
Service --> PaymentSvc["PaymentService(系统)"]
Service --> ThirdSDK["第三方SDK"]
Inc["inc.plugin.php"] --> Setting["setting.plugin.php"]
Inc --> Work["work.plugin.php"]
Work --> Notify["notify_url.php"]
性能与可维护性建议
- 按需引入 SDK:在 Service 的方法内 require SDK 文件,避免启动时加载全部依赖。
- 配置集中化:通过 manifest.meta 或 setting.plugin.php 集中声明配置项,减少硬编码。
- 错误归一化:对第三方异常进行捕获并转换为统一的失败结果,便于上层处理。
- 幂等与重试:回调与查询接口应支持幂等,必要时加入重试与日志记录。
- 资源隔离:插件资源(图片、JS、CSS)放在插件目录内,避免污染全局命名空间。
故障排查指南
- 配置不完整
- 现象:start 或 query 时报错提示配置缺失。
- 定位:检查 manifest.meta 或 setting.plugin.php 中的必填字段是否填写完整。
- 回调验签失败
- 现象:notify 返回 fail。
- 定位:核对公钥/私钥、签名算法、字符集与网关地址;查看 Service 中的验签逻辑。
- 模块依赖未启用
- 现象:传统插件提示未启用钱包模块或需登录。
- 定位:检查 $_OPEN 标志与用户登录态,确保前置模块已开启。
- 回调地址不正确
- 现象:第三方回调无法到达。
- 定位:确认 notify_url/return_url 生成规则与服务器路由一致。
结论
DouPHP 插件体系同时支持现代类式与传统脚本式两种组织方式。现代插件通过 manifest.php + Provider + Service 实现高内聚、低耦合的可插拔扩展;传统插件通过 setting/plugin/work 三件套快速落地。无论哪种方式,都应遵循清晰的目录划分、规范的元数据声明与稳健的错误处理策略,以确保可维护性与可扩展性。
附录:标准插件模板
以下为推荐的插件目录模板与文件职责说明,适用于现代插件(支付、物流、登录等)与传统插件(简单功能扩展)。
- 现代插件模板
- 根目录
- manifest.php:声明 plugin_group 与 provider。
- XxxProvider.php:实现插件能力(start/notify/finish/query),对外暴露 meta 配置。
- XxxService.php:封装第三方 SDK 调用、配置组装、回调处理、状态推进。
- 可选目录
- sdk/:第三方 SDK 或内部库。
- images/、js/、css/:插件资源。
- Internal/:内部回调处理器(如 notify 回调类)。
- 根目录
- 传统插件模板
- 根目录
- inc.plugin.php:插件入口,初始化环境与回调地址。
- setting.plugin.php:插件元数据与配置表单。
- work.plugin.php:渲染页面与业务逻辑。
- notify_url.php / return_url.php:回调与跳转处理。
- icon.png / icon.gif:插件图标。
- 根目录
- 元数据与配置要点
- 版本管理:ver 字段用于标识插件版本,便于升级与兼容判断。
- 依赖声明:通过 $_OPEN 或模块开关声明对其它模块的依赖(如 money)。
- 权限配置:通过 meta.config 或 setting.plugin.php 的 config 数组定义配置项类型(text/textarea/select)与默认值。
- 分组与标识:plugin_group 用于分类展示与管理;unique_id 用于唯一标识。