# 统一接收分发中转接口设计文档

---

## 1. 概述

### 1.1 设计目标

构建一个**国家无关**的接收分发中转接口：接收来自 SaaS 系统的推送请求，根据 `Country` + `PushType` 自动路由到对应国家的处理逻辑，完成文件生成 / 状态更新等操作后返回统一格式响应。

**核心架构：**

```
SaaS 系统
   │ POST 请求
   ▼
api.php（新增：统一中转入口 + 路由）
   │
   ├── 参数校验（ / Country / PushType / Data ）
   ├── 加载 countries/{Country}.php
   ├── 调用 {PushType} 方法
   │
   ▼
国家处理类（de.php / fr.php / be.php / gb.php / it.php ...）
   │
   ├── 调用外部 API（INSEE / ERIC / Playwright ...）
   ├── 生成文件 → 上传 OSS → 更新 DB
   │
   ▼
Response::json() → 统一 JSON 返回 SaaS
```

### 1.2 技术选型

| 项目     | 选型                                                 |
| -------- | ---------------------------------------------------- |
| 数据库   | SQL Server（PDO）                                    |
| 路由方式 | `Country` 类 + `{PushType}` 方法动态调用             |
| 响应格式 | JSON（`{code, msg, data}`）                          |
| 架构模式 | 接收-分发-中转（Relay Pattern）                      |

---

## 2. 接口规格

### 2.1 基本信息

| 项目           | 值                                                         |
| -------------- | ---------------------------------------------------------- |
| **接口名称**   | 统一接收分发中转接口                                       |
| **请求方式**   | POST                                                       |
| **Content-Type** | application/json            |
| **入口文件**   | `api.php`      |
| **本地测试**   | `http://rpa.test.fix.usaeu.com/app_withdrawn/api.php`     |
| **生产地址**   | `http://rpa.fix.usaeu.com/app_withdrawn/api.php`          |

### 2.2 请求参数

| 参数       | 类型   | 必填 | 说明                                                         |
| ---------- | ------ | ---- | ------------------------------------------------------------ |
| `PushType` | string | 是   | 推送类型（国家__业务大类__业务小类，直接作为方法名，如 `DE_VAT_REGISTER`） |
| `Country`  | string | 是   | 国家二字码（DE / FR / BE / GB / IT ...）                     |
| `Data`     | object | 否   | 业务数据（**扁平业务字段**：键为业务字段名，见 [4. Data 结构](#4-data-业务字段结构)；兼容旧格式 `modules` + `formInfo`） |
| `bizParam` | object | 否   | 业务标识信息（顶层，与 `PushType`/`Country`/`Data` 同级）。**原样回传到响应**。文件命名取值：`BusinessSerialNumber` 为 tid，`BusinessId`（兼容拼写 `Businessld`）为 VATRegInfoId，即文件名 `{BusinessSerialNumber}_{VATRegInfoId}_{原文件名}` |

**请求体示例（扁平业务字段）：**

```json
{
  "PushType": "DE_VAT_REGISTER",
  "Country": "DE",
  "bizParam": {
    "BusinessSerialNumber": "DVAT12312312312312313",
    "BusinessId": 123456,
    "projectId": 1
  },
  "Data": {
    "NameCN": "枝江市霞陆逊商贸有限公司",
    "NameEng": "zhijiangshixialuxunshangmaoyouxiangongsi",
    "RegNumber": "91420583MADDMTJE7M",
    "LegalPersonName": "刘振华",
    "LegalPersonIdNumber": "510681198706252865",
    "BusinessLicensePic": "[{\"fileUrl\":\"common-test/2026/08/06/019baf3f-801e-45aa-bf6d-a80c2b07e15d.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl.jpg\"}]",
    "StoreFBAAcitveSetSetScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/8388e6e0-87fd-4bd0-b881-392fbd7d6bb2.png\",\"fileName\":\"4359bc31121b45fd974bf91f0e1dff1b.png\"}]"
  }
}
```

### 2.3 响应格式

**sync 模式成功响应（实时处理，直接返回文件相对路径）：**

```json
{
  "code": 200,
  "msg": "success",
  "ProcessMode": "sync",
  "data": [
    {
      "url": "common-test/generatefile/2026/de_declar_delay/DVAT12312312312312313_123456_alle Anhänge in einem Dokument.pdf",
      "name": "DVAT12312312312312313_123456_alle Anhänge in einem Dokument.pdf",
      "type": "N合1文件"
    }
  ],
  "bizParam": {
    "BusinessSerialNumber": "DVAT12312312312312313",
    "BusinessId": 123456
  }
}
```

> `data` 为**文件数组**，每项含 `url`（OSS 相对路径）、`name`（文件名）、`type`（文件类型枚举，见 [5.2 文件类型枚举](#52-文件类型枚举)），无文件时返回空数组 `[]`。
>
> DE_VAT_REGISTER（德国VAT注册五合一文件生成）最终**只返回一个文件（`type=N合1文件`）**，中间处理文件（授权书/营业执照/身份证/邮件授权/截图）不上传。
>
> `url` 返回 **OSS 相对路径（不含域名）**，域名由 SaaS 侧拼接，完整 URL 形如 `https://usaeu-1259285998.cos.ap-guangzhou.myqcloud.com/{相对路径}`。路径前缀由 `New_OSSDelay_FILE_PATH` 配置决定（测试：`common-test/generatefile/2026/de_declar_delay/`，生产：`common/generatefile/2026/de_declar_delay/`）。
>
> `bizParam` 为**请求原样回传**（请求顶层 `bizParam`，兼容 `Data.bizParam`），不管里面有多少个字段均原样返回；文件命名取 `BusinessSerialNumber` 为 tid、`BusinessId` 为 VATRegInfoId。

**async 模式成功响应（异步受理，`data` 为 `null`，文件生成完成后另行通知/查询获取）：**

```json
{
  "code": 200,
  "msg": "success",
  "ProcessMode": "async",
  "data": null,
  "bizParam": {
    "BusinessSerialNumber": "DVAT12312312312312313",
    "BusinessId": 123456
  }
}
```

**失败响应：**

```json
{
  "code": 400,
  "msg": "缺少必需参数：PushType",
  "data": null
}
```

### 2.4 状态码说明

| code | 含义                       | 示例                                          |
| ---- | -------------------------- | --------------------------------------------- |
| 200  | 请求成功                   | 文件生成完成                       |
| 400  | 请求参数错误 / 业务处理失败 | 缺少参数 / 国家不支持 / 当前状态不允许操作    |
| 500  | 服务器内部错误             | 数据库连接失败 / 国家类加载异常               |

### 2.5 路由规则

```
方法名 = PushType（国家__业务大类__业务小类）

示例:
  PushType="DE_VAT_REGISTER" → 调用 DE_VAT_REGISTER()
  PushType="DE_VAT_DECLARE"  → 调用 DE_VAT_DECLARE()
  PushType="DE_EPR_REGISTER" → 调用 DE_EPR_REGISTER()
```

入口 `api.php`自动：
1. 加载 `countries/{Country}.php`
2. 实例化类
3. 调用对应方法
4. 返回结果

---

## 3. PushType 枚举（方法名）

`PushType` 即方法名，格式为 `{国家二字码}_{业务大类}_{业务小类}` 往后拼接。

| PushType | 说明 |
| --- | --- |
| `FR_VAT_REGISTER_PACK` | 法国 VAT 注册生成文件 |
| `SE_EPR_REGISTER_PACK` | 瑞典 EPR 自动生成文件 |
| `BE_EPR_REGISTER_PACK` | 比利时 EPR 自动生成文件 |
| `FR_EPR_REGISTER_WEEE` | 法国 EPR 的 WEEE 注册 |
| `FR_EPR_REGISTER_WEEE_CONTRACT` | 法国 EPR 的 WEEE 添加合同注册 |
| `FR_EPR_REGISTER_PACK` | 法国包装注册文件 |
| `FR_EPR_REGISTER_电气` | 法国电气注册文件（后缀待改英文） |
| `ES_EPR_REGISTER_HAGUE` | 西班牙 EPR 海牙文件生成（盖章要求/海牙待认证/APODERAMIENTO/030） |
| `ES_EPR_REGISTER_030` | 西班牙 EPR030 文件生成（030文件） |
| `ES_VAT_REGISTER_HAGUE` | 西班牙 VAT 海牙文件生成（海牙待认证/030） |
| `IT_EPR_REGISTER` | 意大利 EPR 注册文件生成 |
| `FR_EPR_REGISTER_LEKO` | 法国 LEKO 注册文件生成（LEKO/POA） |
| `FR_EPR_REGISTER_CITEO` | 法国 CITEO 注册文件生成（POA） |
| `FR_EPR_REGISTER_REFASHION` | 法国纺织法注册文件生成（POA） |

> 差不多就是这样子往后拼接就好了。

---

## 4. Data 业务字段结构

### 4.1 结构概述

`Data` 为**扁平业务字段对象**：键为业务字段名（与 `vat_query_api.php` 的 DEVAT_Register / Base_Customer_Company 字段名一致），值为字段值。文件类字段的值为 JSON 数组字符串，含 `fileUrl`（OSS 相对路径）+ `fileName`。

```
Data
├── 普通字段   { 业务字段名: 值 }                       例: "NameCN": "枝江市霞陆逊商贸有限公司"
├── 文件字段   { 业务字段名: "[{fileUrl,fileName}]" }     例: "BusinessLicensePic": "[{\"fileUrl\":...,\"fileName\":...}]"
└── 数组字段   { 业务字段名: [值,...] }                 例: "RegisteredCapitalCurrency": ["1","2"]
```

> **兼容旧格式**：若 `Data` 携带 `modules` + `formInfo`（动态表单 GUID 结构），接口按 GUID → 业务字段映射兼容解析（代码 `buildDataFromFormLegacy`）。

### 4.2 字段类型

| 类型 | 值格式 | 说明 |
| ---- | ------ | ---- |
| 普通字段 | `"string"` / `"1"` / `"2024-03-22"` | 直接作为业务字段值 |
| 数组字段 | `["1","2"]` | 以逗号连接后使用（如注资币种） |
| 文件字段 | `"[{\"fileUrl\":\"...\",\"fileName\":\"...\"}]"` | JSON 数组字符串，含 `fileUrl`（OSS 相对路径）+ `fileName` |

### 4.3 文件类字段清单

| 业务字段名 | 用途 |
| ---------- | ---- |
| `BusinessLicensePic` | 工商营业执照 |
| `LegalPersonIdNumberFrontPic` | 证件正面照 |
| `LegalPersonIdNumberBackPic` | 证件反面照 |
| `LegalSignedFile` | 上传签名文件 |
| `StoreFBAAcitveSetSetScreenShot` | FBA 开启截图 |
| `StoreWarehouseAddressScreenShot` | 仓库地址截图 |
| `StoreOtherSetScreenShot` | 店铺其他截图 |
| `StoreOverseaWarehouseContract` | 海外仓合同 |
| `StoreSellerProfileScreenShot` | 店铺主页截图 |

### 4.4 Data 业务字段说明（通用总表）

> 字段**只增不减**，所有国家 / 流程共用（括号标注适用流程：DE=德国 VAT、ES=西班牙海牙，未标注为通用字段）。**字段名不允许更改，只允许修改说明信息**。

**公司信息：**

| 字段 | 类型 | 必填 | 说明 |
| ---- | ---- | ---- | ---- |
| `NameCN` | 字符串 | 是 | 企业中文名称 |
| `NameEng` | 字符串 | 是 | 企业英文全称（不能含中文） |
| `RegNumber` | 字符串 | 是 | 营业执照号码 |
| `RegisteredCapital` | 字符串 | 否 | 注册资本 |
| `RegisteredCapitalCurrency` | 数组 | 否 | 注资币种（如 `["1","2"]`） |
| `EstablishmentDate` | 日期 | 否 | 成立日期（YYYY-MM-DD） |
| `CityEngName` | 字符串 | 是 | 公司所在城市（英文） |
| `RegAddressEng` | 字符串 | 是 | 注册地址（英文，不能含中文）（ES） |
| `CompanyAddressLine1En` | 字符串 | 是 | 公司地址第一行（英文） |
| `CompanyAddressLine2En` | 字符串 | 否 | 公司地址第二行（英文）（ES） |
| `CompanyAddressPostcode` | 字符串 | 是 | 公司地址邮编 |
| `CompanyAddressProvinceEn` | 字符串 | 是 | 公司地址省份（英文）（ES） |
| `CompanyCountry` | 字符串 | 是 | 公司所在国家（**中文原值**，如 `中国`/`香港`；`香港`/`HK`/`HONG KONG` 判定为香港公司；任务表 AsyncVATTasks 国家列存英文名 `CompanyCountry_en`）（ES） |
| `CompanyCountry_en` | 字符串 | 是 | 公司国家英文名（如 `China`）—— **以接口传值为准**（ES） |
| `CompanyCountryCode` | 字符串 | 是 | 公司国家区域代码（如 `156`）—— **以接口传值为准**（ES） |
| `Country` | 字符串 | 是 | 注册地址（国家）；ES 流程为 `CompanyCountry` 的兼容字段（取其一） |
| `LocalTaxNumber` | 字符串 | 否 | 本土税号（DE） |
| `ExpectedSalesYear1` | 字符串 | 否 | 注册后第一年预计销售额（欧元）（DE） |
| `ExpectedSalesYear2` | 字符串 | 否 | 注册后第二年预计销售额（欧元）（DE） |
| `DELogisticsSituation` | 字符串 | 否 | 海外仓详细地址（DE） |
| `ProductsRange` | 字符串 | 否 | 产品销售类型（DE） |
| `BusinessPlatform_En` | 字符串 | 否 | 销售平台（1=亚马逊，2=速卖通，3=EBAY）（DE） |
| `ShopName` | 字符串 | 否 | 店铺名称（DE） |
| `ShopUrl` | 字符串 | 否 | 店铺链接（DE） |
| `ShopAccount` | 字符串 | 否 | 店铺 Seller ID(Token)（DE） |

**法人信息：**

| 字段 | 类型 | 必填 | 说明 |
| ---- | ---- | ---- | ---- |
| `LegalPersonName` | 字符串 | 是 | 法人中文姓名 |
| `LegalPersonFullNamePinYin` | 字符串 | 是 | 法人英文姓名（拼音，不能含中文） |
| `LegalPersonEmail` | 字符串 | 否 | 法人邮箱 |
| `LegalPersonPhone` | 字符串 | 否 | 法人手机号码 |
| `LegalPersonGender` | 字符串 | 否 | 性别（`1`/`男` 或 `2`/`女`，亦兼容 `H`/`HOMBRE`/`M`/`MUJER`）；任务表 AsyncVATTasks 存 `H`(男)/`M`(女)，受理时即规范化 |
| `Nationality` | 字符串 | 否 | 民族（`1`=汉 HAN，`2`=回 HUI），身份证翻译件使用 |
| `LegalPersonIdNumber` | 字符串 | 是 | 证件号码 |
| `LegalPersonIdStartDate` | 日期 | 是 | 证件有效期开始时间（YYYY-MM-DD） |
| `LegalPersonIdEndDate` | 日期 | 是 | 证件有效期截止时间（YYYY-MM-DD） |
| `LegalPersonIDCardType` | 字符串 | 是 | 法人证件类型：`1`/`身份证`/`IDCard` → `IDCard`；`2`/`护照`/`Passport` → `Passport`（受理时规范化）（ES） |
| `LegalPersonCountry` | 字符串 | 是 | 法人国籍（**中文原值**，如 `中国`；须在国家数据中存在；任务表 AsyncVATTasks 国家列存英文名 `LegalPersonCountry_en`）（ES） |
| `LegalPersonCountry_en` | 字符串 | 是 | 法人国籍英文名（如 `China`）—— **以接口传值为准**（ES） |
| `LegalPersonBirthDate` | 日期 | 是 | 法人出生日期（YYYY-MM-DD） |
| `LegalPersonCityEngName` | 字符串 | 是 | 法人所在城市（英文） |
| `LegalPersonAddressProvinceEn` | 字符串 | 是 | 法人地址省份（英文）（ES） |
| `LegalPersonIDCardAddress` | 字符串 | 否 | 证件地址（中文原值，与 `LegalPersonIDCardAddressEng` 二选一） |
| `LegalPersonIDCardAddressEng` | 字符串 | 否 | 证件地址（拼音/英文） |

**流程控制：**

| 字段 | 类型 | 必填 | 说明 |
| ---- | ---- | ---- | ---- |
| `AR` | 字符串 | 是 | 授权机关模板：`M`=原模板，`O`=Onesea模板（ES） |
| `SpecsName` | 字符串 | 是 | 含 `免海牙` 走免海牙流程，否则海牙流程（ES） |
| `HagueType` | 数字 | 否 | 香港公司：`1`=包装法、`2`=包装法+VAT（需查册文件）、`3`=VAT（无需查册文件）（ES） |
| `BusinessCode` / `Code` | 字符串 | 否 | 业务编码（用于文件名） |
| `BusinessLicenseDirection` | 数字 | 否 | 营业执照方向：`1`=横版范围、`2`=横版提示、`3`=竖版范围、`4`=竖版提示；不传则自动检测（OCR 判定）（ES） |

**文件字段：**

| 字段 | 类型 | 必填 | 说明 |
| ---- | ---- | ---- | ---- |
| `BusinessLicensePic` | 文件 | 是 | 营业执照原件（大陆）；BR 文件（商业登记证，香港） |
| `LegalPersonIdNumberFrontPic` | 文件 | 是 | 证件正面照 |
| `LegalPersonIdNumberBackPic` | 文件 | 是 | 证件反面照 |
| `LegalSignedFile` | 文件 | 免海牙是 | 法人签名文件 |
| `CreditReportPic` | 文件 | 大陆是/香港否 | 企业信用报告（ES） |
| `BusinessCRFile` | 文件 | 香港是 | CR 文件（注册证书）（ES） |
| `BRFooterPic` | 文件 | 香港是 | BR 脚码（ES） |
| `CRSignerPic` | 文件 | 香港是 | CR 签发人（ES） |
| `CompanyParticularsPic` | 文件 | 香港且 `HagueType=1/2` | 查册文件（ES） |
| `StoreFBAAcitveSetSetScreenShot` | 文件 | 否 | FBA 开启截图（DE） |
| `StoreWarehouseAddressScreenShot` | 文件 | 否 | 仓库地址截图（DE） |
| `StoreOtherSetScreenShot` | 文件 | 否 | 店铺其他截图（DE） |

> **字段取值规则**（ES 海牙）：
> - `LegalPersonCountry` / `CompanyCountry` 传**中文原值**（如 `中国`，用于香港公司判定）；国家英文名与区域代码**以接口传值为准**（`LegalPersonCountry_en` / `CompanyCountry_en` / `CompanyCountryCode` 必填，调用方传入）；**任务表 AsyncVATTasks 的国家列存英文名**（如 `China`），中文原值不入任务表国家列
> - `LegalPersonIDCardType` 统一规范化为 `IDCard` / `Passport`
> - `LegalPersonGender` 任务表 AsyncVATTasks 存 `H`(男) / `M`(女)，受理时由传入值（`1`/`男`/`H`/`HOMBRE` → `H`；`2`/`女`/`M`/`MUJER` → `M`）规范化

**bizParam 字段说明：**

| 字段 | 类型 | 说明 |
| ---- | ---- | ---- |
| `BusinessSerialNumber` | 字符串 | 业务流水号，作为文件名的 tid |
| `Businessld` | 数字 | 业务 ID，作为文件名的 VATRegInfoId（兼容拼写 `BusinessId`） |

> 类型说明：`文件` 类字段的值为 JSON 数组字符串，含 `fileUrl`（OSS 相对路径）+ `fileName`；`日期` 格式 `YYYY-MM-DD`；`数组` 字段以逗号连接后使用。

### 4.4.1 德国VAT注册完整请求实例（Country=DE）

**请求体即 `德国vat注册(1).json` 全文**（顶层含 `PushType` / `Country` / `Data` / `bizParam`），`Data` 为扁平业务字段（键=业务字段名，含公司 / 法人 / 店铺 / 业务字段）：

```json
{
    "PushType": "DE_VAT_REGISTER",
    "Country": "DE",
    "Data": {
        "LegalPersonIdNumberBackPic": "[{\"fileUrl\":\"common-test/2026/08/06/ad9ba397-3a41-443c-8c96-d567f9f567c3.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl (2).jpg\"}]",
        "LegalPersonIdStartDate": "2019-04-15",
        "LegalPersonIdEndDate": "2039-04-15",
        "Nationality": "1",
        "LegalPersonFullNamePinYin": "ZHENHUA LIU",
        "LegalPersonPhone": "8618117939375",
        "LegalPersonBirthDate": "1987-06-25",
        "LegalSignedFile": "[{\"fileUrl\":\"common-test/2026/08/06/60198b6f-122a-4c74-ae64-07502628b828.png\",\"fileName\":\"DownAnnexesFileByFileUrl.png\"}]",
        "LegalPersonIdNumber": "510681198706252865",
        "LegalPersonEmail": "liu5zhen7h7ua@outlook.com",
        "LegalPersonGender": "1",
        "LegalPersonName": "刘振华",
        "LegalPersonIDCardAddress": "四川省广汉市和兴镇国防村4组43号",
        "LegalPersonIDCardAddressEng": "hexing zhen guofang cun 4 zu 43 hao hexing zhen,guanghan shi,sichuan sheng,618300,CN",
        "LegalPersonIdNumberFrontPic": "[{\"fileUrl\":\"common-test/2026/08/06/d257b28a-ea62-4197-b912-dffed75617af.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl (1).jpg\"}]",
        "LocalTaxNumber": "本土税号",
        "ExpectedSalesYear2": "20000.00",
        "ExpectedSalesYear1": "10000.00",
        "DELogisticsSituation": "DTM2 - Kaltbandstrasse 4 - 44145 - Dortmund, North Rhine-Westphalia",
        "ProductsRange": "Home goods",
        "BusinessPlatform_En": "1",
        "StoreFBAAcitveSetSetScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/8388e6e0-87fd-4bd0-b881-392fbd7d6bb2.png\",\"fileName\":\"4359bc31121b45fd974bf91f0e1dff1b.png\"}]",
        "ShopName": "Kyntysc",
        "ShopUrl": "https://www.amazon.de/sp?ie=UTF8&seller=A1DGLUTXACSUO",
        "ShopAccount": "A1DGLUTXACSUO",
        "StoreWarehouseAddressScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/26bd44df-e802-431c-af44-62ebd6e76c20.png\",\"fileName\":\"e62ec40c4ccb456fbc911cfac02b54fb.png\"}]",
        "StoreOtherSetScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/1c1345cb-c588-491a-8f28-17968c49e3e0.png\",\"fileName\":\"logo.png\"}]",
        "CompanyAddressLine1En": "No. W82, 2nd floor, Group 6, Jiangjiaopo Village, Anfu Temple, Zhijiang City, Yichang City, Hubei Province",
        "EstablishmentDate": "2024-03-22",
        "RegisteredCapital": "100000.00",
        "CityEngName": "Zhi Jiang",
        "NameEng": "zhijiangshixialuxunshangmaoyouxiangongsi",
        "NameCN": "枝江市霞陆逊商贸有限公司",
        "RegNumber": "91420583MADDMTJE7M",
        "CompanyAddressPostcode": "443200",
        "RegisteredCapitalCurrency": [
            "1",
            "2"
        ],
        "Country": "中国",
        "BusinessLicensePic": "[{\"fileUrl\":\"common-test/2026/08/06/019baf3f-801e-45aa-bf6d-a80c2b07e15d.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl.jpg\"}]"
    },
    "bizParam": {
        "BusinessSerialNumber": "DVAT12312312312312313",
        "Businessld": 123456
    }
}
```

### 4.4.2 西班牙VAT海牙完整请求实例（Country=ES）

**请求体即 `西班牙EPR海牙.json` 全文**（顶层含 `PushType` / `Country` / `Data` / `bizParam`）：

```json
{
    "PushType": "ES_EPR_REGISTER_HAGUE",
    "Country": "ES",
    "Data": {
        "LegalPersonIdNumberBackPic": "[{\"fileUrl\":\"common-test/2026/08/06/ad9ba397-3a41-443c-8c96-d567f9f567c3.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl (2).jpg\"}]",
        "LegalPersonIdStartDate": "2019-04-15",
        "LegalPersonIdEndDate": "2039-04-15",
        "Nationality": "1",
        "LegalPersonFullNamePinYin": "ZHENHUA LIU",
        "LegalPersonPhone": "8618117939375",
        "LegalPersonBirthDate": "1987-06-25",
        "LegalSignedFile": "[{\"fileUrl\":\"common-test/2026/08/06/60198b6f-122a-4c74-ae64-07502628b828.png\",\"fileName\":\"DownAnnexesFileByFileUrl.png\"}]",
        "LegalPersonIdNumber": "510681198706252865",
        "LegalPersonEmail": "liu5zhen7h7ua@outlook.com",
        "LegalPersonGender": "1",
        "LegalPersonName": "刘振华",
        "LegalPersonIDCardAddress": "四川省广汉市和兴镇国防村4组43号",
        "LegalPersonIDCardAddressEng": "hexing zhen guofang cun 4 zu 43 hao hexing zhen,guanghan shi,sichuan sheng,618300,CN",
        "LegalPersonIdNumberFrontPic": "[{\"fileUrl\":\"common-test/2026/08/06/d257b28a-ea62-4197-b912-dffed75617af.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl (1).jpg\"}]",
        "LocalTaxNumber": "本土税号",
        "ExpectedSalesYear2": "20000.00",
        "ExpectedSalesYear1": "10000.00",
        "DELogisticsSituation": "Calle de Alcalá 21, 28014 Madrid, Comunidad de Madrid",
        "ProductsRange": "Home goods",
        "BusinessPlatform_En": "1",
        "StoreFBAAcitveSetSetScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/8388e6e0-87fd-4bd0-b881-392fbd7d6bb2.png\",\"fileName\":\"4359bc31121b45fd974bf91f0e1dff1b.png\"}]",
        "ShopName": "Kyntysc",
        "ShopUrl": "https://www.amazon.es/sp?ie=UTF8&seller=A1DGLUTXACSUO",
        "ShopAccount": "A1DGLUTXACSUO",
        "StoreWarehouseAddressScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/26bd44df-e802-431c-af44-62ebd6e76c20.png\",\"fileName\":\"e62ec40c4ccb456fbc911cfac02b54fb.png\"}]",
        "StoreOtherSetScreenShot": "[{\"fileUrl\":\"common-test/2026/08/07/1c1345cb-c588-491a-8f28-17968c49e3e0.png\",\"fileName\":\"logo.png\"}]",
        "CompanyAddressLine1En": "No. W82, 2nd floor, Group 6, Jiangjiaopo Village, Anfu Temple, Zhijiang City, Yichang City, Hubei Province",
        "EstablishmentDate": "2024-03-22",
        "RegisteredCapital": "100000.00",
        "CityEngName": "Zhi Jiang",
        "NameEng": "zhijiangshixialuxunshangmaoyouxiangongsi",
        "NameCN": "枝江市霞陆逊商贸有限公司",
        "RegNumber": "91420583MADDMTJE7M",
        "CompanyAddressPostcode": "443200",
        "RegisteredCapitalCurrency": [
            "1",
            "2"
        ],
        "Country": "中国",
        "CompanyCountry": "中国",
        "CompanyCountry_en": "China",
        "CompanyCountryCode": "156",
        "BusinessLicensePic": "[{\"fileUrl\":\"common-test/2026/08/06/019baf3f-801e-45aa-bf6d-a80c2b07e15d.jpg\",\"fileName\":\"DownAnnexesFileByFileUrl.jpg\"}]",
        "AR": "M",
        "SpecsName": "海牙",
        "RegAddressEng": "No. W82, 2nd floor, Group 6, Jiangjiaopo Village, Anfu Temple, Zhijiang City, Yichang City, Hubei Province",
        "CompanyAddressLine2En": "",
        "CompanyAddressProvinceEn": "Hubei",
        "LegalPersonCityEngName": "Guang Han",
        "LegalPersonIDCardType": "1",
        "LegalPersonCountry": "中国",
        "LegalPersonCountry_en": "China",
        "LegalPersonAddressProvinceEn": "Sichuan",
        "BusinessCode": "",
        "Code": "",
        "CreditReportPic": "[{\"fileUrl\":\"common-test/2026/08/07/credit_report.pdf\",\"fileName\":\"credit_report.pdf\"}]",
        "HagueType": 3,
        "BusinessCRFile": "[{\"fileUrl\":\"common-test/2026/08/07/cr.pdf\",\"fileName\":\"cr.pdf\"}]",
        "BRFooterPic": "[{\"fileUrl\":\"common-test/2026/08/07/br_footer.png\",\"fileName\":\"br_footer.png\"}]",
        "CRSignerPic": "[{\"fileUrl\":\"common-test/2026/08/07/cr_signer.png\",\"fileName\":\"cr_signer.png\"}]",
        "CompanyParticularsPic": "[{\"fileUrl\":\"common-test/2026/08/07/particulars.pdf\",\"fileName\":\"particulars.pdf\"}]"
    },
    "bizParam": {
        "BusinessSerialNumber": "EEPR12312312312312313",
        "Businessld": 789012
    }
}
```

> 注：示例含少量德国流程遗留字段（店铺 / 销售 / 海外仓截图类），ES 海牙受理时忽略，可删除。

---

## 5. data 文件返回规范

### 5.1 规范说明

所有涉及文件生成的 PushType，返回的 `data` 统一为**文件数组**，每个元素结构：

| 字段   | 类型   | 说明                                                         |
| ------ | ------ | ------------------------------------------------------------ |
| `url`  | string | OSS 文件相对路径（不含域名，域名由 SaaS 侧拼接，完整 URL 形如 `https://usaeu-1259285998.cos.ap-guangzhou.myqcloud.com/{相对路径}`） |
| `name` | string | 上传后的完整文件名（含 tid 前缀，如 `DVAT12312312312312313_123456_xxx.pdf`） |
| `type` | string | 文件类型枚举，取值见 [5.2 文件类型枚举](#52-文件类型枚举)    |

**无文件时返回空数组 `[]`**（不是 `null`）。

示例：

```json
"data": [
  {
    "url": "common-test/generatefile/2026/de_declar_delay/DVAT12312312312312313_123456_alle Anhänge in einem Dokument.pdf",
    "name": "DVAT12312312312312313_123456_alle Anhänge in einem Dokument.pdf",
    "type": "N合1文件"
  }
]
```

### 5.2 文件类型枚举

`type` 字段取值（固定枚举，勿自定义）：

| 文件类型枚举           | 说明                       |
| ---------------------- | -------------------------- |
| `VAT业务申请表`        | 增值税注册申请表           |
| `营业执照或BR文件`     | 营业执照 / BR 文件         |
| `护照或法人身份证正面` | 护照或法人身份证正面       |
| `法人身份证反面`       | 法人身份证反面             |
| `CR文件(香港公司)`     | 香港公司 CR 文件           |
| `NNC1文件(香港公司)`   | 香港公司 NNC1 文件         |
| `公司章程文件`         | 公司章程文件               |
| `法人签名`             | 法人签名                   |
| `EPR业务申请表`        | EPR 业务申请表             |
| `授权代表业务申请表`   | 授权代表业务申请表         |
| `申请准备文件`         | 申请准备文件               |
| `申请回执`             | 申请回执                   |
| `申请预览`             | 申请预览                   |
| `N合1文件`             | 多文件合并的 N 合 1 文件   |
| `海牙文件-已认证`      | 已认证的海牙文件           |
| `EORI证书`             | EORI 证书                  |
| `本土税号证书`         | 本土税号证书               |
| `VAT税号证书`          | VAT 税号证书               |
| `法人税号证书`         | 法人税号证书               |
| `亚马逊证书`           | 亚马逊证书                 |
| `注册码证书`           | 注册码证书                 |
| `其他推送文件`         | 其他推送文件               |
| `授权书`               | 授权书（Mandat）           |
| `章程翻译件`           | 章程翻译件                 |
| `身份证合并件`         | 身份证合并件               |
| `营业执照合并件`       | 营业执照合并件             |
| `公司章程原件文件`     | 公司章程原件文件           |
| `普通申报回执`         | 普通申报回执               |
| `B2B申报回执`          | B2B 申报回执               |
| `延缓申报回执`         | 延缓申报回执               |
| `延缓申报确认函`       | 延缓申报确认函             |
| `其他附件`             | 其他附件                   |

### 5.3 各国映射示例

| PushType | 返回文件（type 枚举） |
| -------- | --------------------- |
| `DE_VAT_REGISTER`（德国VAT注册五合一文件生成） | 只返回 1 个文件：`N合1文件`（中间处理文件不上传） |
| `FR_VAT_REGISTER`（法国VAT注册文件生成） | 返回 5 个文件：`授权书`、`章程翻译件`、`身份证合并件`、`营业执照合并件`、`公司章程原件文件` |

> 不同国家可根据业务需求调整实际返回的文件类型，但 `type` 必须取自 [5.2 文件类型枚举](#52-文件类型枚举)。

### 5.4 新增流程文件槽契约（ES / IT / FR）

下列 7 个文件生成转发流程，relay 原样透传下游返回的 `data`（file1~file10），文件槽由下游填充；空槽为空字符串 `""`。

| PushType | file1 | file2 | file3 | file4 |
| --- | --- | --- | --- | --- |
| `ES_EPR_REGISTER_HAGUE` | 盖章要求文件（固定） | 海牙待认证文件 | APODERAMIENTO 文件 | 030文件 |
| `ES_EPR_REGISTER_030` | 030文件 | | | |
| `ES_VAT_REGISTER_HAGUE` | 海牙待认证文件 | 030文件 | | |
| `IT_EPR_REGISTER` | EPR注册文件 | | | |
| `FR_EPR_REGISTER_LEKO` | LEKO文件 | POA文件 | | |
| `FR_EPR_REGISTER_CITEO` | POA文件 | | | |
| `FR_EPR_REGISTER_REFASHION` | POA文件 | | | |

> 下游地址须 define 同名常量（如 `ES_EPR_REGISTER_HAGUE_API_URL`）；未定义或为空串时 **fail-closed 返 400**（不回落 `HTTP_HOST`，防 SSRF / PII 外泄）。部署时必须为每个流程 define 对应常量。

---

## 6. ProcessMode 处理模式

> `ProcessMode` 仅作为响应参数返回（响应侧约定，不随请求体传入）。

| 模式    | 适用接口                                    | 响应内容                                               |
| ------- | ------------------------------------------- | ------------------------------------------------------ |
| `sync`  | DE_VAT_REGISTER 等同步实时处理              | `data` 直接返回文件数组（`[{url, name, type}]`）       |
| `async` | ES 海牙系列（`ES_VAT_REGISTER_HAGUE`/`ES_EPR_REGISTER_HAGUE`/`ES_EPR_REGISTER_030`）| 异步受理：`data=null`，文件由 `task/queue_processor.php` 后台生成，结果写入 `AsyncVATTasks.ResultData`，030 由 RPA 生成后调对方结果通知接口（URL 由 RPA 固定配置） |

**sync 流程：**

```
请求 → 校验 → 路由到国家类 → 同步处理（生成文件 / 更新DB）
  → 返回 data 文件数组 [{url, name, type}]
```

**async 流程（ES 海牙，`public/es_hague_api.php`）：**

```
请求 → 校验 → 创建异步任务（AsyncVATTasks, DataSource='api', TaskStatus=0）
  → 立即返回 { ProcessMode:'async', data:null, bizParam }
queue_processor → 生成海牙合并PDF → ResultData{file1, cos_key, cos_url}
  └ 最终失败（达重试上限）→ failApiTask（TaskStatus=3）→ 按 ES_HAGUE_RESULT_CALLBACK_URL 回调调用方（.env 可选配置）
RPA 程序 → 生成 030 → 调用对方结果通知接口
```

---

## 7. 项目目录结构

```
app_withdrawn/
├── index.php                  ← 旧版接口入口（不在本文档对接范围）
├── api.php                    ← 新增：统一中转接口入口（接收 + 校验 + 路由 + 分发）
├── core/
│   ├── Database.php           ← 数据库连接（PDO 单例）
│   ├── CountryBase.php        ← 国家处理基类（execute / fetchOne）
│   └── Response.php           ← 统一 JSON 响应类
├── config/
│   └── database.php           ← SQL Server 配置
├── countries/                 ← 国家处理类（多国家扩展点）
│   ├── de.php                 ← 德国（DE_VAT_REGISTER ...）
│   ├── fr.php                 ← 法国（FR_VAT_REGISTER_PACK ...）
│   ├── be.php                 ← 比利时
│   ├── gb.php                 ← 英国
│   └── it.php                 ← 意大利
├── docs/
│   ├── UNIFIED_API_DESIGN.md  ← 本文档
│   ├── API_USAGE.md           ← 使用说明
│   └── DEVELOPER_GUIDE.md     ← 开发者指南
├── logs/                      ← 日志目录
│   └── api_YYYY-MM-DD.log
└── README.md
```

---

## 8. 扩展新国家 / 新方法

### 8.1 添加新国家

1. 在 `countries/` 下创建 `{country}.php`，类名与文件名一致（小写）
2. 继承 `CountryBase`
3. 实现对应方法，方法名 = PushType（国家__业务大类__业务小类，如 `DE_VAT_REGISTER`）

```php
<?php
// countries/es.php
class es extends CountryBase
{
    public function DE_VAT_REGISTER($params): array
    {
        // 西班牙 VAT 注册文件生成逻辑
        // 生成文件 → 上传 OSS → 返回 data 文件数组
        return [
            'code' => 200,
            'msg' => 'success',
            'data' => [
                [
                    'url'  => 'common-test/generatefile/2026/de_declar_delay/xxx.pdf',
                    'name' => 'xxx.pdf',
                    'type' => 'N合1文件',
                ],
                // ...
            ]
        ];
    }
}
```

### 8.2 添加新 PushType

直接在对应国家类中新增方法即可，无需修改 `api.php`。路由是动态的：

```
Country 类存在 → 方法 {PushType} 存在 → 自动调用
```

---

## 9. 新对接方法映射表

> 所有方法统一使用新命名 `PushType = {国家二字码}_{业务大类}_{业务小类}`（如 `DE_VAT_REGISTER`），`api.php` 直接以 PushType 作为方法名路由。

| Country | PushType | 方法名 | 说明 |
| ------- | -------- | ------ | ---- |
| DE | `DE_VAT_REGISTER` | `DE_VAT_REGISTER` | 德国VAT注册五合一文件生成 → vat_new_file_api.php |
| FR | `FR_VAT_REGISTER` | `FR_VAT_REGISTER` | 法国 VAT 注册生成文件（预留） |
| ES | `ES_EPR_REGISTER_HAGUE` | `ES_EPR_REGISTER_HAGUE` | 西班牙 EPR 海牙文件生成（盖章要求/海牙待认证/APODERAMIENTO/030） |
| ES | `ES_EPR_REGISTER_030` | `ES_EPR_REGISTER_030` | 西班牙 EPR030 文件生成（030文件） |
| ES | `ES_VAT_REGISTER_HAGUE` | `ES_VAT_REGISTER_HAGUE` | 西班牙 VAT 海牙文件生成（海牙待认证/030） |
| IT | `IT_EPR_REGISTER` | `IT_EPR_REGISTER` | 意大利 EPR 注册文件生成 |
| FR | `FR_EPR_REGISTER_LEKO` | `FR_EPR_REGISTER_LEKO` | 法国 LEKO 注册文件生成（LEKO/POA） |
| FR | `FR_EPR_REGISTER_CITEO` | `FR_EPR_REGISTER_CITEO` | 法国 CITEO 注册文件生成（POA） |
| FR | `FR_EPR_REGISTER_REFASHION` | `FR_EPR_REGISTER_REFASHION` | 法国纺织法注册文件生成（POA） |
| SE | `SE_EPR_REGISTER_PACK` | `SE_EPR_REGISTER_PACK` | 瑞典 EPR 自动生成文件（预留） |
| BE | `BE_EPR_REGISTER_PACK` | `BE_EPR_REGISTER_PACK` | 比利时 EPR 自动生成文件（预留） |
| FR | `FR_EPR_REGISTER_WEEE` | `FR_EPR_REGISTER_WEEE` | 法国 EPR 的 WEEE 注册（预留） |
| FR | `FR_EPR_REGISTER_WEEE_CONTRACT` | `FR_EPR_REGISTER_WEEE_CONTRACT` | 法国 EPR 的 WEEE 添加合同注册（预留） |
| GB | — | — | 预留 |
| NL | — | — | 预留 |
| PL | — | — | 预留 |
| AT | — | — | 预留 |
| CZ | — | — | 预留 |

---

## 10. 测试用例

### 10.1 cURL 示例

```bash
# 文件处理（德国 VAT 注册文件生成，同步模式）
curl -X POST http://localhost/app_withdrawn/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "PushType": "DE_VAT_REGISTER",
    "Country": "DE",
    "bizParam": {
      "BusinessSerialNumber": "DVAT12312312312312313",
      "BusinessId": 123456
    },
    "Data": {
      "NameCN": "枝江市霞陆逊商贸有限公司",
      "BusinessLicensePic": "[{\"fileUrl\":\"common-test/2026/08/06/xxx.jpg\",\"fileName\":\"license.jpg\"}]"
    }
  }'

```

### 10.2 Python 调用示例

```python
import requests

url = "http://localhost/app_withdrawn/api.php"

# sync 模式 — 文件处理
payload = {
    "PushType": "DE_VAT_REGISTER",
    "Country": "DE",
    "bizParam": {
        "BusinessSerialNumber": "DVAT12312312312312313",
        "BusinessId": 123456
    },
    "Data": {
        "NameCN": "枝江市霞陆逊商贸有限公司",
        "BusinessLicensePic": "[{\"fileUrl\":\"common-test/2026/08/06/xxx.jpg\",\"fileName\":\"license.jpg\"}]"
    }
}


```

---

## 11. 与现有外部 API 的对接关系

| 外部系统 / API                         | 对接方式                         | 对应 PushType（新）    |
| -------------------------------------- | -------------------------------- | ---------------------- |
| `vat_api_de_client/server/vat_query_api.php` | 在本项目中创建 DE 方法调用        | `DE_VAT_REGISTER`      |
| `vat_api_de_client/server/vat_deferred_7_query_api.php` | 在本项目中创建 DE 方法调用      | `DE_VAT_DECLARE`（计划） |
| `vat_api_fr_client/server/epr_weee_contract_api.php`（FR） | 在本项目中创建 FR 方法调用       | `FR_EPR_REGISTER`（计划） |
| ERIC / ELSTER（德国税局）              | Python 子进程调用                | `DE_VAT_DECLARE`（计划） |
| INSEE API（法国）                      | HTTP API 调用                    | `FR_EPR_REGISTER`（计划） |
| 腾讯云 COS                             | SDK 上传                         | 各国家通用             |

---

## 12. 后续扩展

| 扩展项         | 说明                                               |
| -------------- | -------------------------------------------------- |
| Token 认证     | 增加 `Authorization: Bearer <token>` 校验          |
| async 回调     | ES 海牙已实现异步受理（见 §6）：文件由 queue_processor 后台生成，030 由 RPA 生成后调对方结果通知接口（URL 由 RPA 固定配置）；生成阶段最终失败（达重试上限）时按 `ES_HAGUE_RESULT_CALLBACK_URL`（.env，可选）回调调用方错误信息 |
| 限流机制       | 按国家 + PushType 维度的 QPS 限制                 |
| 任务队列       | 接入 Redis 队列实现真正的异步处理（当前为轮询 AsyncVATTasks） |
| 日志增强       | 增加 PushType / Country / 耗时统计                 |
| Swagger 文档   | 生成 OpenAPI 3.0 规范文档                          |

---

## 附录 A：Country 枚举

| 代码 | 国家     | 文件            | 状态     |
| ---- | -------- | --------------- | -------- |
| DE   | 德国     | `countries/de.php` | 已实现 |
| FR   | 法国     | `countries/fr.php` | 已实现 |
| BE   | 比利时   | `countries/be.php` | 预留   |
| GB   | 英国     | `countries/gb.php` | 预留   |
| IT   | 意大利   | `countries/it.php` | 已实现 |
| NL   | 荷兰     | 待创建          | 预留     |
| ES   | 西班牙   | `countries/es.php` | 已实现 |
| PL   | 波兰     | 待创建          | 预留     |
| AT   | 奥地利   | 待创建          | 预留     |
| SE   | 瑞典     | 待创建          | 预留     |
| CZ   | 捷克     | 待创建          | 预留     |
