chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
# 支付钩子调用机制与时序图
本文档说明 mqpay 支付插件内部基于 ThinkPHP **事件系统(Event+ 订阅器(Subscriber** 的钩子调用方式,
以及与会员开通(`UserMemberActivate`)的解耦关系。完整插件说明见 `../README.md`
## 一、整体机制
支付钩子**不是**传统 `Hook::add`/`Hook::listen`,而是 ThinkPHP 的事件系统:
- 业务核心 `app/member/controller/Payment.php` 只负责「触发事件」(`Event::trigger`);
- 支付插件 `addon/mqpay/subscribe/Payment.php` 通过「事件订阅器」监听并注入实现;
- 两者解耦,框架在启动阶段按 `info.php` 声明自动注册,无需手动绑定。
## 二、调用链路(5 步)
1. **声明订阅器**`addon/mqpay/info.php``events.subscribe`
```php
'events' => [
'subscribe' => [
'addon\\mqpay\\subscribe\\Payment',
],
],
```
2. **自动注册** — `ywxapp/service/AppService.php::loadAddonRelevant()`
遍历启用插件,调用 `app()->loadEvent($info['events'])`,把订阅器注册进事件系统。
3. **订阅方法即钩子** — `subscribe/Payment.php` 中方法名约定 `on + 事件名`
- `onPaymentMethods` ↔ `PaymentMethods`
- `onPaymentOrderCreate` ↔ `PaymentOrderCreate`
- `onPaymentCreate` ↔ `PaymentCreate`
- `onPaymentNotify` ↔ `PaymentNotify`
- `onPaymentFreeActive` ↔ `PaymentFreeActive`
4. **业务点火** — `app/member/controller/Payment.php`
```php
$results = Event::trigger('PaymentMethods', []); // Payment.php:77
Event::trigger('PaymentOrderCreate', ['order' => $order]); // Payment.php:153
$results = Event::trigger('PaymentCreate', [...]); // Payment.php:156
$results = Event::trigger('PaymentNotify', [...]); // Payment.php:180
Event::trigger('PaymentFreeActive', [...]); // Payment.php:134
```
5. **返回值消费**
- `PaymentMethods` → 返回 `array`,合并去重后返回前端(按 `sort` 排序)。
- `PaymentCreate` → 返回 `array`(如 `['type'=>'qrcode','qrcode_url'=>...]`)或 `null`(不处理);`create()` 取第一个非空作为支付参数。
- `PaymentNotify` → 返回 `'success'`/`'fail'``notify()` 直接作为网关响应体输出。
- `PaymentOrderCreate` / `PaymentFreeActive` → 副作用型(写库/日志),返回值忽略。
## 三、会员开通:UserMemberActivate 监听器
支付成功后本插件仅完成**订单激活**(`wxapp_mqpay_order.status=1`),真正的「会员权益写入」
(用户组 / 会员有效期 / 资金流水 / 操作日志)通过触发 `UserMemberActivate` 事件交给业务层处理。
- **实现**`app/member/listener/UserMemberActivate.php`
- `handle($event)` 读取 `uid` / `plan_id` / `order` / `method`
- 按 `config('member.plans')` 取套餐 `duration`/`level`/`gid`
- 在原未过期时间上**顺延**期限(防重复购买覆盖);
- 写 4 处:用户主表 `vip_expire`/`vip_level`/`gid`、`user_group_access`、`user_bill`、`user_log`。
- **注册**:全局 `app/event.php` 的 `listen` 数组(**非**插件 `info.php`)—— 与具体支付插件解耦。
- **触发**:本插件 `confirmOrder()``subscribe/Payment.php:326`),两条路径殊途同归:
- 安卓免签:`POST /mqpay/pay/notify-app` → `notifyApp()` 验签 → 按 `real_amount` 匹配 → `confirmOrder()`
- 后台人工:后台 `Confirm` 接口 → `Pay.php` → `confirmOrder()`
## 四、完整时序图(以"个人免签"为例)
```
用户浏览器 app/member/controller/Payment addon/mqpay/subscribe/Payment 安卓监听App 会员监听器
│ │ │ │ │
│─ GET methods ───────▶│ │ │ │
│ │ Event::trigger('PaymentMethods') │ │
│ │────────────────────────────▶│ onPaymentMethods() │ │
│◀─ 方式列表 ──────────│◀─────────────────────────────│ │ │
│ │ │ │ │
│─ POST create(personal)▶│ │ │ │
│ │ 生成 order │ │ │
│ │ Event::trigger('PaymentOrderCreate') │ │
│ │────────────────────────────▶│ onPaymentOrderCreate() │ │
│ │ Event::trigger('PaymentCreate') │ │
│ │────────────────────────────▶│ onPaymentCreate() │ │
│ │ │ personalQrcode()+jitter │ │
│◀─ 收款码+精确金额 ───│◀─────────────────────────────│ │ │
│ │ │ ║ 用户扫码转账到账 ║ │ │
│ │ │ │ 监听通知栏 │
│ │ │ │─ POST /mqpay/pay/notify-app(amount)▶│
│ │ │ notifyApp() 验签 md5(key+amount+sn+key) │
│ │ │ 按 real_amount 精确匹配 │ │
│ │ │ confirmOrder(order_sn) │ │
│ │ │ status=1 │ │
│ │ │ Event::trigger('UserMemberActivate') │
│ │ │────────────────────────── 开通会员 ──────▶│
│◀─ 轮询/刷新看到已开通─│ │ │ │
```
> 网关支付(微信/支付宝)走 `onPaymentNotify` 异步回调;**免签**(personal)无网关回调,
> 由 `notify-app`(安卓)或后台 `Confirm` 触发 `confirmOrder()`,殊途同归到 `UserMemberActivate`。
## 五、钩子 / 事件速查表
| 事件名 | 订阅方法 | 订阅位置 | 触发位置 | 返回值 |
|---|---|---|---|---|
| `PaymentMethods` | `onPaymentMethods` | `subscribe/Payment.php` | `Payment.php::methods()` | `array` 方式列表 |
| `PaymentOrderCreate` | `onPaymentOrderCreate` | `subscribe/Payment.php` | `Payment.php::create()` | 无(写库) |
| `PaymentCreate` | `onPaymentCreate` | `subscribe/Payment.php` | `Payment.php::create()` | `array`/`null` 支付参数 |
| `PaymentNotify` | `onPaymentNotify` | `subscribe/Payment.php` | `Payment.php::notify()` | `'success'`/`'fail'` |
| `PaymentFreeActive` | `onPaymentFreeActive` | `subscribe/Payment.php` | `Payment.php::create()` | 无 |
| `UserMemberActivate` | `handle()` | `app/member/listener/UserMemberActivate.php` | `confirmOrder()` | 无(写库/日志) |
### 注册方式对照
- 支付钩子(前 5 个):`addon/mqpay/info.php` 的 `events.subscribe` 声明,框架启动时自动 `loadEvent` 注册。
- 会员开通(最后 1 个):全局 `app/event.php` 的 `listen` 中注册,与支付插件解耦。