Files

99 lines
5.4 KiB
Markdown

# pay v2 — pangolin1 部署脚手架
pangolin1(`103.119.13.48`,Debian 12,root,内存 ~960Mi)上单独跑一份 `payd`
实例(`pay-v2`),只走 **crypto(USDT-TRC20)+ 哪吒(nezha,CNY)双渠道**,MOCK 关。
与阿里云那份 `pay`(仓库根 `deploy.sh`,支付宝+微信)彻底分开:不同 systemd
服务名(`pay-v2`)、不同端口(`8090`,旧 USDT watcher 已下线释放)、不同二进制/数据/
配置路径(`/opt/pay-v2` `/var/lib/pay-v2` `/etc/pay-v2`)、不同系统用户(`payv2`)。
## 文件清单
| 文件 | 用途 |
|---|---|
| `pay-v2.service` | systemd unit,装到 pangolin1 的 `/etc/systemd/system/pay-v2.service` |
| `pay.env.example` | env 模板,人工填真值后存到 pangolin1 的 `/etc/pay-v2/pay.env`(**不进 git**) |
| `config.yaml` | 非密钥配置源,`deploy.sh` 首次部署会拷到 `/etc/pay-v2/config.yaml` |
| `deploy.sh` | 部署脚本(交叉编译 + 上传 + 装 unit/config + 重启 + 探活回滚) |
## 部署步骤
1. **先手工准备凭证**(pangolin1 上,或本机 `rbw get` 取值后 `scp`/粘贴):
```bash
ssh pangolin1 'mkdir -p /etc/pay-v2'
# 把 pay.env.example 拷一份改名 pay.env,逐项填真值,再传上去:
scp pay.env pangolin1:/etc/pay-v2/pay.env
ssh pangolin1 'chmod 640 /etc/pay-v2/pay.env'
```
需要人工填的 env(全部走 Bitwarden,建议条目命名见括号):
- `PANGOLIN_CRYPTO_1_ADDRESS` —— TRC20 收款地址(Bitwarden:`pay-v2 pangolin1 crypto-1`)
- `TRONGRID_API_KEY` —— TronGrid API key(同上条目,或单独 `pay-v2 trongrid-key`)
- `PANGOLIN_NEZHA_1_PID` —— 哪吒商户号(Bitwarden:`pay-v2 pangolin1 nezha-1`)
- `PANGOLIN_NEZHA_1_PRIVATE_KEY` —— 商户 RSA 私钥 PEM(同上条目)
- `PANGOLIN_NEZHA_1_PLATFORM_PUBLIC_KEY` —— 哪吒平台 RSA 公钥 PEM(同上条目)
- `BIZ_PANGOLIN_SECRET` —— 与 pangolin-server 的 `PAY_BIZ_SECRET` 同值
(Bitwarden:`pay-v2 BIZ_PANGOLIN_SECRET`,两边必须手工同步同一个值)
2. **改 `config.yaml` 里的占位域名**(部署前,本地改好再让 `deploy.sh` 上传首个版本):
- `biz.pangolin.callback_url` 的 `<pangolin-server-域名占位>` 换成真实域名。
3. **跑部署脚本**(pay 仓根目录,本机执行):
```bash
./deploy/pangolin1/deploy.sh
```
首次会:建 `payv2` 系统用户 → 建 `/opt/pay-v2` `/var/lib/pay-v2` `/etc/pay-v2` →
装 unit → 拷 `config.yaml`(仅当远端还没有时)→ 传二进制 → `enable --now` →
探活 `curl 127.0.0.1:8090/health`。之后重跑只刷新二进制,`config.yaml`/`pay.env`
都不会被覆盖(改配置要单独 `scp` 再 `systemctl restart pay-v2`)。
4. **验证**:
```bash
ssh pangolin1 'systemctl status pay-v2 --no-pager'
ssh pangolin1 'journalctl -u pay-v2 -n 50 --no-pager'
ssh pangolin1 'curl -s 127.0.0.1:8090/health'
```
## seed 生产套餐(占位命令,按需调整价格/名称)
pay 目前套餐通过代码里的 `seed()`/`seedWechat()` 之类函数在启动时 upsert,或者用
管理接口/直接写库。crypto 结算币种是 USDT,nezha 结算币种是 CNY——**两个渠道各需
一套独立的 `ProductPrice`**(同一 `Product` 下按币种分别挂价,不能共用一条同金额
不同币种硬凑)。生产 seed 前先确认落地方式(建代码里的 seed 函数,还是走管理接口),
以下只是占位:
```bash
# 占位:crypto(USDT)套餐价 —— 具体走哪个接口/表待定,先别直接照抄执行
# INSERT INTO product_prices (product_id, currency, amount, ...) VALUES (..., 'USDT', ...);
# 占位:nezha(CNY)套餐价
# INSERT INTO product_prices (product_id, currency, amount, ...) VALUES (..., 'CNY', ...);
```
## 渠道说明
- **crypto**:`method` 名为 `crypto`。地址 watch-only,**payd 不做归集**——收到的
USDT 一直留在 `PANGOLIN_CRYPTO_1_ADDRESS` 这个地址上,不会自动转出。定期手动
归集/转出是运营动作,不在 payd 职责内。
- **nezha**:`method` 名预期为 `nezha`(哪吒 provider 正在另一分支开发,尚未合并
进 `internal/providerbuild/registry.go` 的 `BuildRegistry`)。本仓 `config.yaml`
已经把 `pangolin-nezha-1` 账户和 `credential_env_prefix` 结构定好,**但在
provider 代码合并前,该渠道不会真正被注册**(`BuildRegistry` 只认识
`crypto`/`alipay`/`stripe`/`fake`,未知 channel 的 enabled 账户会被静默忽略,
不会 fatal,只是收不到这个渠道)。provider 分支合并后需确认:
- env 变量名是否确实是 `PID` / `PRIVATE_KEY` / `PLATFORM_PUBLIC_KEY`(本文档
按任务描述推导,以 provider 代码实际 `accts.Credential(accountID, "KEY")`
调用为准);
- PEM 私钥/公钥在 `pay.env` 里是单行原始换行还是 `\n` 转义,需和 provider 的
解析方式对齐(`pay.env.example` 里留了两种可能的说明)。
## 已知易错点
- `QUERY_SYNC_ENABLED` **不是** `QUERYSYNC_ENABLED`——viper 的 `"." → "_"`
替换对 `query_sync.enabled` 展开成 `QUERY_SYNC_ENABLED`(带下划线),已用本地
viper 用例验证过。`pay.env.example` 里已经用对的名字。
- **绝对不要**在 `pay.env` 或 `config.yaml` 里设置 `MOCK_CHANNEL_ENABLED=true` /
`mock_channel_enabled: true`——会注册 `fake` 渠道并挂载
`/api/v2/dev/orders/:order_no/mark-paid` 这类联调专用端点,生产环境绝不能开。
- 阿里云那份 `pay`(仓库根 `deploy.sh`)服务名是 `pay`、端口 `8080`、路径
`/opt/pay`;这份是 `pay-v2` / `8090` / `/opt/pay-v2`,两者互不干扰,**别把
两个 `deploy.sh` 搞混执行**。