|
|
# 实名制采集保存(smz.saveSmzcjxx)— Java 改写说明
|
|
|
|
|
|
> 对应原 C#:`CallClient/TaxTrueNameCaiji.cs` → `BaishuiModel.SmzSaveSmzcjxx`
|
|
|
> 目标:前端传入手机号 / 邮箱 / 固话 / 比对序号,Java 后端再转发调用百税 `smz.saveSmzcjxx`。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 1. 原 C# 行为摘要
|
|
|
|
|
|
```text
|
|
|
办税员弹窗 TaxerInfo
|
|
|
→ 点击「实名采集」(未采集时可见)
|
|
|
→ 弹出 TaxTrueNameCaiji
|
|
|
→ 用户填写:手机号(必填)、电子邮箱、固定电话
|
|
|
→ 点击登记
|
|
|
→ 调用百税 smz.saveSmzcjxx
|
|
|
入参:rxsfzBdxh、sjhm、dzyx、lxdh
|
|
|
→ result.code == "00" → 提示成功,关闭弹窗,隐藏采集按钮并回填手机号
|
|
|
```
|
|
|
|
|
|
比对序号 `rxsfzBdxh` 在原客户端来自办税员窗已加载的 `CompareCode`(取号时人脸比对结果),不在采集窗输入。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 2. 改写后的职责划分
|
|
|
|
|
|
| 角色 | 职责 |
|
|
|
|------|------|
|
|
|
| 前端 | 收集并校验:手机号、电子邮箱、固定电话、人像身份证比对序号;调用 Java API |
|
|
|
| Java 后端 | 接收前端参数 → 校验 → 组装百税请求 → 调用 `smz.saveSmzcjxx` → 将结果返回前端 |
|
|
|
| 百税网关 | 按原协议处理采集保存 |
|
|
|
|
|
|
前端不再直连百税;百税 URL、编码、表单协议只存在于 Java 侧。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 3. Java 对外 API(暴露给前端)
|
|
|
|
|
|
### 3.1 接口定义(建议)
|
|
|
|
|
|
| 项 | 建议值 |
|
|
|
|----|--------|
|
|
|
| Method | `POST` |
|
|
|
| Path | `/api/smz/save-cjxx`(可按现有工程规范调整) |
|
|
|
| Content-Type | `application/json` |
|
|
|
|
|
|
### 3.2 请求 Body
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"rxsfzBdxh": "418206",
|
|
|
"sjhm": "13800138000",
|
|
|
"dzyx": "a@example.com",
|
|
|
"lxdh": "0571-88888888"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
| 字段 | 类型 | 必填 | 含义 | 对应百税字段 |
|
|
|
|------|------|------|------|--------------|
|
|
|
| `rxsfzBdxh` | string | 是 | 人像身份证比对序号 | `rxsfzBdxh` |
|
|
|
| `sjhm` | string | 是 | 手机号码 | `sjhm` |
|
|
|
| `dzyx` | string | 否 | 电子邮箱 | `dzyx` |
|
|
|
| `lxdh` | string | 否 | 固定电话 | `lxdh` |
|
|
|
|
|
|
### 3.3 前端校验(与 C# 对齐)
|
|
|
|
|
|
| 规则 | 说明 |
|
|
|
|------|------|
|
|
|
| `sjhm` 不能为空 | C#:`所登记的手机号不能为空` |
|
|
|
| 占位文案不作为有效值 | C# 会把「请输入手机号码」等占位当成空串 |
|
|
|
| `rxsfzBdxh` 不能为空 | 原客户端从办税员窗带入;Java 版由前端显式传入,后端应二次校验 |
|
|
|
|
|
|
邮箱、固话格式是否严格校验:原 C# 未做正则,Java 侧可选增强,非必须。
|
|
|
|
|
|
### 3.4 响应 Body(建议)
|
|
|
|
|
|
透传百税业务结果,便于前端按原逻辑提示:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"success": true,
|
|
|
"code": "00",
|
|
|
"mess": "保存成功"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
| 字段 | 说明 |
|
|
|
|------|------|
|
|
|
| `success` | Java 层业务成功标志(建议:`code == "00"` 或 `"0"` 时为 true) |
|
|
|
| `code` | 百税 `result.code` |
|
|
|
| `mess` | 百税 `result.mess`;空时可回落「保存成功」 |
|
|
|
|
|
|
失败示例:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"success": false,
|
|
|
"code": "99",
|
|
|
"mess": "无返回错误信息"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
网关/网络异常时返回明确错误信息,HTTP 状态可用 `502` / `500`,或统一 `200` + `success=false`(与现有工程约定一致即可)。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 4. Java 调用百税 `smz.saveSmzcjxx`
|
|
|
|
|
|
### 4.1 百税协议(与 BaiShuiSDK 一致)
|
|
|
|
|
|
| 项 | 值 |
|
|
|
|----|-----|
|
|
|
| Method | `POST` |
|
|
|
| URL | 配置项,对应原 `REALNAME_CHECK_API` / `ApiUrl` |
|
|
|
| Content-Type | `application/x-www-form-urlencoded` |
|
|
|
| Body | `domain.ywId=smz.saveSmzcjxx&domain.parmJson={UrlEncode(JSON)}` |
|
|
|
|
|
|
`parmJson` 序列化规则:
|
|
|
|
|
|
1. 整对象转 JSON(含 `ver`、`bid` 及业务字段)
|
|
|
2. **忽略 null 字段**
|
|
|
3. 中文保持原文,不做 `\uXXXX`
|
|
|
4. 再对整段 JSON 做 URL 编码;建议与 C# `HttpUtils.UrlEncode(..., Encoding.Default)` 对齐(中文环境多为 GBK,`%XX` 大写),避免 `2003 JSON解析出错`
|
|
|
|
|
|
### 4.2 组装给百税的 `parmJson`
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"ver": "1.0",
|
|
|
"bid": "smz.saveSmzcjxx",
|
|
|
"rxsfzBdxh": "418206",
|
|
|
"sjhm": "13800138000",
|
|
|
"dzyx": "a@example.com",
|
|
|
"lxdh": "0571-88888888"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
字段映射:前端入参原样写入同名字段;空的可选字段不传(null 忽略)。
|
|
|
|
|
|
### 4.3 百税响应
|
|
|
|
|
|
HTTP 外层:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"domain": {
|
|
|
"ywId": "smz.saveSmzcjxx",
|
|
|
"retJson": "{\"result\":{\"code\":\"00\",\"mess\":\"保存成功\"}}"
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
解析 `domain.retJson` 后:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"result": {
|
|
|
"code": "00",
|
|
|
"mess": "保存成功"
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
无额外业务字段(`JhxtSaveSmzcjxxResult` 仅含 `code` / `mess`)。
|
|
|
|
|
|
C# SDK 中 `SmzSaveSmzcjxx` **不强制**校验 `code == "00"` 后抛异常,而是把 `result` 交回 UI 判断。Java 建议:
|
|
|
|
|
|
- 能解析出 `result`:按 `code` 组装对外响应,不抛中断(除非工程统一要求失败抛异常)
|
|
|
- 通信失败 / 无 `retJson`:记日志并返回失败给前端
|
|
|
|
|
|
---
|
|
|
|
|
|
## 5. 后端处理流程
|
|
|
|
|
|
```text
|
|
|
① 接收前端 JSON
|
|
|
② 校验 sjhm、rxsfzBdxh 非空(可选:手机号格式)
|
|
|
③ 组装 BsRequest:
|
|
|
ver=1.0, bid=smz.saveSmzcjxx,
|
|
|
rxsfzBdxh, sjhm, dzyx?, lxdh?
|
|
|
④ POST 百税网关(form-urlencoded + UrlEncode)
|
|
|
⑤ 解析 domain.retJson → result.code / result.mess
|
|
|
⑥ 返回给前端(success / code / mess)
|
|
|
```
|
|
|
|
|
|
伪代码:
|
|
|
|
|
|
```java
|
|
|
@PostMapping("/api/smz/save-cjxx")
|
|
|
public ApiResult saveCjxx(@RequestBody SaveSmzcjxxReq req) {
|
|
|
if (isBlank(req.getSjhm())) {
|
|
|
return ApiResult.fail("所登记的手机号不能为空");
|
|
|
}
|
|
|
if (isBlank(req.getRxsfzBdxh())) {
|
|
|
return ApiResult.fail("人像身份证比对序号不能为空");
|
|
|
}
|
|
|
|
|
|
Map<String, Object> parm = new LinkedHashMap<>();
|
|
|
parm.put("ver", "1.0");
|
|
|
parm.put("bid", "smz.saveSmzcjxx");
|
|
|
parm.put("rxsfzBdxh", req.getRxsfzBdxh());
|
|
|
parm.put("sjhm", req.getSjhm());
|
|
|
if (notBlank(req.getDzyx())) parm.put("dzyx", req.getDzyx());
|
|
|
if (notBlank(req.getLxdh())) parm.put("lxdh", req.getLxdh());
|
|
|
|
|
|
BsResult result = bsClient.execute("smz.saveSmzcjxx", parm);
|
|
|
boolean ok = "00".equals(result.getCode()) || "0".equals(result.getCode());
|
|
|
String mess = blankToDefault(result.getMess(), ok ? "保存成功" : "无返回错误信息");
|
|
|
return new ApiResult(ok, result.getCode(), mess);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 6. 配置项
|
|
|
|
|
|
| 配置键(建议) | 含义 | 对应原系统 |
|
|
|
|----------------|------|------------|
|
|
|
| `baishui.api-url` / `REALNAME_CHECK_API` | 百税网关完整 URL | `TaxTrueNameCaiji.ApiUrl` / `SystemControl.Get("REALNAME_CHECK_API")` |
|
|
|
| 超时时间 | HTTP 超时 | C# `PostSync` 约 60s 量级 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 7. 前端对接要点(办税员窗复刻)
|
|
|
|
|
|
1. 打开采集弹窗前,确保已有 `rxsfzBdxh`(来自票的比对序号 / 办税员信息加载结果)。
|
|
|
2. 用户填写 `sjhm`(必填)、`dzyx`、`lxdh`。
|
|
|
3. 调用 Java `/api/smz/save-cjxx`。
|
|
|
4. `success == true`(或 `code == "00"`):
|
|
|
- 提示成功
|
|
|
- 关闭弹窗
|
|
|
- 隐藏「实名采集」按钮
|
|
|
- 回填展示手机号(原 `SetTruceNameCaijiOk`)
|
|
|
5. 失败:展示 `mess`。
|
|
|
|
|
|
说明:查询是否已采集仍可走原逻辑对应的 `smz.getSmzcjxx`(若也改写到 Java,另文说明);**本文仅覆盖采集保存**。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 8. 实现清单
|
|
|
|
|
|
| 优先级 | 项 | 说明 |
|
|
|
|--------|----|------|
|
|
|
| P0 | 对外 REST API | 暴露四个参数,校验手机号与比对序号 |
|
|
|
| P0 | 百税 Client | form-urlencoded + `domain.ywId` / `domain.parmJson` + UrlEncode |
|
|
|
| P0 | 调用 `smz.saveSmzcjxx` | 字段映射与响应解析 |
|
|
|
| P1 | 统一错误码 / 日志 | 记录入参(可脱敏手机号)与百税返回 |
|
|
|
| P2 | 手机号格式校验 | 原 C# 未做,可选 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 9. 源码索引
|
|
|
|
|
|
| 说明 | 路径 |
|
|
|
|------|------|
|
|
|
| 采集弹窗 / 提交 | `CallClient/TaxTrueNameCaiji.cs` |
|
|
|
| 办税员窗打开采集 | `CallClient/WPF/TaxerInfo.xaml.cs` → `Caiji_Click` |
|
|
|
| 成功回调 | `TaxerInfo.SetTruceNameCaijiOk` |
|
|
|
| 请求模型 | `BaiShuiSDK/Request/SmzJhxtSaveSmzcjxxRequest.cs`(`bid = smz.saveSmzcjxx`) |
|
|
|
| 响应模型 | `BaiShuiSDK/Response/SmzJhxtSaveSmzcjxxResponse.cs` |
|
|
|
| SDK 封装 | `BaiShuiSDK/Model/BaishuiModel.cs` → `SmzSaveSmzcjxx` |
|
|
|
| HTTP 协议 | `BaiShuiSDK/Client/BsDefaultClient.cs` |
|
|
|
| 协议参考 | `BaiShuiSDK/smz.rxsfzBd-接口说明.md`(协议相同,bid 不同) |
|