merge: deploy-scaffold
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# 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` 搞混执行**。
|
||||
@@ -0,0 +1,66 @@
|
||||
# pay v2 — pangolin1 部署配置模板。
|
||||
#
|
||||
# 部署时原样拷到 /etc/pay-v2/config.yaml(deploy.sh 首次部署会拷;之后重跑不覆盖,
|
||||
# 改配置需手动 scp 这个文件上去再 systemctl restart pay-v2)。
|
||||
#
|
||||
# ⚠️ 密钥/凭证一律不写在这里!全部走 /etc/pay-v2/pay.env(见同目录 pay.env.example),
|
||||
# 由 config.go 的 viper AutomaticEnv("." → "_" 转大写)或 accounts.Registry 按
|
||||
# credential_env_prefix 在运行时从环境变量读取。
|
||||
|
||||
server:
|
||||
port: "8090"
|
||||
mode: "release"
|
||||
# 拼 notify_url / return_url 用(alipay/wechat 才用得到;本部署这两渠道都禁用,
|
||||
# 留默认占位即可,不影响 crypto/nezha)。
|
||||
base_url: "http://127.0.0.1:8090"
|
||||
|
||||
database:
|
||||
driver: "sqlite"
|
||||
dsn: "/var/lib/pay-v2/pay.db"
|
||||
|
||||
# 本部署刻意只留 crypto + nezha 两个账户;alipay_sandbox / wechat 不写段落即用
|
||||
# config.go 默认值(enabled: false),mock_channel_enabled 同理不写即默认 false
|
||||
# ——不要在这里加 mock_channel_enabled: true。
|
||||
|
||||
# accounts:多账户路由注册表(v2)。凭证一律不写这里,只声明 credential_env_prefix,
|
||||
# 真值由 internal/accounts.Registry 运行时从 `<credential_env_prefix>_<KEY>` 环境变量读取。
|
||||
accounts:
|
||||
# crypto:USDT-TRC20,watch-only(不持私钥)。地址/TronGrid key 走
|
||||
# PANGOLIN_CRYPTO_1_ADDRESS / PANGOLIN_CRYPTO_1_TRONGRID_KEY(或全局 TRONGRID_API_KEY)。
|
||||
- account_id: "pangolin-crypto-1"
|
||||
channel: "crypto"
|
||||
enabled: true
|
||||
weight: 1
|
||||
region: "global"
|
||||
subject: "pangolin USDT 收款(TRC20)"
|
||||
credential_env_prefix: "PANGOLIN_CRYPTO_1"
|
||||
|
||||
# nezha:哪吒渠道,CNY 结算。provider 正在另一分支开发,这里先把账户/env 前缀
|
||||
# 结构定好;商户号/密钥走 PANGOLIN_NEZHA_1_PID / PANGOLIN_NEZHA_1_PRIVATE_KEY /
|
||||
# PANGOLIN_NEZHA_1_PLATFORM_PUBLIC_KEY。provider 未合并前 providerbuild.BuildRegistry
|
||||
# 不认识 "nezha" 这个 channel,该账户会被跳过(不会 fatal),只是渠道暂不生效。
|
||||
- account_id: "pangolin-nezha-1"
|
||||
channel: "nezha"
|
||||
enabled: true
|
||||
weight: 1
|
||||
region: "cn"
|
||||
subject: "pangolin CNY 收款(哪吒)"
|
||||
credential_env_prefix: "PANGOLIN_NEZHA_1"
|
||||
|
||||
# 业务对接:pangolin-server 的 webhook 接收器。secret 留空,走环境变量
|
||||
# BIZ_PANGOLIN_SECRET(须与 pangolin-server 侧 PAY_BIZ_SECRET 同值)。
|
||||
biz:
|
||||
pangolin:
|
||||
callback_url: "https://<pangolin-server-域名占位>/v1/webhook/pay" # ⚠️ 部署时替换成真实域名
|
||||
secret: ""
|
||||
|
||||
# 兜底主动查单(防异步回调丢失)。
|
||||
query_sync:
|
||||
enabled: true
|
||||
interval_sec: 30
|
||||
max_age_min: 30
|
||||
|
||||
# 后台守护/对账(过期清理/用量刷新/查单对账/已付抽查/退款自愈/crypto 孤儿扫描)。
|
||||
# 其余间隔字段沿用 config.go 默认值,量不大不必在此覆盖。
|
||||
reconcile:
|
||||
enabled: true
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env bash
|
||||
# pay v2 → pangolin1 专用部署脚本:交叉编译 → 传 pangolin1 → 首次装
|
||||
# 用户/目录/systemd unit/config.yaml → 备份旧二进制 → daemon-reload + enable --now →
|
||||
# 探活(失败自动回滚)。幂等:重复跑只刷新二进制,不覆盖 /etc/pay-v2/pay.env 或已存在的
|
||||
# /etc/pay-v2/config.yaml。
|
||||
#
|
||||
# 用法(pay 仓根目录执行):
|
||||
# ./deploy/pangolin1/deploy.sh
|
||||
#
|
||||
# 前提:
|
||||
# - ~/.ssh/config 有 pangolin1 别名(密钥登录);pangolin1 上以 root 身份操作
|
||||
# (systemctl / 装 unit / 建系统用户都需要)。
|
||||
# - 首次部署前,必须已在 pangolin1 上手工创建 /etc/pay-v2/pay.env
|
||||
# (参照 deploy/pangolin1/pay.env.example 填真值,真值一律走 Bitwarden/rbw)。
|
||||
# 本脚本刻意不生成/不覆盖这个文件——密钥不能经这条流水线过一遍。
|
||||
#
|
||||
# shellcheck disable=SC2029 # 下面 ssh 命令里的 $HOST/$DIR/$SVC 等都是本脚本的本地
|
||||
# 变量,故意要在客户端展开后再传给远端 shell(远端命令里没有任何"远端才存在的变量"),
|
||||
# 这正是想要的行为,不是需要转义的 bug。
|
||||
set -euo pipefail
|
||||
|
||||
HOST=pangolin1
|
||||
SVC=pay-v2
|
||||
SVC_USER=payv2
|
||||
DIR=/opt/pay-v2
|
||||
DATA_DIR=/var/lib/pay-v2
|
||||
ETC_DIR=/etc/pay-v2
|
||||
BIN=/tmp/pay-v2d-release
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
HERE="$REPO_ROOT/deploy/pangolin1"
|
||||
|
||||
log() { printf '\033[1;32m[deploy-pangolin1]\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m[deploy-pangolin1]\033[0m %s\n' "$*" >&2; }
|
||||
|
||||
echo "[1/6] 交叉编译 linux/amd64 …"
|
||||
(
|
||||
cd "$REPO_ROOT"
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o "$BIN" .
|
||||
)
|
||||
|
||||
echo "[2/6] 首次初始化(幂等):系统用户 + 目录 …"
|
||||
ssh "$HOST" "
|
||||
set -e
|
||||
id -u '$SVC_USER' >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin '$SVC_USER'
|
||||
mkdir -p '$DIR' '$DATA_DIR' '$ETC_DIR'
|
||||
chown -R '$SVC_USER:$SVC_USER' '$DATA_DIR'
|
||||
"
|
||||
|
||||
echo "[3/6] 装 systemd unit + config.yaml(不覆盖已存在的 config.yaml/pay.env)…"
|
||||
scp -q "$HERE/pay-v2.service" "$HOST:/etc/systemd/system/pay-v2.service"
|
||||
if ssh "$HOST" "[ -f '$ETC_DIR/config.yaml' ]"; then
|
||||
log "$ETC_DIR/config.yaml 已存在,跳过覆盖(改配置需手动: scp $HERE/config.yaml $HOST:$ETC_DIR/config.yaml)"
|
||||
else
|
||||
scp -q "$HERE/config.yaml" "$HOST:$ETC_DIR/config.yaml"
|
||||
log "已写入首个 $ETC_DIR/config.yaml"
|
||||
fi
|
||||
if ! ssh "$HOST" "[ -f '$ETC_DIR/pay.env' ]"; then
|
||||
warn "$ETC_DIR/pay.env 不存在!请先在 $HOST 上手工创建(参照 $HERE/pay.env.example,真值走 Bitwarden),"
|
||||
warn "否则 systemctl start 会因缺 env 报错或以空凭证跑起来。继续执行,但服务大概率起不来。"
|
||||
fi
|
||||
ssh "$HOST" "
|
||||
[ -f '$ETC_DIR/pay.env' ] && { chown root:'$SVC_USER' '$ETC_DIR/pay.env'; chmod 640 '$ETC_DIR/pay.env'; } || true
|
||||
chown root:root '$ETC_DIR/config.yaml' 2>/dev/null || true
|
||||
chmod 644 '$ETC_DIR/config.yaml' 2>/dev/null || true
|
||||
"
|
||||
|
||||
echo "[4/6] 上传二进制 + 备份旧版 + 切换 …"
|
||||
scp -q "$BIN" "$HOST:$DIR/payd-new"
|
||||
ssh "$HOST" "
|
||||
set -e
|
||||
[ -f '$DIR/payd' ] && cp '$DIR/payd' '$DIR/payd.bak' || true
|
||||
mv '$DIR/payd-new' '$DIR/payd'
|
||||
chmod +x '$DIR/payd'
|
||||
chown '$SVC_USER:$SVC_USER' '$DIR/payd'
|
||||
"
|
||||
|
||||
echo "[5/6] daemon-reload + enable --now …"
|
||||
ssh "$HOST" "systemctl daemon-reload && systemctl enable --now $SVC && systemctl restart $SVC"
|
||||
|
||||
echo "[6/6] 探活 …"
|
||||
if ssh "$HOST" "curl -fsS --retry 8 --retry-delay 1 --retry-connrefused -o /dev/null -w 'health %{http_code}\n' http://127.0.0.1:8090/health"; then
|
||||
echo "✅ 发布完成(上一版已备份在 $DIR/payd.bak,若存在)"
|
||||
else
|
||||
echo "❌ 探活失败,自动回滚 …"
|
||||
ssh "$HOST" "
|
||||
if [ -f '$DIR/payd.bak' ]; then
|
||||
cp '$DIR/payd.bak' '$DIR/payd' && systemctl restart '$SVC'
|
||||
else
|
||||
systemctl stop '$SVC'
|
||||
fi
|
||||
"
|
||||
echo "↩️ 已回滚/停止。请 ssh $HOST 'journalctl -u $SVC -n 100 --no-pager' 排查后重试。"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,57 @@
|
||||
[Unit]
|
||||
Description=pay v2 收款服务(pangolin1 专用实例;crypto USDT + 哪吒(nezha) CNY 双渠道,MOCK 关)
|
||||
Documentation=https://github.com/wangjia/pay
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
# 崩溃后不放弃自愈,但避免瞬时死循环耗尽资源(呼应 pangolin-agent.service 的自愈风格,
|
||||
# 这里用有限重启而非 Restart=always,因 payd 不是"必须永不停"的网络自愈进程)。
|
||||
# 注:StartLimitIntervalSec=/StartLimitBurst= 是 [Unit] 段指令(现代 systemd,
|
||||
# 与 pangolin-agent.service 的用法一致),不是 [Service] 段——放错段会被忽略。
|
||||
StartLimitIntervalSec=60
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=payv2
|
||||
Group=payv2
|
||||
WorkingDirectory=/var/lib/pay-v2
|
||||
EnvironmentFile=/etc/pay-v2/pay.env
|
||||
ExecStart=/opt/pay-v2/payd
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
# ── 加固 ─────────────────────────────────────────────────────────────────
|
||||
# ProtectSystem=strict 把整个文件系统挂只读,仅 ReadWritePaths 列出的目录可写
|
||||
# (sqlite 库文件 + 未来任何本地状态都落 /var/lib/pay-v2)。/etc/pay-v2 下的
|
||||
# config.yaml / pay.env 只读挂载即可,不需要写权限。
|
||||
# 仍需正常出网:连 TronGrid(crypto 查链)、哪吒网关(nezha 下单/查单/回调验签)、
|
||||
# 回调 pangolin-server 的 /v1/webhook/pay——因此不设 PrivateNetwork=true,
|
||||
# 也不把 RestrictAddressFamilies 收窄到只剩 AF_UNIX(仍留 AF_INET/AF_INET6)。
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/var/lib/pay-v2
|
||||
PrivateTmp=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelLogs=true
|
||||
ProtectControlGroups=true
|
||||
ProtectClock=true
|
||||
ProtectHostname=true
|
||||
ProtectProc=invisible
|
||||
RestrictSUIDSGID=true
|
||||
RestrictRealtime=true
|
||||
RestrictNamespaces=true
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
LockPersonality=true
|
||||
RemoveIPC=true
|
||||
# payd 是纯 Go 静态二进制(CGO_ENABLED=0 交叉编译,sqlite 走 modernc 纯 Go 实现,
|
||||
# 无 cgo/JIT),历史上 MemoryDenyWriteExecute=true 对这类构建安全;若启动后
|
||||
# journalctl 看到 SIGSYS/mmap 相关崩溃,先注释这一行排查。
|
||||
MemoryDenyWriteExecute=true
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
UMask=0027
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,51 @@
|
||||
# pay v2 — pangolin1 部署 env 模板(/etc/pay-v2/pay.env)。
|
||||
#
|
||||
# ⚠️ 本文件全是占位符,禁止填真值后提交进 git!真值一律经 Bitwarden → rbw 在
|
||||
# pangolin1 上手工写入 /etc/pay-v2/pay.env(权限建议 640, root:payv2)。
|
||||
# 部署脚本 deploy.sh 不会创建/覆盖这个文件——首次部署需手工准备好它。
|
||||
#
|
||||
# viper 的 env 覆盖规则是 "." → "_" 再转大写(见 config/config.go SetEnvKeyReplacer),
|
||||
# 下面每个变量名后注释了它覆盖的是 config.yaml 的哪个字段。
|
||||
|
||||
# ── 基础服务 ────────────────────────────────────────────────────────────────
|
||||
SERVER_PORT=8090 # server.port(pangolin1 上 8090,旧 USDT watcher 已下线释放)
|
||||
SERVER_MODE=release # server.mode(release 关 gin 调试日志)
|
||||
DATABASE_DRIVER=sqlite # database.driver
|
||||
DATABASE_DSN=/var/lib/pay-v2/pay.db # database.dsn(sqlite 文件路径,ExecStart 前需目录存在且属主可写)
|
||||
|
||||
# ── crypto 渠道(USDT-TRC20,watch-only,不持私钥)── Bitwarden 条目建议命名
|
||||
# "pay-v2 pangolin1 crypto-1" ─────────────────────────────────────────────
|
||||
# 收款地址(TRC20,仅地址,不涉及私钥/助记词):
|
||||
PANGOLIN_CRYPTO_1_ADDRESS=<占位-TRC20收款地址-走Bitwarden>
|
||||
# TronGrid API key:优先用账户级 <PREFIX>_TRONGRID_KEY,缺省回退全局 TRONGRID_API_KEY
|
||||
# (internal/provider/crypto/crypto.go::apiKey)。单账户场景填全局这个即可,
|
||||
# 多账户各自限流时再加 PANGOLIN_CRYPTO_1_TRONGRID_KEY 覆盖。
|
||||
TRONGRID_API_KEY=<占位-TronGrid-APIKey-走Bitwarden>
|
||||
# PANGOLIN_CRYPTO_1_TRONGRID_KEY=<可选-账户专属TronGrid-Key-走Bitwarden>
|
||||
|
||||
# ── 哪吒(nezha)渠道(CNY 结算)── Bitwarden 条目建议命名 "pay-v2 pangolin1 nezha-1" ──
|
||||
# provider 正在另一分支开发,以下三项是其将读取的凭证 env(命名按
|
||||
# CredentialEnvPrefix=PANGOLIN_NEZHA_1 推导,若合并后实际 key 名不同,以那边为准再改)。
|
||||
PANGOLIN_NEZHA_1_PID=<占位-哪吒商户号-走Bitwarden>
|
||||
# 商户 RSA 私钥(PEM)。若 env 单行存不了原始换行,推荐把 PEM 内的真实换行替换成
|
||||
# 字面 "\n" 再存一行(需 provider 侧对应做 strings.ReplaceAll(v, `\n`, "\n") 解码;
|
||||
# nezha provider 合并后核对其实际解析方式,当前仅占位)。
|
||||
PANGOLIN_NEZHA_1_PRIVATE_KEY=<占位-商户RSA私钥PEM-走Bitwarden>
|
||||
# 哪吒平台 RSA 公钥(PEM,验证哪吒回调签名用),同上单行转义方式。
|
||||
PANGOLIN_NEZHA_1_PLATFORM_PUBLIC_KEY=<占位-平台RSA公钥PEM-走Bitwarden>
|
||||
|
||||
# ── 业务对接(pangolin)── Bitwarden 条目建议命名 "pay-v2 BIZ_PANGOLIN_SECRET" ──
|
||||
# HMAC 共享密钥,须与 pangolin-server 那侧 PAY_BIZ_SECRET 同值(见
|
||||
# server/internal/httpapi 对 /v1/webhook/pay 的验签)。
|
||||
BIZ_PANGOLIN_SECRET=<占位-与pangolin-server-PAY_BIZ_SECRET同值-走Bitwarden>
|
||||
|
||||
# ── 后台守护 ────────────────────────────────────────────────────────────────
|
||||
RECONCILE_ENABLED=true # reconcile.enabled(过期清理/查单对账/退款自愈/crypto孤儿扫描)
|
||||
QUERY_SYNC_ENABLED=true # query_sync.enabled ⚠️ 注意是 QUERY_SYNC(带下划线),
|
||||
# 不是 QUERYSYNC——viper 的 "." → "_" 替换对 query_sync.enabled
|
||||
# 展开成 QUERY_SYNC_ENABLED(已用本地 viper 用例验证过)。
|
||||
|
||||
# ── MOCK 渠道:pangolin1 是真实收款环境,禁止开 ─────────────────────────────
|
||||
# 不要在这里设置 MOCK_CHANNEL_ENABLED(留空/不写即默认 false)。一旦误设为 true 会
|
||||
# 注册 fake 渠道 + 挂载 /api/v2/dev/orders/:order_no/mark-paid 这类联调专用端点。
|
||||
# MOCK_CHANNEL_ENABLED=true # ← 禁止在生产取消这行注释
|
||||
Reference in New Issue
Block a user