|
|
@@ -7,6 +7,7 @@ import com.xuekairui.common.ValidateUtil;
|
|
|
import com.xuekairui.common.event.ActivityEventRedisService;
|
|
|
import com.xuekairui.user.dto.*;
|
|
|
import com.xuekairui.user.entity.User;
|
|
|
+import com.xuekairui.user.entity.LoginLog;
|
|
|
import com.xuekairui.user.enums.LicenseStatus;
|
|
|
import com.xuekairui.user.enums.MembershipLevel;
|
|
|
import com.xuekairui.user.enums.OperationSource;
|
|
|
@@ -52,12 +53,12 @@ public class AuthService {
|
|
|
private final CertificateSyncService certificateSyncService;
|
|
|
private final BusinessLicenseService businessLicenseService;
|
|
|
private final ShopResourceSyncService shopResourceSyncService;
|
|
|
- private final com.xuekairui.user.mapper.LicenseSyncDiffMapper licenseSyncDiffMapper;
|
|
|
private final com.xuekairui.user.mapper.PlatformAccountMapper platformAccountMapper;
|
|
|
private final com.xuekairui.user.mapper.CrawlerUsageLogMapper crawlerUsageLogMapper;
|
|
|
private final com.xuekairui.user.mapper.SearchRecordMapper searchRecordMapper;
|
|
|
private final com.xuekairui.user.mapper.PurchaseIntentMapper purchaseIntentMapper;
|
|
|
private final ActivityEventRedisService activityEventRedisService;
|
|
|
+ private final com.xuekairui.user.mapper.LoginLogMapper loginLogMapper;
|
|
|
|
|
|
/**
|
|
|
* 发送验证码
|
|
|
@@ -788,29 +789,6 @@ public class AuthService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 将双方都审核通过时的字段差异保存到 t_license_sync_diff 表,等待运营确认
|
|
|
- */
|
|
|
- private void saveLicenseSyncDiffRecords(Long userId, Long licenseId, Map<String, String[]> diff) {
|
|
|
- try {
|
|
|
- diff.forEach((field, values) -> {
|
|
|
- com.xuekairui.user.entity.LicenseSyncDiff record =
|
|
|
- com.xuekairui.user.entity.LicenseSyncDiff.builder()
|
|
|
- .licenseId(licenseId)
|
|
|
- .userId(userId)
|
|
|
- .fieldName(field)
|
|
|
- .localValue(values[0])
|
|
|
- .thirdPartyValue(values[1])
|
|
|
- .status(0)
|
|
|
- .build();
|
|
|
- licenseSyncDiffMapper.insert(record);
|
|
|
- });
|
|
|
- log.info("保存入驻信息差异记录成功: licenseId={}, count={}", licenseId, diff.size());
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("保存入驻信息差异记录失败(不阻断同步): licenseId={}, error={}", licenseId, e.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 将第三方传入的入驻字段覆盖到本地记录(非空即覆盖)
|
|
|
*/
|
|
|
@@ -858,82 +836,6 @@ public class AuthService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 检测本地入驻信息与第三方传入字段的不一致项
|
|
|
- * <p>返回 Map:key=字段名,value=[本地值, 第三方值]
|
|
|
- */
|
|
|
- private Map<String, String[]> detectLicenseDiff(
|
|
|
- com.xuekairui.user.entity.BusinessLicense existing,
|
|
|
- SyncShopReportRequest req, String storeName, String terminalType) {
|
|
|
- Map<String, String[]> diff = new java.util.LinkedHashMap<>();
|
|
|
- if (storeName != null && !storeName.equals(existing.getStoreName())) {
|
|
|
- diff.put("storeName", new String[]{existing.getStoreName(), storeName});
|
|
|
- }
|
|
|
- if (terminalType != null && !terminalType.equals(existing.getTerminalType())) {
|
|
|
- diff.put("terminalType", new String[]{existing.getTerminalType(), terminalType});
|
|
|
- }
|
|
|
- putIfDiff(diff, "province", existing.getProvince(), req.getContactProvince());
|
|
|
- putIfDiff(diff, "city", existing.getCity(), req.getContactCity());
|
|
|
- putIfDiff(diff, "district", existing.getDistrict(), req.getContactArea());
|
|
|
- putIfDiff(diff, "storeAddress", existing.getStoreAddress(), req.getContactAddr());
|
|
|
- putIfDiff(diff, "contactPerson", existing.getContactPerson(), req.getContactName());
|
|
|
- putIfDiff(diff, "contactPhone", existing.getContactPhone(), req.getContactPhone());
|
|
|
- putIfDiff(diff, "licenseImageUrl", existing.getLicenseImageUrl(), req.getBusinessLicenseImage());
|
|
|
- putIfDiff(diff, "drugLicenseUrl", existing.getDrugLicenseUrl(), req.getDrugBusinessLicenseImage());
|
|
|
- putIfDiff(diff, "medicalDeviceClass2Url",
|
|
|
- existing.getMedicalDeviceClass2Url(), req.getTwoMedicalDeviceRegistration());
|
|
|
- putIfDiff(diff, "medicalDeviceClass3Url",
|
|
|
- existing.getMedicalDeviceClass3Url(), req.getThreeMedicalDeviceBusinessLicense());
|
|
|
- return diff;
|
|
|
- }
|
|
|
-
|
|
|
- private static void putIfDiff(Map<String, String[]> diff, String field, String local, String third) {
|
|
|
- if (third != null && !third.isBlank() && !third.equals(local)) {
|
|
|
- diff.put(field, new String[]{local, third});
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 记录第三方变更入驻信息的审计日志
|
|
|
- * <p>
|
|
|
- * 第三方同步入驻信息时,我们不对对方谁操作做验证,
|
|
|
- * 只通过对方传过来的用户手机号判断变更了谁的信息。
|
|
|
- * 审计日志中记录:被变更用户的手机号、用户ID、变更前后的字段值。
|
|
|
- *
|
|
|
- * @param phone 第三方传入的用户手机号(用于识别被变更的用户)
|
|
|
- * @param userId 被变更的用户ID
|
|
|
- * @param licenseId 入驻信息ID
|
|
|
- * @param diff 变更字段差异(key=字段名,value=[本地值, 第三方值])
|
|
|
- */
|
|
|
- private void recordThirdPartyUpdateAudit(String phone, Long userId, Long licenseId, Map<String, String[]> diff) {
|
|
|
- try {
|
|
|
- Map<String, Object> beforeData = new java.util.LinkedHashMap<>();
|
|
|
- Map<String, Object> afterData = new java.util.LinkedHashMap<>();
|
|
|
- diff.forEach((field, values) -> {
|
|
|
- beforeData.put(field, values[0]);
|
|
|
- afterData.put(field, values[1]);
|
|
|
- });
|
|
|
-
|
|
|
- // 目标标识:用户手机号 + 用户ID,便于审计时定位"变更了谁的信息"
|
|
|
- String targetIdentifier = String.format("PHONE:%s|USER:%d|LICENSE:%d",
|
|
|
- phone != null ? phone : "UNKNOWN", userId, licenseId);
|
|
|
-
|
|
|
- auditLogService.logSuccess(
|
|
|
- 0L,
|
|
|
- OperatorRole.SYSTEM,
|
|
|
- OperationType.LICENSE_THIRD_UPDATE,
|
|
|
- targetIdentifier,
|
|
|
- licenseId,
|
|
|
- beforeData,
|
|
|
- afterData,
|
|
|
- String.format("第三方变更入驻信息(双方均已审核通过,待运营确认):用户手机号 %s(ID=%d),共 %d 个字段不一致: %s",
|
|
|
- phone != null ? phone : "UNKNOWN", userId, diff.size(), diff.keySet()),
|
|
|
- OperationSource.SYSTEM_SYNC);
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("记录第三方变更入驻信息审计日志失败: licenseId={}, error={}", licenseId, e.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 第三方登录接口同步入驻信息(适配 ExternalTokenRequest → SyncInfoRequest)
|
|
|
*/
|
|
|
@@ -1403,6 +1305,9 @@ public class AuthService {
|
|
|
}
|
|
|
userMapper.updateById(user);
|
|
|
|
|
|
+ // 记录登录日志(用于区分不同端最后登录时间)
|
|
|
+ recordLoginLog(user.getId(), user.getLoginSource(), user.getLastLoginIp());
|
|
|
+
|
|
|
return LoginResponse.builder()
|
|
|
.userId(user.getId())
|
|
|
.accessToken(accessToken)
|
|
|
@@ -1816,6 +1721,7 @@ public class AuthService {
|
|
|
if (unionId != null) {
|
|
|
existUser.setWechatUnionId(unionId);
|
|
|
}
|
|
|
+ existUser.setLoginSource("MINIAPP");
|
|
|
existUser.setLastLoginTime(LocalDateTime.now());
|
|
|
existUser.setLastLoginIp(ip);
|
|
|
userMapper.updateById(existUser);
|
|
|
@@ -1934,4 +1840,24 @@ public class AuthService {
|
|
|
log.warn("外部系统注册失败(不阻断主流程): userId={}", user.getId(), e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录用户登录日志
|
|
|
+ */
|
|
|
+ private void recordLoginLog(Long userId, String loginSource, String ip) {
|
|
|
+ if (userId == null || loginSource == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ LoginLog logEntry = LoginLog.builder()
|
|
|
+ .userId(userId)
|
|
|
+ .loginSource(loginSource)
|
|
|
+ .loginIp(ip)
|
|
|
+ .loginTime(LocalDateTime.now())
|
|
|
+ .build();
|
|
|
+ loginLogMapper.insert(logEntry);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("记录登录日志失败(不阻断登录): userId={}, source={}", userId, loginSource, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|