# justsolutionsWeb — 后端 API 调用清单 > 本文档整理 `justsolutionsWeb`(Angular 16,`justsolutions-web` v1.2.0)前端对后端 API 的全部调用。 > 统计基于源码静态分析(`src/app` 下所有 `*.ts`)。 ## 1. 调用架构概览 所有业务 API 调用都收口在统一的 **`HttpService`**(`src/app/services/http.service.ts`): - **基地址**:请求时把相对路径拼到 `environment.apis.url` 之后,即 `environment.apis.url + request.url`。 - **鉴权**:自动从 `localStorage` 或 `sessionStorage` 读取 `aml_access_token`,存在时加上请求头 `Authorization: Bearer `。 - **请求模型**:统一使用 `Http.Request`(`src/app/models/http.ts`),字段含 `method` / `url` / `body` / `params` / `headers` / `responseType` 等。 > 例外:支付跳转直接 `location.href` 重定向到 QFPay 外部网关(见第 6 节),不经过 `HttpService`。 ### 1.1 环境与基地址配置 | 环境文件 | `apis.url`(API 基地址) | `apis.amlUrl`(AML 门户来源) | `apis.test` | |----------|--------------------------|-------------------------------|-------------| | `environment.ts`(本地默认) | `https://api-aml.iconsz.com` | `https://aml.iconsz.com` | `true` | | `environment.dev.ts` | `https://api-aml.iconsz.com` | `https://aml.iconsz.com` | `true` | | `environment.prod.ts` | `https://api.justsolutions.ai` | `https://aml.justsolutions.ai` | `false` | - `apis.amlUrl`:仅用于 `plans` 页面与父窗口(AML 门户 iframe 宿主)之间的 `postMessage` 通信,并非 HTTP 端点。 - `apis.test`:为 `true` 时支付金额固定写死为 `10`(分),用于测试支付(见第 6 节)。 ## 2. 调用清单(按端点汇总) | # | 方法 | 端点(相对 `apis.url`) | 用途 | 前端方法 | 所在文件 | |---|------|--------------------------|------|----------|----------| | 1 | POST | `/connect/token?__tenant=2C` | OAuth 取 access token | `getToken()` | `modules/aml-query/services/aml-query.service.ts` | | 2 | GET | `/api/aml/ConsumerPortal/GetPrice/{inputCode}` | 查询消费者查询价格 | `getPrice()` | `modules/aml-query/services/aml-query.service.ts` | | 3 | POST | `/api/amlPortal/customer/CreateFeedback` | 提交联系表单反馈 | `sendContactEmailAndReturnFeedback()` | `modules/contact/services/contact.service.ts` | | 4 | POST | `/api/aml/emailQueue/CreateEmailQueue` | 发送通知邮件(管理员 + 用户回执两次调用) | `sendContactEmail()` / `sendContactByReturnEmail()` | `modules/contact/services/contact.service.ts` | | 5 | POST | `/api/amlPortal/plan/portal/GetPlanList` | 获取套餐列表(基础/jQ/加人/KYC) | `getAllPlanList()` | `modules/plans/services/plan.service.ts` | | 6 | POST | `/api/amlPortal/Order/portal/GetEditionList` | 获取系统定义的 edition(所属行业)列表 | `getEditionList()` | `modules/plans/services/plan.service.ts` | | 7 | POST | `/api/amlPortal/Order/getCategoryByTypes` | 获取国家/地区列表(`typeCodes: ['COUNTRY']`) | `getCountryList()` | `modules/plans/services/plan.service.ts` | | 8 | GET | `/api/identity/users/SearchUserByCodeAndType/{userCode}/true` | 校验优惠码/代理商是否存在 | `getAgentor()` | `modules/plans/services/plan.service.ts` | | 9 | POST | `/api/amlPortal/Order/portal/queryRenewableTenant` | 查询可续费租户 | `queryTenant()` | `modules/plans/services/plan.service.ts` | | 10 | POST | `/api/amlPortal/Order/portal/ExistsByOrganizationBRCI` | 校验商业登记号(BR)/公司编号(CI)是否已存在 | `checkBRCI()` | `modules/plans/services/plan.service.ts` | | 11 | POST | `/api/amlPortal/customer/portal/CheckEmailExists/{email}` | 校验管理员邮箱是否已存在 | `checkEmailExist()` | `modules/plans/services/plan.service.ts` | | 12 | POST | `/api/amlPortal/Order/portal/CreateOrder` | 新租户下单 | `createOrder()` | `modules/plans/services/plan.service.ts` | | 13 | POST | `/api/amlPortal/Order/portal/TenantRenewal` | 租户续费下单 | `tenantRenewal()` | `modules/plans/services/plan.service.ts` | | 14 | POST | `/api/amlPortal/Order/portal/PaymentWebhook` | 支付完成回调(作为 `notify_url` 传给 QFPay,由 QFPay 服务端回调,**非前端直接调用**) | — | `modules/plans/pages/tabs/plan4/plan4.component.ts` | ## 3. 鉴权(OAuth Token) **端点 1** — `POST /connect/token?__tenant=2C` - 位置:`AmlQueryService`。在该服务 **构造函数中自动触发**:当 `localStorage` 无 `aml_access_token` 时,调用 `getToken()` 并把返回的 `access_token` 写入 `localStorage`。 - 请求头:`Content-Type: application/x-www-form-urlencoded` - Body(`x-www-form-urlencoded`,硬编码凭证): | 字段 | 值 | |------|-----| | `grant_type` | `password` | | `response_type` | `token` | | `username` | `customer1` | | `password` | `1qaz@WSX` | | `scope` | `FX` | | `client_id` | `customer1_client` | | `client_secret` | `1qaz@WSX` | > ⚠️ 用户名/密码/client secret 以明文硬编码在前端源码中(`aml-query.service.ts:47-51`),属于公开网站内置的固定访客凭证。 ## 4. AML 查询模块(aml-query) **端点 2** — `GET /api/aml/ConsumerPortal/GetPrice/{inputCode}` - 调用方:`aml-query-layout.component.ts`(`ngOnInit` 时以 `getPrice('E')` 拉取价格)。 - 价格的真正计算逻辑在 `AmlQueryService.calculatePrice()`(本地计算,不走接口)。 > 备注:`aml-query/pages/result/result.component.ts`(评估报告页)当前使用 **本地 mock 数据 / `Math.random()`** 生成风险评估结果,PDF 下载指向 `assets/sample-report.pdf`,`apiIntegration()` 弹窗里的 `api.credit-risk.example.com` 等仅为示例文案,**不是真实后端调用**。 ## 5. 联系我们模块(contact) 调用方:`contact/pages/contact/contact.component.ts` 提交表单时触发。 - **端点 3** `POST /api/amlPortal/customer/CreateFeedback`:保存反馈记录。 - Body(`CreateFeedbackParam`):`companyName`、`customerName`、`customerEmail`、`typeOfQuery`、`message`、`userHost`、`destEmail`、`emailSubject`、`emailBody`。 - **端点 4** `POST /api/aml/emailQueue/CreateEmailQueue`:进入邮件发送队列,被调用 **两次**: - `sendContactEmail()` → 通知管理员(收件人 `environment.email.contact`)。 - `sendContactByReturnEmail()` → 给提交者发送回执邮件(收件人为用户填写邮箱)。 - Body(`CreateEmailQueueParam`):`subject`、`to`、`body`(HTML)、`businessType: 2100`、`businessId: ''`。 ## 6. 套餐与下单模块(plans / Order) `PlanService` 集中了套餐查询、校验与下单接口。各端点的页面调用关系: | 端点 | 调用页面 | |------|----------| | `getAllPlanList()`(端点 5) | `plans.component.ts`(进入套餐页 / 收到父窗口 `postMessage` 后) | | `getEditionList()`(端点 6) | `plans.component.ts`、`plan3.component.ts` | | `getCountryList()`(端点 7) | `plans.component.ts`、`plan3.component.ts` | | `getAgentor()`(端点 8) | `plan3.component.ts`(输入优惠码校验) | | `queryTenant()`(端点 9) | `plan1.component.ts`、`plan3.component.ts`(续费选租户) | | `checkBRCI()`(端点 10) | `plan3.component.ts` | | `checkEmailExist()`(端点 11) | `plan1.component.ts`、`plan3.component.ts` | | `createOrder()`(端点 12) | `plan4.component.ts`(`type === 'new'`) | | `tenantRenewal()`(端点 13) | `plan4.component.ts`(`type === 'renew'`) | 关键请求体: - **`getAllPlanList`**(`GetPlanListParam`):`pageIndex: 0`、`pageSize: 9999`、`tag1List: ['B','jQ','j','AdlU','KYC']`、`tag2List`/`tag3List`(由调用方传入)、`agentUserId`。 - **`getCountryList`**:`{ typeCodes: ['COUNTRY'] }`。 - **`checkBRCI`**:通过 `params` 传 `br` / `ci`(query string)。 - **`createOrder`**(`CreateOrderParam`):`planList[]`(`planId`/`planDetailId`/`pcs`)、`tenantName`、`tenantAdminEmail`、`jurisdiction`、`organizationBR`、`organizationCI`、`organizationReference`、`contactPerson`、`companyAddress`、`phone`、`effectiveStartTime`、`agentorId`、`isOfflinePayment: false`、`isAgentBehalf`。 - **`tenantRenewal`**(`TenantRenewalParam`):`targetTenantID`、`planList[]`、`agentorId`、`tenantAdminEmail`、`isOfflinePayment: false`、`isAgentBehalf`。 ### 6.1 支付跳转(QFPay 外部网关,不经过 HttpService) 位置:`plan4.component.ts` 的 `payFn()`。下单成功(`createOrder`/`tenantRenewal` 返回 `code === 0`)后: - 若订单 `paymentStatus === 200` 或 `txamt === 0` → 直接跳转 `plans-plus/payment-success`。 - 否则通过 `location.href` 重定向到 QFPay 收银台: `https://openapi-hk.qfapi.com/checkstand/#/?<参数>&sign=` 主要参数: | 参数 | 值 | |------|-----| | `appcode` | `environment.qfpay.appcode`(固定值) | | `goods_name` | 下单返回的 `planName` | | `out_trade_no` | 下单返回的 `orderCode` | | `paysource` | `remotepay_checkout` | | `return_url` | `{baseUrl}/plans-plus/payment-success` | | `failed_url` | `{baseUrl}/plans-plus/payment-failure` | | `notify_url` | `{apis.url}/api/amlPortal/Order/portal/PaymentWebhook`(端点 14,QFPay 服务端回调后端) | | `txamt` | `apis.test ? 10 : planPrice * 100`(单位:分) | | `txcurrcd` | `HKD` | | `sign` | `sha256(<排序后的参数串> + api_key)` | ## 7. 端点前缀分布 | 前缀 | 含义 | 涉及端点 | |------|------|----------| | `/connect/*` | OpenIddict/IdentityServer OAuth | 端点 1 | | `/api/aml/*` | AML 主模块(消费者查询、邮件队列) | 端点 2、4 | | `/api/amlPortal/*` | AML 门户模块(客户、套餐、订单) | 端点 3、5、6、7、9、10、11、12、13、14 | | `/api/identity/*` | ABP Identity(用户) | 端点 8 | ## 8. 速查(按调用次序的典型流程) - **应用启动**:`AmlQueryService` 构造 → 端点 1 取 token。 - **AML 查询页加载**:端点 2 取价格。 - **联系页提交**:端点 3 + 端点 4(×2)。 - **套餐购买流程**: 1. 进入套餐页:端点 5、6、7。 2. 填写租户/续费信息:端点 8(优惠码)、9(租户)、10(BR/CI)、11(邮箱)。 3. 确认下单:端点 12(新购)或 13(续费)。 4. 跳转 QFPay 支付 → 支付完成后 QFPay 回调端点 14。