PrizeX 是什么
PrizeX 是一套基于 PHP 的奖品、游戏与交易平台:拍卖、彩票、盲盒、一组街机小游戏、多商家电商商城,以及钱包/积分体系 — 全都装在同一个自托管应用里。它采用插件/主题架构,自带管理后台和 38 个支付网关插件,覆盖银行卡、电子钱包、加密货币和区域性支付服务商,另有 3 种由内核预置的手动付款方式。
不存在 SaaS 绑定:你把它装在自己的主机上,数据库归你所有,授权内享终身更新。每条业务线(拍卖、彩票、盲盒、游戏、商城)都能在管理后台里单独开关 — 一份全新安装既可以只跑单条业务线,也可以跑完整套件。
核心代码从不硬依赖任何插件。每条业务线、每个支付网关、每种社交登录都是 plugins/ 下的一个插件,可以随意启用、停用或删除,不会弄坏站点的其余部分。
数据表前缀 tbl_,不用 ORM,基本都是预处理语句。每个插件通过幂等的 db_delta() 安装程序管理并迁移自己的数据表。
运行环境
PrizeX 跑在普通共享主机或 VPS 上就行 — 除了需要一台支持 URL 重写的 Web 服务器,不需要任何特殊的服务器配置。
* database/migrations/ 下有若干文件用到了 MariaDB 独有的 ADD COLUMN IF NOT EXISTS 扩展语法。纯 MySQL 8.0/8.4 会直接报错 — 数据库请用 MariaDB,开发和生产环境都一样。
让一份全新安装跑起来
全新安装没有安装向导 — 你直接导入表结构,然后配置环境变量文件。
- 安装 PHP 依赖:
composer install - 复制环境变量模板,填入你的数据库凭据:
cp .env.example .env - 把
database/production.sql导入到.env里指定的那个数据库 — 这一步会建好完整的表结构。 - 替换掉预置的管理员账号(见下方提示),然后在
/admin/登录。
database/production.sql 里带了一行 tbl_admin 记录(admin@wowcodes.in),它的密码哈希在每一份安装里都完全相同。上线之前请删掉它,插入你自己的账号:
php -r "echo password_hash('your-password', PASSWORD_BCRYPT), \"\n\";"DELETE FROM tbl_admin;
INSERT INTO tbl_admin (username, email, password, image, status, permission_settings)
VALUES ('yourname', 'you@example.com', '<hash from the command above>', '', 1, 1);本地开发不用 Apache 也行,PHP 自带的服务器就够:php -S localhost:8000 router.php — 注意这个服务器完全不读 .htaccess,所以 router.php 用手写的方式把同一套路由规则又实现了一遍(参见 Web 服务器配置)。
环境变量
所有与环境相关的设置都放在 .env 里,由 vlucas/phpdotenv 加载。把 .env.example 复制成 .env(已被 git 忽略),再按各自环境填入真实值 — 至少要在导入表结构之前把数据库凭据配好。
与环境无关的全站设置(应用名称、货币、已启用的插件、当前主题,以及各业务线的开关)存在数据库的 tbl_settings 表里,在管理后台管理,而不是改文件。
Web 服务器配置
路由与安全规则 — 伪静态 URL、拦截对 .env/connection.php/日志文件的直接访问,以及防止上传的内容被当作 PHP 执行 — 都定义在项目各处的 .htaccess 文件里。Apache 和 LiteSpeed/OpenLiteSpeed 原生就能读取这些规则。
用 nginx 的话请参照 nginx.conf.example,它把上述每一条规则都对应写成了 nginx 的 server{} 配置块 — 按你的环境改一下 server_name、root 和 PHP-FPM 的 socket 就行。
.htaccess(生产环境)、router.php(本地 php -S 开发服务器)和 nginx.conf.example(nginx)各自独立地实现了同一套路由规则。新增一条伪静态路由,就意味着三处都得改。
请求架构
每个前台页面(index.php、item.php ……)都经由 includes/header.php 启动,顺序如下:
connection.php 会开启会话,用 .env 里的凭据通过 mysqli 建立连接,把 tbl_settings 加载成 APP_NAME、CURRENCY 这类常量,并登录当前用户、写入一条设备指纹记录。plugins_load() 会启动所有已启用的插件并触发 plugins_loaded 钩子 — 到这一步,当前真正启用了哪些业务线才算确定下来,所以 header.php 随后要拿旧版设置里的开关(shop、multivendor、auction、lottery)和插件的实际启用状态再核对一遍。
管理后台并没有把这套启动流程重写一遍 — admin/includes/connection.php 只设置后台专用的会话与错误配置,然后引入根目录下同一个 includes/connection.php。
插件系统
一个插件就是 plugins/<slug>/plugin.php — 文件头注释里的元数据会被解析出来,而不会执行这个文件 — 外加一个可选的 plugin.json,用来提供更丰富的目录信息。已启用的插件以 JSON 数组的形式存在 tbl_settings.active_plugins 里。
- 数据表归属 — 每个插件都定义自己的
includes/schema.php,在启用时被调用,内部使用幂等的db_delta()辅助函数(CREATE TABLE IF NOT EXISTS加上只做新增的ALTER TABLE ADD COLUMN)。插件绝不会碰其他插件的数据表。 - 注册表先加载 —
add_admin_page、add_route、add_cron_job、add_api_route和register_module都在任何插件加载之前就已定义好,所以哪怕某个插件最终并未启用,它顶层的调用也不会引发致命错误。 - 干净卸载 — 删除插件会执行它的
uninstall.php并移除它的目录;plugins/<slug>/之外的任何代码都不应该硬性引入它的文件,所以插件被删掉之后,站点其余部分照常运行。
主题系统
一套主题放在 assets/themes/<slug>/ 下 — 包含一个 manifest.php、一个 theme.css、承载主题钩子的 functions.php,以及可选的 components/。当前主题记录在 tbl_settings.active_theme 中,未设置时以 editorial 兜底。
组件查找按这个顺序进行:先看当前主题自己的 components/ 目录,再看插件通过 register_module() 声明的组件目录,最后是根目录下共享的 components/。实际效果是:共享的默认实现只在 components/ 里存一份,而任何一套主题 — 或者任何已启用的业务线插件 — 都可以用自己的副本覆盖某个具体的组件路径。
数据库
数据表前缀 tbl_,原生 mysqli,基本都是预处理语句。SQL 文件按权威程度排列如下:
database/core-schema.sql— 人工维护,只含内核表;业务线/插件的数据表是刻意排除在外的。database/production.sql— 自动生成(内核表结构加上每个插件自己的安装程序,在一个空白数据库上跑完后导出)。全新安装要导入的就是这个文件。database/sandbox.sql— 供本地开发使用的演示/种子数据。database/migration.sql— 面向已有安装的合并版幂等升级脚本。database/migrations/<slug>/up.sql(可回滚的还会附带down.sql) — 每次迁移各占一个文件。
模块
所有模块都装在同一份安装包里,可以在管理后台里逐个开关。
拍卖
实时竞价,配套多商家卖家后台和佣金引擎。核心插件:plugins/auction。
彩票
凭票参与的开奖玩法,开奖周期、奖品和中奖通知都可配置。核心插件:plugins/lottery。
盲盒
奖品池可配置,还带开箱动画 — 用户买下盒子,立刻就能看到自己抽中了什么。插件:plugins/mystery-box。
游戏与奖励
games/ 目录下的一组街机小游戏,外加若干互动/赚币类插件:
商城与交易平台
一层多商家电商能力,带促销和商品运营工具。核心插件:plugins/shop、plugins/multivendor。
钱包、积分与投资
一个贯穿全平台、所有模块共用的钱包。
推荐与奖励
认证、风控与合规
实用工具
管理后台
管理后台放在 admin/ 下,并没有把前台那套启动流程重写一遍 — 它只设置后台专用的会话与错误配置,然后引入根目录下同一个 includes/connection.php。页面通过 add_admin_page() 注册,侧边栏入口、权限校验、CSRF 和登录态外壳都由它统一处理;后台专用的 JSON 操作则通过 add_admin_ajax() 注册,由 admin/ajax.php?action=<slug> 分发。
商品、横幅、页面、菜单、博客。
自动与手动网关管理、手动付款审核、结算导出。
用户分组、角色权限、卖家资料、模拟登录。
交易/订单/用户导出、定时任务日志、错误追踪、管理员操作日志。
邮件营销、模板、订阅邮件、推送通知、通知日志。
启用/停用插件和主题、逐页 SEO 设置、全站设置。
前台主题
assets/themes/ 下随包附带五套主题,每份安装都能在管理后台里自由切换。每套主题都在自己的 components/ 目录里保留一份共享组件的副本。
简洁现代的外观,白色卡片配柔和阴影 — 稳妥百搭,几乎适合任何类型的商城。
干净的杂志风外观,暖调纸感配利落的字体排版,让店面显得精致可信。
默认兜底主题大胆奢华的深色主题,点缀金色 — 就是要那种刺激又高端的感觉。
温暖而繁复的装饰风格,灵感来自传统集市,并支持从右到左的语言。
带点惊悚气氛的节日限定风格 — 深紫色背景配上发光的南瓜橙点缀。
支付网关
38 个自动网关全部由插件自己拥有 — 每个都住在各自的 plugins/gateway-<slug>/ 目录里,通过 add_payment_gateway() 向内核注册自己。启用之后即刻可用;结账分发器(payment_processor.php)里没有任何一处写死了具体某个网关。
那 3 种手动方式是内核预置的 gateway_type = 'manual' 记录,没有 init/verify 代码需要配置 — 它们只是展示付款说明或一个二维码。manual-gateway-builder 插件让管理员不用碰代码就能再添加自定义的手动付款方式。
有些网关(Stripe、Razorpay、Midtrans、Venmo)还会注册一个 render 钩子,用于那些需要客户端 JS 的结账流程 — 比如 Stripe Checkout 的初始化脚本,或者需要先在服务端生成订单 ID 或令牌才能跑起来的 Razorpay/Midtrans/Braintree SDK。其余所有网关都不需要在内核里做任何额外接线。
API 与 AJAX 层
api/v1/— 面向移动应用和外部调用方的 REST API,采用 JWT 鉴权。api/v1/middleware/*.php负责校验Authorization: Bearer <token>请求头。插件通过add_api_route()添加自己的接口。ajax/— 供前台自己的 JS 使用的内部 AJAX(购物车、优惠券、通知),靠会话 Cookie 鉴权。没有令牌层 — 它依赖connection.php建立起来的 PHP 会话。- 顶层零散的
api/— 一些不带版本号的杂项接口,比如geo_location.php、exchange-rate.php和offerwall_postback.php。
移动应用
mobile/ 是一个独立的 Capacitor + Ionic 工程 — 它是在线站点外面套的一层 WebView 壳,既不是独立的 SPA,也不只是 api/v1 的调用方。它的 capacitor.config.ts 把 server.url 指向你的域名。它有自己的 package.json,不从项目根目录构建:
cd mobile
npm run sync
npm run open:ios
npm run open:android升级与迁移
在对线上数据库执行 database/migration.sql 或任何 database/migrations/<slug>/up.sql 之前,先做一份备份快照:
mysqldump --single-transaction -u<user> -p<pass> <db> > pre-deploy-$(date +%Y%m%d-%H%M%S).sql大多数迁移都附带一个对应的 down.sql,专门用来回退那一处改动。少数迁移改的是已有数据、而不只是新增结构,它们附带的 down.sql 只会说明为什么这里什么都不做 — 这类情况要回滚,就得从上线前导出的备份里恢复。
安全须知
- 导入完成后立刻更换预置的管理员凭据(参见 安装)。
.env、connection.php和日志文件都被随包附带的.htaccess/ nginx 规则挡住了直接的 HTTP 访问 — 不要删掉这些规则。- 上传的内容在对外提供访问时无法作为 PHP 执行,这一点是在 Web 服务器配置层面强制的,而不是在应用层面。
- 支付网关凭据在管理后台里按网关分别配置,保存在服务端 — 永远不会暴露给前台。
测试
项目没有 PHPUnit 测试套件。composer test 实际运行的是 bin/run-probes.php,它会汇总 includes/_probes/ 以及各插件自己的 _probes/ 目录下的每一个 probe_*.php 文件,把每个都作为 CLI 子进程运行并检查退出码。
composer test # run every probe
php plugins/<slug>/_probes/probe_*.php # run a single probe directly
php bin/run-probes.php --all # also run destructive probes (skipped by default)常见问题
技术支持与资源
还是卡住了,或者需要本页没讲到的内容?