Compare commits
No commits in common. "c6bff91c452bf8a345d44a09951561cf9b6a4586" and "4519399cb7bd1a1b668cf16cacd281bba08adf69" have entirely different histories.
c6bff91c45
...
4519399cb7
|
|
@ -1,7 +1,6 @@
|
||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
需要遵守:@AGENTS.md
|
|
||||||
|
|
||||||
## Repository Overview
|
## Repository Overview
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
# syntax=docker/dockerfile:1
|
|
||||||
#
|
|
||||||
# Local-development image for iCON.Abp.FX.HttpApi.Host (+ DbMigrator).
|
|
||||||
#
|
|
||||||
# Differs from src/iCON.Abp.FX.HttpApi.Host/Dockerfile (CI):
|
|
||||||
# - Targets .NET 6 (the projects are net6.0; the CI Dockerfile still says 5.0).
|
|
||||||
# - Does not COPY the non-existent src/access-token.bin.
|
|
||||||
# - Produces two runtime targets: `host` (the API) and `migrator` (data init).
|
|
||||||
#
|
|
||||||
# Build context = repository root (AML_Backend). See Dockerfile.local.dockerignore.
|
|
||||||
|
|
||||||
############################
|
|
||||||
# Restore + build (whole solution available)
|
|
||||||
############################
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
|
||||||
ARG BUILD_CONFIGURATION=Release
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
# NuGet.Config carries the ABP commercial feed (the account key is embedded in the URL).
|
|
||||||
COPY NuGet.Config ./
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Cache the NuGet global-packages folder so context changes don't force a re-download.
|
|
||||||
RUN --mount=type=cache,target=/root/.nuget/packages \
|
|
||||||
dotnet restore "src/iCON.Abp.FX.HttpApi.Host/iCON.Abp.FX.HttpApi.Host.csproj" && \
|
|
||||||
dotnet restore "src/iCON.Abp.FX.DbMigrator/iCON.Abp.FX.DbMigrator.csproj"
|
|
||||||
|
|
||||||
############################
|
|
||||||
# Publish API host
|
|
||||||
############################
|
|
||||||
FROM build AS publish-host
|
|
||||||
ARG BUILD_CONFIGURATION=Release
|
|
||||||
# -m:1 builds one project at a time to keep peak memory down (this solution's
|
|
||||||
# DbMigrations project is large enough to OOM Roslyn when compiled in parallel).
|
|
||||||
RUN --mount=type=cache,target=/root/.nuget/packages \
|
|
||||||
dotnet publish "src/iCON.Abp.FX.HttpApi.Host/iCON.Abp.FX.HttpApi.Host.csproj" \
|
|
||||||
-c "$BUILD_CONFIGURATION" -o /app/host /p:UseAppHost=false -m:1
|
|
||||||
|
|
||||||
############################
|
|
||||||
# Publish DbMigrator (schema migration + data seeding)
|
|
||||||
############################
|
|
||||||
FROM build AS publish-migrator
|
|
||||||
ARG BUILD_CONFIGURATION=Release
|
|
||||||
RUN --mount=type=cache,target=/root/.nuget/packages \
|
|
||||||
dotnet publish "src/iCON.Abp.FX.DbMigrator/iCON.Abp.FX.DbMigrator.csproj" \
|
|
||||||
-c "$BUILD_CONFIGURATION" -o /app/migrator /p:UseAppHost=false -m:1
|
|
||||||
|
|
||||||
############################
|
|
||||||
# Runtime: API host
|
|
||||||
############################
|
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS host
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=publish-host /app/host ./
|
|
||||||
EXPOSE 44331
|
|
||||||
ENTRYPOINT ["dotnet", "iCON.Abp.FX.HttpApi.Host.dll"]
|
|
||||||
|
|
||||||
############################
|
|
||||||
# Runtime: DbMigrator
|
|
||||||
# Seed contributors read data files and the full AppConfig relative to the
|
|
||||||
# app base directory, so we reuse the host's appsettings.json / Data / wwwroot.
|
|
||||||
############################
|
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS migrator
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=publish-migrator /app/migrator ./
|
|
||||||
COPY --from=publish-host /app/host/appsettings.json ./appsettings.json
|
|
||||||
COPY --from=publish-host /app/host/Data ./Data
|
|
||||||
COPY --from=publish-host /app/host/wwwroot ./wwwroot
|
|
||||||
ENTRYPOINT ["dotnet", "iCON.Abp.FX.DbMigrator.dll"]
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# Dedicated ignore file for Dockerfile.local (BuildKit picks <dockerfile>.dockerignore).
|
|
||||||
# Unlike the repo .dockerignore, this one keeps appsettings*.json so the local
|
|
||||||
# image is self-contained (config is then overridden via env vars in compose).
|
|
||||||
**/bin
|
|
||||||
**/obj
|
|
||||||
**/.git
|
|
||||||
**/.vs
|
|
||||||
**/.vscode
|
|
||||||
**/node_modules
|
|
||||||
**/*.user
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
# Local development stack for iCON.Abp.FX.HttpApi.Host
|
|
||||||
#
|
|
||||||
# docker compose -f docker-compose.local.yml up -d --build
|
|
||||||
#
|
|
||||||
# Services:
|
|
||||||
# mssql - SQL Server 2022 (amd64 under Rosetta on Apple Silicon)
|
|
||||||
# db-migrator - runs once: applies EF migrations + seeds data, then exits
|
|
||||||
# httpapi-host - the API; waits for a successful migration before starting
|
|
||||||
#
|
|
||||||
# After it is up:
|
|
||||||
# Swagger : http://localhost:44331/swagger
|
|
||||||
# DB : localhost,11433 (sa / Aml@Local2026)
|
|
||||||
# Admin : admin / 1q2w3E*
|
|
||||||
name: aml-local
|
|
||||||
|
|
||||||
services:
|
|
||||||
mssql:
|
|
||||||
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
||||||
platform: linux/amd64 # Apple Silicon: requires Rosetta emulation in Docker Desktop
|
|
||||||
container_name: aml-mssql
|
|
||||||
environment:
|
|
||||||
ACCEPT_EULA: "Y"
|
|
||||||
MSSQL_SA_PASSWORD: "Aml@Local2026"
|
|
||||||
MSSQL_PID: "Developer"
|
|
||||||
ports:
|
|
||||||
- "11433:1433"
|
|
||||||
volumes:
|
|
||||||
- mssql-data:/var/opt/mssql
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P \"$$MSSQL_SA_PASSWORD\" -C -Q \"SELECT 1\" -b"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 30
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
db-migrator:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile.local
|
|
||||||
target: migrator
|
|
||||||
image: aml-dbmigrator:local
|
|
||||||
container_name: aml-dbmigrator
|
|
||||||
depends_on:
|
|
||||||
mssql:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
DOTNET_ENVIRONMENT: "Development"
|
|
||||||
ConnectionStrings__Default: "Server=mssql,1433;Database=AbpAML;User Id=sa;Password=Aml@Local2026;TrustServerCertificate=True;Encrypt=False;"
|
|
||||||
restart: "no"
|
|
||||||
|
|
||||||
httpapi-host:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile.local
|
|
||||||
target: host
|
|
||||||
image: aml-httpapi-host:local
|
|
||||||
container_name: aml-httpapi-host
|
|
||||||
depends_on:
|
|
||||||
mssql:
|
|
||||||
condition: service_healthy
|
|
||||||
db-migrator:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
ports:
|
|
||||||
- "44331:44331"
|
|
||||||
volumes:
|
|
||||||
# ABP commercial license token (from `abp login`). The runtime license
|
|
||||||
# check reads /root/.abp/cli/access-token.bin; without it the host aborts
|
|
||||||
# (ABP-LIC-0008). Generate once with: abp login <user> -o <org> -p <pwd>
|
|
||||||
- "${HOME}/.abp/cli:/root/.abp/cli:ro"
|
|
||||||
environment:
|
|
||||||
ASPNETCORE_ENVIRONMENT: "Development"
|
|
||||||
ASPNETCORE_URLS: "http://+:44331"
|
|
||||||
ConnectionStrings__Default: "Server=mssql,1433;Database=AbpAML;User Id=sa;Password=Aml@Local2026;TrustServerCertificate=True;Encrypt=False;"
|
|
||||||
# IdentityServer issuer / self URL must match the URL used by the browser.
|
|
||||||
App__SelfUrl: "http://localhost:44331"
|
|
||||||
AuthServer__Authority: "http://localhost:44331"
|
|
||||||
AuthServer__RequireHttpsMetadata: "false"
|
|
||||||
# Silence integrations that point at unreachable infra in local dev.
|
|
||||||
AppConfig__RabbitMQConfig__EnableConsumer: "false"
|
|
||||||
AppConfig__RabbitMQConfig__HostName: "127.0.0.1"
|
|
||||||
AppConfig__JobConfig__SanctionJob__Enabled: "false"
|
|
||||||
AppConfig__JobConfig__EngineListSyncJob__Enabled: "false"
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
mssql-data:
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
||||||
# AML_Backend 本地开发(docker-compose)使用说明
|
|
||||||
|
|
||||||
用 docker-compose 在本地一键拉起 `iCON.Abp.FX.HttpApi.Host`,包含 SQL Server 数据库容器,并自动完成数据库迁移与种子数据初始化,用于本地开发调试。
|
|
||||||
|
|
||||||
> 适用平台:macOS(含 Apple Silicon / arm64)。相关文件均位于 `AML_Backend/` 目录下。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 架构概览
|
|
||||||
|
|
||||||
`docker-compose.local.yml` 定义三个服务:
|
|
||||||
|
|
||||||
| 服务 | 作用 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| `mssql` | SQL Server 2022 数据库 | arm64 上通过 `platform: linux/amd64`(Rosetta 模拟)运行;数据持久化在命名卷 `mssql-data` |
|
|
||||||
| `db-migrator` | 数据初始化 | 运行一次:执行 EF Core 迁移 + 种子数据,完成后退出(exit 0) |
|
|
||||||
| `httpapi-host` | 后端 API 主机 | 等 `db-migrator` 成功后才启动;对外暴露 `44331` |
|
|
||||||
|
|
||||||
启动顺序由健康检查与 `depends_on` 保证:`mssql` 健康 → `db-migrator` 跑完 → `httpapi-host` 启动。
|
|
||||||
|
|
||||||
配套文件:
|
|
||||||
- `Dockerfile.local`:本地多阶段构建镜像(**.NET 6**),产出 `host` 与 `migrator` 两个目标。
|
|
||||||
- `Dockerfile.local.dockerignore`:本地构建专用忽略表(保留 `appsettings.json`,仅排除 `bin/obj/.git` 等)。
|
|
||||||
|
|
||||||
> ⚠️ 仓库自带的 CI 用 `src/iCON.Abp.FX.HttpApi.Host/Dockerfile` 已过时(写的是 .NET 5、且 COPY 一个不存在的 `src/access-token.bin`),**不要**用它做本地构建,请使用 `Dockerfile.local`。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 前置条件
|
|
||||||
|
|
||||||
1. **Docker Desktop** 已安装并运行。
|
|
||||||
2. **内存 ≥ 16 GB**:SQL Server 2022 在 Apple Silicon 上是 amd64 模拟运行,内存不足会 SIGSEGV(exit 139)。
|
|
||||||
- 在 Docker Desktop → Settings → Resources → Memory 调到 16 GB,或编辑 `~/Library/Group Containers/group.com.docker/settings-store.json` 加入 `"MemoryMiB": 16384` 后执行 `docker desktop restart`。
|
|
||||||
3. **ABP 商业版授权令牌**(关键,见下一节)。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. ABP 授权令牌(必须,否则 API 起不来)
|
|
||||||
|
|
||||||
`httpapi-host` 依赖 ABP 商业模块(LanguageManagement、Lepton Commercial、Account Pro 等)。
|
|
||||||
启动时若授权校验失败,进程会直接终止:**exit 214 / `ABP-LIC-0008`**。
|
|
||||||
appsettings 内置的 `AbpLicenseCode` 是 2021 年的旧授权(已过期),因此需要用 `abp login` 生成的令牌。
|
|
||||||
|
|
||||||
> 注:`db-migrator` 不强制校验授权,所以数据迁移/种子在没有令牌时也能成功,只有 `httpapi-host` 需要令牌。
|
|
||||||
|
|
||||||
### 生成令牌(一次即可,令牌持久化在 `~/.abp/cli/`)
|
|
||||||
|
|
||||||
本机若已安装 ABP CLI:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
abp login fengruixiang -o JustGroup -p <你的密码>
|
|
||||||
```
|
|
||||||
|
|
||||||
本机未安装 ABP CLI 时,可在容器内执行(令牌通过挂载落到宿主机 `~/.abp/cli/`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p "$HOME/.abp"
|
|
||||||
docker run --rm -v "$HOME/.abp:/root/.abp" \
|
|
||||||
--entrypoint /bin/bash mcr.microsoft.com/dotnet/sdk:6.0 -lc '
|
|
||||||
export PATH="$PATH:/root/.dotnet/tools"
|
|
||||||
dotnet tool install --global Volo.Abp.Cli --version 6.0.3
|
|
||||||
abp login fengruixiang -o JustGroup -p <你的密码>
|
|
||||||
'
|
|
||||||
```
|
|
||||||
|
|
||||||
成功后会生成 `~/.abp/cli/access-token.bin`。`docker-compose.local.yml` 已把它只读挂载进容器:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
volumes:
|
|
||||||
- "${HOME}/.abp/cli:/root/.abp/cli:ro"
|
|
||||||
```
|
|
||||||
|
|
||||||
> 该令牌在**运行时联网**向 abp.io 校验授权,因此 `httpapi-host` 启动时需要网络。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. 一键启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd AML_Backend
|
|
||||||
docker compose -f docker-compose.local.yml up -d --build
|
|
||||||
```
|
|
||||||
|
|
||||||
首次构建较慢(需还原大量 ABP 商业 NuGet 包并编译约 40 个项目,并拉取 SQL Server 镜像)。
|
|
||||||
构建已做内存优化(`-m:1` 单项目编译 + NuGet 缓存挂载),避免 Roslyn 因内存不足被杀(OOM / exit 137)。
|
|
||||||
|
|
||||||
启动后验证:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose -f docker-compose.local.yml ps
|
|
||||||
# httpapi-host 为 Up、db-migrator 为 Exited(0)、mssql 为 Up(healthy)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 访问信息
|
|
||||||
|
|
||||||
| 项目 | 地址 / 凭据 |
|
|
||||||
|------|------------|
|
|
||||||
| Swagger | http://localhost:44331/swagger (FX API + AMLPortal API) |
|
|
||||||
| OpenID 配置 | http://localhost:44331/.well-known/openid-configuration |
|
|
||||||
| 数据库 | `localhost,11433`,用户 `sa`,密码 `Aml@Local2026`,库名 `AbpAML` |
|
|
||||||
| 应用管理员 | `admin@abp.io` / `1q2w3E*` |
|
|
||||||
|
|
||||||
种子数据包含:管理员账号、249 个国家、155 种货币、转账类型、文本模板、检测阈值等(共约 124 张表)。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. 常用操作
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd AML_Backend
|
|
||||||
|
|
||||||
# 查看后端日志(注意:Release 构建日志写文件,docker logs 可能为空,见下)
|
|
||||||
docker compose -f docker-compose.local.yml logs -f httpapi-host
|
|
||||||
|
|
||||||
# 停止(保留数据库卷)
|
|
||||||
docker compose -f docker-compose.local.yml down
|
|
||||||
|
|
||||||
# 重新启动
|
|
||||||
docker compose -f docker-compose.local.yml up -d
|
|
||||||
|
|
||||||
# 改了代码后重建并重启
|
|
||||||
docker compose -f docker-compose.local.yml up -d --build
|
|
||||||
|
|
||||||
# 仅重跑数据初始化(迁移+种子,幂等)
|
|
||||||
docker compose -f docker-compose.local.yml run --rm db-migrator
|
|
||||||
|
|
||||||
# 彻底重置数据库(删除数据卷后重来)
|
|
||||||
docker compose -f docker-compose.local.yml down -v
|
|
||||||
docker compose -f docker-compose.local.yml up -d --build
|
|
||||||
|
|
||||||
# 连接数据库执行 SQL
|
|
||||||
docker exec aml-mssql /opt/mssql-tools18/bin/sqlcmd \
|
|
||||||
-S localhost -U sa -P "Aml@Local2026" -C -d AbpAML -Q "SELECT COUNT(*) FROM AbpUsers"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. 本地开发已做的环境覆盖
|
|
||||||
|
|
||||||
`httpapi-host` 通过环境变量覆盖了若干配置,让本地能干净启动:
|
|
||||||
|
|
||||||
- `ASPNETCORE_URLS=http://+:44331`,`App__SelfUrl` / `AuthServer__Authority=http://localhost:44331`(保证 IdentityServer 颁发者与浏览器访问地址一致),`AuthServer__RequireHttpsMetadata=false`。
|
|
||||||
- `ConnectionStrings__Default` 指向 `mssql` 服务(覆盖 appsettings 里的 `localhost`)。
|
|
||||||
- 屏蔽不可达的外部集成:`AppConfig__RabbitMQConfig__HostName=127.0.0.1`(快速失败)、`...__EnableConsumer=false`;关闭 `SanctionJob`、`EngineListSyncJob`。
|
|
||||||
|
|
||||||
> 仍有部分检测功能依赖 Elasticsearch / iCS 等远程或局域网服务,本 compose 未包含。如需本地联调这些功能,需另行配置对应服务地址。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. 故障排查
|
|
||||||
|
|
||||||
| 现象 | 原因 | 解决 |
|
|
||||||
|------|------|------|
|
|
||||||
| `httpapi-host` 反复重启 / exit 214,日志含 `ABP-LIC-0008` | ABP 授权令牌缺失或过期 | 按第 3 节生成 `~/.abp/cli/access-token.bin`,确认 compose 挂载,重启服务 |
|
|
||||||
| `mssql` exit 139(SIGSEGV)、状态 unhealthy | Apple Silicon 模拟下内存不足 | 把 Docker 内存调到 ≥16 GB(第 2 节),`docker desktop restart` |
|
|
||||||
| 构建时 `csc.dll exited with code 137` / `cannot allocate memory` | 编译 `DbMigrations` 大项目时 OOM | 已用 `-m:1` 缓解;确保 Docker 内存充足,必要时串行构建 |
|
|
||||||
| `docker logs httpapi-host` 为空但服务异常 | Release 构建只写文件日志(`#if DEBUG` 才有控制台 sink),日志在容器内 `/app/Logs/<级别>/<日期>/` | `docker cp aml-httpapi-host:/app/Logs ./Logs` 后查看,或临时用 `--build-arg BUILD_CONFIGURATION=Debug` 构建以获得控制台日志 |
|
|
||||||
| 访问 Swagger 401/跳转异常 | `AuthServer:Authority` 与实际访问地址不一致 | 确认仍是 `http://localhost:44331`,端口映射 `44331:44331` 未改 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. 相关文件清单
|
|
||||||
|
|
||||||
```
|
|
||||||
AML_Backend/
|
|
||||||
├─ docker-compose.local.yml # 本地三服务编排(本说明对应文件)
|
|
||||||
├─ Dockerfile.local # 本地 .NET 6 多阶段构建(host / migrator 两个目标)
|
|
||||||
├─ Dockerfile.local.dockerignore # 本地构建忽略表(保留 appsettings.json)
|
|
||||||
└─ src/iCON.Abp.FX.HttpApi.Host/ # API 主机工程
|
|
||||||
```
|
|
||||||
|
|
@ -384,7 +384,7 @@ POST /payments/create body = { orderId, amount, currency:'HKD', company, email }
|
||||||
<tr><td><code>TenantAdminEmail</code></td><td><code>email</code></td><td>必填;後端再校驗未註冊</td></tr>
|
<tr><td><code>TenantAdminEmail</code></td><td><code>email</code></td><td>必填;後端再校驗未註冊</td></tr>
|
||||||
<tr><td><code>Jurisdiction</code></td><td><code>jurisdiction</code></td><td>必填</td></tr>
|
<tr><td><code>Jurisdiction</code></td><td><code>jurisdiction</code></td><td>必填</td></tr>
|
||||||
<tr><td><code>OrganizationReference</code></td><td><code>edition</code>(Guid)</td><td>必填;校驗 edition 存在</td></tr>
|
<tr><td><code>OrganizationReference</code></td><td><code>edition</code>(Guid)</td><td>必填;校驗 edition 存在</td></tr>
|
||||||
<tr><td><code>OrganizationBR</code> / <code>OrganizationCI</code></td><td><code>br</code> / —</td><td><span class="pill done">已改</span> 後端已去除「BR 或 CI 至少一個」必填校驗(<code>OrderService.cs:154,190</code> 注釋),可不填;唯一性校驗保留,僅在實際填寫時生效</td></tr>
|
<tr><td><code>OrganizationBR</code> / <code>OrganizationCI</code></td><td><code>br</code> / —</td><td><b>BR 或 CI 至少一個</b>(OrderService.cs:154);plans-plus 僅收 BR 且標可選 ⇒ 缺口</td></tr>
|
||||||
<tr><td><code>EffectiveStartTime</code></td><td><code>startDate</code></td><td></td></tr>
|
<tr><td><code>EffectiveStartTime</code></td><td><code>startDate</code></td><td></td></tr>
|
||||||
<tr><td><code>ContactPerson</code></td><td><code>contact</code></td><td></td></tr>
|
<tr><td><code>ContactPerson</code></td><td><code>contact</code></td><td></td></tr>
|
||||||
<tr><td><code>CompanyAddress</code></td><td><code>address</code></td><td>可選</td></tr>
|
<tr><td><code>CompanyAddress</code></td><td><code>address</code></td><td>可選</td></tr>
|
||||||
|
|
@ -394,10 +394,6 @@ POST /payments/create body = { orderId, amount, currency:'HKD', company, email }
|
||||||
<tr><td><code>IsOfflinePayment</code>/<code>IsAgentBehalf</code></td><td>—</td><td>固定 <code>false</code></td></tr>
|
<tr><td><code>IsOfflinePayment</code>/<code>IsAgentBehalf</code></td><td>—</td><td>固定 <code>false</code></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="callout ok">
|
|
||||||
<p><span class="lbl">BR/CI 已放開(2026-06):</span>後端 <code>CreateOrder</code> 原有兩處「BR 或 CI 至少一個」必填校驗(<code>OrderService.cs:154</code> 與 <code>:190</code>)已注釋去除,plans-plus 可不填 BR/CI 直接下單。<b>保留</b>緊隨其後的唯一性校驗 <code>ExistsByOrganizationBRCI</code>(<code>OrderService.cs:191</code>)——兩者皆空時返回 <code>false</code> 放行,填寫時仍攔重複。DB 列可空(<code>nvarchar(max)</code>),無需遷移。</p>
|
|
||||||
<p><span class="lbl">影響:</span>① 改動為<b>全局</b>,旧站共用 <code>CreateOrder</code> 同樣放開(旧站前端仍自填 BR,行為不變);② 空 BR 不再參與去重,原「同公司只能註冊一次」對空 BR 失效;③ 下游 <code>TenantInfo</code>(<code>OrderService.cs:791</code>)、偵測報告(<code>ReportService.cs:276</code>)僅透傳展示、可容忍空值,但合規/STR 報告該欄會留白,需業務確認可接受。<b>續費/加購走 <code>TenantRenewal</code>,BR 繼承自上期訂單,不受影響。</b></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4>② type='renew' → TenantRenewal</h4>
|
<h4>② type='renew' → TenantRenewal</h4>
|
||||||
<table>
|
<table>
|
||||||
|
|
@ -482,7 +478,7 @@ if (addons.jquotaPackageId)
|
||||||
<tr><td>6</td><td><b>去掉管理員密碼步驟</b></td><td>後端已忽略 AdminPassword,發重置郵件</td><td><span class="pill done">無影響</span></td></tr>
|
<tr><td>6</td><td><b>去掉管理員密碼步驟</b></td><td>後端已忽略 AdminPassword,發重置郵件</td><td><span class="pill done">無影響</span></td></tr>
|
||||||
<tr><td>7</td><td><b>bestValue / 賣點 note</b>(方案卡片標記與文案)</td><td>後端 Plan 無此字段,BFF 配置或後端補</td><td><span class="pill partial">BFF/後端</span></td></tr>
|
<tr><td>7</td><td><b>bestValue / 賣點 note</b>(方案卡片標記與文案)</td><td>後端 Plan 無此字段,BFF 配置或後端補</td><td><span class="pill partial">BFF/後端</span></td></tr>
|
||||||
<tr><td>8</td><td><b>edition 多語言名稱</b>(中/日)</td><td>後端只有 displayName,BFF 補映射</td><td><span class="pill partial">BFF</span></td></tr>
|
<tr><td>8</td><td><b>edition 多語言名稱</b>(中/日)</td><td>後端只有 displayName,BFF 補映射</td><td><span class="pill partial">BFF</span></td></tr>
|
||||||
<tr><td>9</td><td><b>BR 標為可選</b>(UI)</td><td>後端已去除 BR/CI 必填校驗(<code>OrderService.cs:154,190</code>),可不填即下單;唯一性校驗保留、僅在填寫時生效</td><td><span class="pill done">已改</span></td></tr>
|
<tr><td>9</td><td><b>BR 標為可選</b>(UI)</td><td>後端要求 BR 或 CI 至少一個;需 UI 補 CI 或設必填</td><td><span class="pill todo">需對齊</span></td></tr>
|
||||||
<tr><td>10</td><td><b>支付 create 端點化</b>(前端拿 redirectUrl)</td><td>QFPay 簽名邏輯移到 BFF 服務端</td><td><span class="pill todo">BFF</span></td></tr>
|
<tr><td>10</td><td><b>支付 create 端點化</b>(前端拿 redirectUrl)</td><td>QFPay 簽名邏輯移到 BFF 服務端</td><td><span class="pill todo">BFF</span></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
@ -532,7 +528,7 @@ if (addons.jquotaPackageId)
|
||||||
<ol class="tight" style="padding-left:20px">
|
<ol class="tight" style="padding-left:20px">
|
||||||
<li><b>租戶查詢:</b>後端能否新增「按管理員郵箱查可續費租戶」?返回是否能直接帶 currentSubscription(planId / 上期價 / 已購加值項)?</li>
|
<li><b>租戶查詢:</b>後端能否新增「按管理員郵箱查可續費租戶」?返回是否能直接帶 currentSubscription(planId / 上期價 / 已購加值項)?</li>
|
||||||
<li><b>topup:</b>純加購走 TenantRenewal(PlanList 僅加值項)後端是否接受、語義是否「只疊配額不延期」?還是需新端點?</li>
|
<li><b>topup:</b>純加購走 TenantRenewal(PlanList 僅加值項)後端是否接受、語義是否「只疊配額不延期」?還是需新端點?</li>
|
||||||
<li><b>BR/CI:</b><span class="pill done">已解決</span> 後端已去除「BR 或 CI 至少一個」必填校驗(<code>OrderService.cs:154,190</code> 注釋,2026-06),plans-plus 可不填 BR/CI 直接下單;唯一性(去重)校驗保留,僅在填寫時生效。<b>待業務確認</b>:① 改動為全局,旧站共用 <code>CreateOrder</code> 是否接受同樣放開;② 空 BR 不再去重、合規/STR 報告該欄留白是否可接受。</li>
|
<li><b>BR/CI:</b>plans-plus 把 BR 標為可選,但後端要求 BR 或 CI 至少一個——UI 是否補 CI 字段,或把 BR 設為必填?</li>
|
||||||
<li><b>bestValue / note / edition 多語言:</b>由 BFF 配置維護,還是後端在數據上補字段?</li>
|
<li><b>bestValue / note / edition 多語言:</b>由 BFF 配置維護,還是後端在數據上補字段?</li>
|
||||||
<li><b>QFPay:</b>V2 是否沿用旧站同一 <code>appcode</code>/<code>api_key</code>/收銀台域名?簽名算法是否一致(sha256 排序串 + key)?</li>
|
<li><b>QFPay:</b>V2 是否沿用旧站同一 <code>appcode</code>/<code>api_key</code>/收銀台域名?簽名算法是否一致(sha256 排序串 + key)?</li>
|
||||||
<li><b>0 元 / P2G:</b>免支付分支的判定(<code>paymentStatus===200</code> 或 <code>txamt===0</code>)是否照搬?</li>
|
<li><b>0 元 / P2G:</b>免支付分支的判定(<code>paymentStatus===200</code> 或 <code>txamt===0</code>)是否照搬?</li>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue