彩虹易支付(epay)开发文档
这个项目是什么
本仓库不是易支付的源码本体,而是 88531 聚合支付平台(pay.88531.cn)的 Docker 部署配置、补丁与支付插件集合:用 docker-compose.prod.yml 起一套 nginx + php + mysql + cron 的生产环境,把定制补丁以挂载方式注入容器,PHP 运行镜像直接用上游 ghcr.io/aliveranme/epay:latest,这样镜像升级后补丁依然存在。
适合两类读者:一是要自己部署/维护彩虹易支付站的运维;二是想了解「这套站改了哪些地方」的二次开发者。
技术栈与架构
四个容器组成一条链路,全部在 epay-network 桥接网络里:
| 容器 | 镜像 | 作用 |
|---|---|---|
epay-nginx |
nginx:alpine |
对外 80 端口(NGINX_PORT 可改),只读挂载应用代码,配置在 docker/nginx.conf |
epay-php |
ghcr.io/aliveranme/epay:latest |
易支付 PHP 应用,entrypoint 启动时把 staging 补丁同步进工作目录 |
epay-mysql |
mysql:8.0 |
utf8mb4、utf8mb4_unicode_ci、空 sql-mode、时区 +08:00、mysql_native_password |
epay-cron |
alpine:latest |
每 5 分钟 curl 一次 SITE_URL/cron.php?key=CRON_KEY,驱动结算等定时任务 |
数据用命名卷持久化:app_data(站点代码与数据)、uploads(上传资源)、sessions(PHP 会话)、mysql_data(数据库)。plugins/ 与 patches/ 以宿主目录形式挂进 php 容器。
仓库结构
| 路径 | 作用 |
|---|---|
docker-compose.prod.yml |
生产编排:nginx / php / mysql / cron、卷、网络、补丁挂载、extra_hosts |
docker/nginx.conf |
站点 nginx 配置(对 /assets/dist/epay-ui.css|js 设 no-cache) |
docker/php-custom.ini |
PHP 自定义配置 |
patches/ |
补丁文件,挂到 /var/www/html-staging/ 对应路径,容器启动时同步进工作目录 |
patches/admin/ |
后台相关补丁(set.php、login.php) |
plugins/ |
支付插件源码,60+ 个目录(alipay、wxpay、paypal、stripe、unionpay、jeepay、bepusdt 等),另含 AGENTS.md |
.env |
环境变量(数据库/管理员密码等敏感信息,不入库) |
部署方式
准备 .env(见下表变量)后启动:
docker compose -f docker-compose.prod.yml up -d
容器重建、镜像升级都用同一条命令;补丁会在容器启动时由 entrypoint 从 staging 自动同步,不会因重建而丢失。
配置项说明
以下变量均来自 docker-compose.prod.yml,.env 中未设置的会用括号里的默认值:
| 配置键 | 默认值 | 含义 |
|---|---|---|
NGINX_PORT |
80 |
对外 HTTP 端口 |
DB_HOST / DB_PORT |
mysql / 3306 |
数据库地址与端口 |
DB_USER / DB_PASSWORD / DB_NAME |
epay / 无 / epay |
数据库账号、密码、库名 |
DB_PREFIX |
pay |
表前缀 |
MYSQL_ROOT_PASSWORD |
无 | MySQL root 密码 |
ADMIN_PASSWORD |
无 | 管理员初始密码 |
SITE_URL |
http://localhost(cron 内为 http://nginx) |
站点对外地址,影响回调与 cron |
API_TIMESTAMP_CHECK |
空(按 1 处理) | API 是否校验 timestamp,1 开启、0 关闭(兼容不传该字段的老平台) |
CRON_KEY |
无 | cron 容器调用 cron.php 的密钥 |
extra_hosts 里把 newapi.88531.cn、ai.88531.cn、pay.88531.cn 指向 host-gateway,让容器内应用能走宿主机访问这些域名。
补丁机制(本仓库的核心)
补丁放 patches/,由 compose 以只读方式挂到 /var/www/html-staging/ 对应路径,容器启动时 entrypoint 把 staging 同步到工作目录。当前挂载清单:
| 补丁 | 目标路径 | 作用 |
|---|---|---|
patches/functions.php |
includes/functions.php |
is_public_url 白名单 |
patches/epay-ui.css |
assets/dist/epay-ui.css |
后台布局覆盖样式 |
patches/epay-ui.js |
assets/dist/epay-ui.js |
后台侧栏脚本 |
patches/head.php |
admin/head.php |
后台资源链接加 ?v= 版本号 |
patches/test.php |
user/test.php |
测试支付页修复 |
patches/admin/set.php |
admin/set.php |
改密码存储与登录兼容 |
patches/admin/login.php |
admin/login.php |
登录兼容历史 md5 存储 |
patches/getshop.php |
getshop.php |
支付页轮询时主动向微信查单 |
新增补丁的方法:把文件放进 patches/,在 docker-compose.prod.yml 的 php 服务 volumes 里加一行 :ro 挂载到 /var/www/html-staging/<目标路径>,重启容器即可;镜像升级后补丁照常生效。
已做的定制改造
- 测试支付页白屏修复(
patches/test.php):/user/test.php由 React 渲染,服务端paytype数组键从商户渠道 ID 开始(非 0 起),json_encode输出成对象{"1":{...}},前端.map调用抛错导致整页白屏;用array_values()重排索引输出为 JSON 数组。 - 后台通道名称乱码修复(数据库):历史数据导入时 UTF-8 被按 cp1252 二次编码,用
latin1↔cp1252的双向转换还原(UPDATE ... CONVERT(CAST(CONVERT(name USING latin1) AS BINARY) USING utf8mb4),并用REGEXP '[一-龥]'只命中乱码行)。已修复pay_channel.name与pay_user.username,全库其余文本列扫描无同类问题。 - 后台 UI 全屏化:从构建产物 JS 中移除 9 处
max-w-[1440px]及 9 处页面级容器宽度类,CSS 末尾追加覆盖规则兜底,顶栏/侧栏/内容区铺满窗口。 - 后台侧栏优化:宽度 256px → 320px,菜单一行 2 个(分组标题独占整行、超长省略号、隐藏右侧箭头),脚本把
aria-current="page"的当前菜单滚动到可视区中间;移动端抽屉保持单列。 - 缓存与版本策略:nginx 把
/assets/dist/epay-ui.css|js设为no-cache;head.php给后台资源链接带?v=版本号,升级补丁后改这个版本号即可强制全端更新。
日常维护与二次开发要点
改补丁的完整流程:改 patches/ 下对应文件 → 同步进容器 → 更新 head.php 的 ?v= → 提交推送:
docker cp patches/epay-ui.css epay-php:/var/www/html/assets/dist/epay-ui.css
容器重建(镜像升级同此命令):
docker compose -f docker-compose.prod.yml up -d
.env含数据库与管理员密码,禁止提交进仓库。- 升级 PHP 镜像前先确认补丁仍能对上目标文件路径(上游改文件后 staging 挂载点要跟着调整)。
- 支付类改动务必在
/user/test.php页验证一遍渠道渲染,它正是历史上白屏的入口。
相关链接
- Gitea 仓库:http://127.0.0.1:3200/jinghui/epay
- 线上站点:
pay.88531.cn(README 记录的生产实例)