86 lines
4.6 KiB
Plaintext
86 lines
4.6 KiB
Plaintext
# 支付插件运行时
|
||
|
||
支付渠道通过 `.yingce-plugin` 包接入。宿主只负责订单、幂等、配置加密、回调收件箱、积分入账和对账;插件负责渠道协议转换。
|
||
|
||
## 包结构
|
||
|
||
```text
|
||
my-payment.yingce-plugin
|
||
├── manifest.json
|
||
├── backend/provider
|
||
├── assets/icon.svg
|
||
└── docs/README.md
|
||
```
|
||
|
||
Manifest 的支付贡献声明 `runtime.backend` 为 `rpc` 或 `wasm`,并通过 `runtime.backendEntry` 指定后端入口。当前版本首先启用 `rpc`:宿主以一次 JSON 请求启动入口进程,进程返回一次 JSON 响应。WASM 使用相同的 `yingce.payment/v1` 数据契约,运行时启用后即可复用插件实现。
|
||
|
||
## 标准操作
|
||
|
||
入口进程接收以下操作名:
|
||
|
||
| 操作 | 返回值 |
|
||
| --- | --- |
|
||
| `validate_config` | 空数据;失败返回 `ok:false` |
|
||
| `create_order` | `Checkout`:`mode`、`value`、`expiresAt` |
|
||
| `query_order` | 标准 `Result` |
|
||
| `close_order` | 标准 `Result` |
|
||
| `verify_notification` | `Notification`,请求体通过 `bodyBase64` 传入 |
|
||
| `download_trade_bill` | `BillRecord[]` |
|
||
|
||
请求固定带有 `version: "yingce.payment/v1"`。插件不得访问宿主数据库,不得自行入账积分。宿主目前控制进程工作目录、环境变量、标准输出大小和 30 秒超时;支付宝、微信实现还会在插件内部校验网关和账单下载域名。通用插件的操作系统级沙箱、签名校验和网络白名单尚未启用,不应直接运行不受信任的支付插件。
|
||
|
||
## 原生包的平台边界
|
||
|
||
`runtime.backend: "rpc"` 的 `backend/provider` 是原生可执行文件,不是平台无关静态资源。官方 backend 镜像在 Docker 构建中读取 `TARGETOS` 和 `TARGETARCH`,以 `CGO_ENABLED=0` 分别生成目标平台 provider,并在同一阶段重新生成 `.yingce-plugin`;目录文件与包内文件会比较内容,并在目标平台容器中真实执行冒烟请求。因此 Apple Silicon、Intel Mac 或 Windows 上发起的 Docker 构建不会把宿主二进制复制进 Linux 镜像。
|
||
|
||
仓库中保留的官方支付包用于 Linux amd64 源码运行和回归测试,其规范平台固定为 `linux/amd64`。在其他平台直接运行源码时,应先在具有 Node.js 和 `zip` 的 POSIX shell 中执行:
|
||
|
||
```bash
|
||
PAYMENT_PLUGIN_GOOS="$(go env GOOS)" \
|
||
PAYMENT_PLUGIN_GOARCH="$(go env GOARCH)" \
|
||
PAYMENT_PLUGIN_CGO_ENABLED=0 \
|
||
./plugin-packages/build-packages.sh --payments-only
|
||
```
|
||
|
||
当前 manifest 尚未声明 native artifact 的 OS/CPU;第三方市场若要分发原生 RPC 插件,应后续在 package index 或 manifest ABI 中增加平台选择信息,不能把单一 native package 视为跨平台包。
|
||
|
||
## 运行时缓存与诊断
|
||
|
||
宿主以完整 `.yingce-plugin` 字节的 SHA-256 作为 package 文件名和 `runtime/<digest>` 缓存键。provider 内容变化会产生新 digest 和新运行目录;解包先写临时目录,完成后写入 ready marker 并原子发布,旧目录不会覆盖新包,也不要求升级时手工清空整个数据卷。
|
||
|
||
执行前,Linux 宿主会拒绝 Mach-O、Windows PE、损坏的 ELF 和与当前 CPU 不匹配的 ELF。管理员可区分可执行文件缺失或加载器不可用、权限不足、格式或架构不兼容、进程异常退出、超时和无效 JSON。服务端启动日志只记录插件 ID、provider ID、宿主平台、可执行路径和操作系统错误;不会记录 RPC 请求、支付配置、密钥或插件 stderr。
|
||
|
||
## Manifest 示例
|
||
|
||
```json
|
||
{
|
||
"apiVersion": "yingce.plugin/v1",
|
||
"id": "example-aggregate-payment",
|
||
"name": "Example 聚合支付",
|
||
"version": "1.0.0",
|
||
"author": "Example",
|
||
"enabled": true,
|
||
"runtime": { "backend": "rpc", "backendEntry": "backend/provider" },
|
||
"configuration": {
|
||
"fields": [
|
||
{ "name": "merchantId", "type": "string", "required": true },
|
||
{ "name": "secret", "type": "password", "required": true, "secret": true }
|
||
]
|
||
},
|
||
"contributes": {
|
||
"paymentProviders": [{
|
||
"id": "example-qr",
|
||
"label": "Example 聚合支付",
|
||
"icon": "assets/icon.svg",
|
||
"checkoutMode": "qr_code",
|
||
"identityFields": ["merchantId"],
|
||
"expiryPolicy": { "defaultMinutes": 30, "minMinutes": 5, "maxMinutes": 1440 },
|
||
"notificationSuccess": { "status": 204 },
|
||
"notificationFailure": { "status": 400 }
|
||
}]
|
||
}
|
||
}
|
||
```
|
||
|
||
历史订单绑定插件版本和包哈希。升级不会替换未完结订单所需的运行文件;宿主检测到未完结订单时会拒绝支付插件升级或卸载,直到订单进入终态。签名根、WASM 执行器和通用网络白名单将在后续安全阶段加入。
|