# 应用市场商业化流程(Discuz! 式插件/模板售卖闭环) > 业务模型:**框架免费,靠卖插件/模板变现**。 > 中心站(market)承载商品/交易/授权,客户机(client)拉取并受授权闸门约束。 ## 一、总体流程图 ``` 开发者提交 ──▶ 审核 ──▶ 上架 ──▶ 浏览详情 ──▶ 前台购买 ──▶ 支付 ──▶ 回调出授权 │ │ │ │ │ │ │ Market::submit 后台审核 catalog() Store::detail Store::buy Yansongda completeOrder() │ │ │ │ │ │ │ → 写 license_key │ │ │ │ │ │ │ → 写分润/开发者余额 └────────────┴─────────┴───────────┴────────────┴──────────┴───────────┴──▶ 下载安装(绑定域名) │ Market::valid / index │ 启用闸门(运行期校验) │ AddonService::verifyRuntimeLicense │ AddonService::checkLicenses (crontab) │ 过期/吊销 → 自动禁用 │ 分润提现 Withdrawal 模型 ``` ## 二、各阶段落地清单 | 阶段 | 状态 | 关键代码 | 说明 | |------|------|----------|------| | 1. 开发者提交 | ✅ | `Market::submit` | 支持 addon / template 两种类型,含安全扫描 | | 2. 审核 / 上架 | ✅ | 后台审核 + `MarketService::catalog()` | 通过后才进 `catalog()` 列表 | | 3. 浏览详情 | ✅ | `Store::detail` + `view/frontend/store/detail.html` | 价格/截图/版本/授权说明 | | 4. 前台购买下单 | ✅ | `Store::buy`(POST `/appmall/store/buy`) | 取会员 uid;中心站直连 `MarketService::buy`,客户机经 `RemoteService::buy` | | 5. 支付 | ✅ | `MarketService::buy` 内 `Yansongda\Pay`;`Market::notify` / `payResult` | 返回 `pay_params`(web 表单)前端 `window.open` 拉起收银台 | | 6. 回调出授权 | ✅ | `MarketService::completeOrder` | 支付成功生成 `license_key`(HMAC 签名)+ 写分润/开发者余额 | | 7. 订单轮询 | ✅ | `Store::orderStatus`(GET `/appmall/store/orderStatus`) | 前端拉起收银台后轮询,拿到 `license_key` | | 8. 下载安装 + 域名绑定 | ✅ | `Market::index`(下载)/ `Market::valid`(安装时校验绑定域名) | 校验:免费→uid→存在→吊销→过期→域名绑定 | | 9. 启用闸门 | ✅ | `AddonService::enable` → `verifyRuntimeLicense` | POST 中心站 `validDomain`;失败抛 `AddonException`(除非 `offline_tolerant`) | | 10. 运行期过期巡检 | ✅ | `AddonService::checkLicenses` + `addon:license-check` 命令 | crontab 每日巡检,过期落库禁用 | | 11. 分润 / 提现 | ✅ | `Withdrawal` 模型 + 收益后台 | 开发者余额可提现 | ## 三、配置开关 `config/ywxapp.php`: - `market_mode` / `api_url`:决定中心站 or 客户机。客户机(`is_market_client()===true`)才启用授权校验。 - `addon_license_check`:`false`(关闭校验)/ `true`(中心站不可达也禁用)/ `'offline_tolerant'`(不可达放行,仅真实过期拒绝禁用)。 ## 四、前端购买链路(detail.html) ``` 点击「立即购买」 → POST /appmall/store/buy {name} ← code=1, license_key → 提示已购,引导后台安装绑定域名 ← code=1, trade_no+pay_params → window.open 收银台 + 轮询 orderStatus ← code=1, trade_no(无pay_params, mock) → 演示确认 → 轮询 ← code=0, need_login → 跳 /member/login ``` ## 五、部署清单 **中心站需同步**:`addon/appmall/`(Store 控制器 + route/app.php + view/frontend/store/detail.html)、`config/pay.php`(Yansongda 配置)。 **客户机需同步**: - `ywxapp/service/AddonService.php`(`verifyRuntimeLicense` + `checkLicenses`) - `ywxapp/service/AppService.php`(`addon:license-check` 注册) - `ywxapp/command/AddonLicenseCheck.php` - `config/ywxapp.php`(`addon_license_check`) **定时巡检(客户机)**: ``` 10 3 * * * cd /path/to/site && php think addon:license-check >> runtime/license_check.log 2>&1 ``` ## 六、待办(真实支付与增长) 1. 真实支付:当前 `pay_params` 来自 `Yansongda\Pay`(中心站 `config/pay.php`),mqpay 免签插件未参与此链路;如需接 mqpay 收银台需另接。 2. 域名绑定可视化:安装时填写域名并校验的 UI 提示。 3. 运营增长:优惠券/分销、开发者实名结算、SEO 内容填充。 --- *参考:`docs/自定义命令清单.md`(`addon:license-check`)、`docs/系统架构与解耦设计.md`。*