优化
This commit is contained in:
@@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
|
||||
@@ -16,6 +17,11 @@ public interface IamOnboardingClient {
|
||||
@RequestHeader("X-Internal-Service-Token") String internalToken,
|
||||
@RequestBody OnboardingRequest request);
|
||||
|
||||
@GetMapping("/merchant-registrations/{authUserId}")
|
||||
ApiResponse<OnboardingResponse> registration(
|
||||
@RequestHeader("X-Internal-Service-Token") String internalToken,
|
||||
@PathVariable("authUserId") Long authUserId);
|
||||
|
||||
@DeleteMapping("/merchant-registrations/{authUserId}/compensation")
|
||||
ApiResponse<Void> compensate(
|
||||
@RequestHeader("X-Internal-Service-Token") String internalToken,
|
||||
|
||||
@@ -12,7 +12,7 @@ public record MerchantRegisterRequest(
|
||||
@NotBlank @Size(min = 8, max = 72) String password,
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@NotBlank @Size(max = 128) String companyName,
|
||||
@NotBlank @Size(max = 64) String legalPerson,
|
||||
@Size(max = 64) String legalPerson,
|
||||
@Schema(description = "首个企业管理员的登录手机号;注册时同时初始化企业联系电话,创建后两者独立维护")
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@Email @Size(max = 128) String contactEmail,
|
||||
|
||||
@@ -35,11 +35,20 @@ public class MerchantRegistrationService {
|
||||
@BusinessAudit(event = "MERCHANT_REGISTER", resourceType = "ACCOUNT",
|
||||
resourceId = "#request.username", description = "商户注册", captureAfter = false)
|
||||
public MerchantRegisterResponse register(MerchantRegisterRequest request) {
|
||||
if (accountRepository.existsByUsername(request.username())) {
|
||||
AuthAccount usernameAccount = accountRepository.findByUsername(request.username());
|
||||
AuthAccount phoneAccount = accountRepository.findByPhone(request.phone());
|
||||
if (usernameAccount != null && phoneAccount != null
|
||||
&& usernameAccount.getId().equals(phoneAccount.getId())
|
||||
&& "MERCHANT".equals(usernameAccount.getDefaultAppCode())
|
||||
&& "ACTIVE".equals(usernameAccount.getAccountStatus())
|
||||
&& passwordEncoder.matches(request.password(), usernameAccount.getPasswordHash())) {
|
||||
return existingRegistration(usernameAccount);
|
||||
}
|
||||
if (usernameAccount != null) {
|
||||
throw new BizException(ResultCode.CONFLICT, "用户名已存在");
|
||||
}
|
||||
if (accountRepository.existsByPhone(request.phone())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "手机号已存在");
|
||||
if (phoneAccount != null) {
|
||||
throw new BizException(ResultCode.CONFLICT, "该手机号已注册,请直接登录后继续完善企业资质");
|
||||
}
|
||||
long accountId = IdWorker.getId();
|
||||
String passwordHash = passwordEncoder.encode(request.password());
|
||||
@@ -111,6 +120,24 @@ public class MerchantRegistrationService {
|
||||
"LOGIN_AND_COMPLETE_QUALIFICATIONS");
|
||||
}
|
||||
|
||||
private MerchantRegisterResponse existingRegistration(AuthAccount account) {
|
||||
try {
|
||||
var response = onboardingClient.registration(internalToken, account.getId());
|
||||
if (response == null || !response.successful() || response.data() == null) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "注册状态暂时无法确认,请直接登录后继续完善企业资质");
|
||||
}
|
||||
var onboarding = response.data();
|
||||
if (!java.util.Set.of("PROFILE_REQUIRED", "REJECTED").contains(onboarding.tenantStatus())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "该账号已注册,请直接登录");
|
||||
}
|
||||
return new MerchantRegisterResponse(account.getId(), onboarding.tenantId(), onboarding.membershipId(),
|
||||
onboarding.tenantStatus(), onboarding.dimensionInitializationStatus(),
|
||||
"LOGIN_AND_COMPLETE_QUALIFICATIONS");
|
||||
} catch (FeignException exception) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "注册状态暂时无法确认,请直接登录后继续完善企业资质");
|
||||
}
|
||||
}
|
||||
|
||||
private void registerRollbackCompensation(long accountId, AtomicBoolean compensationCompleted) {
|
||||
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
return;
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
||||
@SpringJUnitConfig(MerchantRegistrationService.class)
|
||||
@TestPropertySource(properties = "baiyue.security.internal-service-token=internal-token")
|
||||
@@ -61,6 +62,49 @@ class MerchantRegistrationServiceTest {
|
||||
assertEquals("PENDING", result.dimensionInitializationStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void exactIncompleteRegistrationRetryReturnsTheExistingRegistration() {
|
||||
AuthAccount account = new AuthAccount();
|
||||
account.setId(9001L);
|
||||
account.setUsername("registered_owner");
|
||||
account.setPhone("13800138000");
|
||||
account.setPasswordHash("encoded-password");
|
||||
account.setAccountStatus("ACTIVE");
|
||||
account.setDefaultAppCode("MERCHANT");
|
||||
when(accounts.findByUsername("registered_owner")).thenReturn(account);
|
||||
when(accounts.findByPhone("13800138000")).thenReturn(account);
|
||||
when(encoder.matches("Password123", "encoded-password")).thenReturn(true);
|
||||
when(onboarding.registration("internal-token", 9001L)).thenReturn(ApiResponse.success(
|
||||
new IamOnboardingClient.OnboardingResponse(10001L, 30001L, "PROFILE_REQUIRED", "READY")));
|
||||
|
||||
var result = service.register(new MerchantRegisterRequest(
|
||||
"registered_owner", "Password123", "注册人", "测试企业", null,
|
||||
"13800138000", "owner@example.com", "CN", "深圳市宝安区"));
|
||||
|
||||
assertEquals(9001L, result.accountId());
|
||||
assertEquals(10001L, result.tenantId());
|
||||
assertEquals("READY", result.dimensionInitializationStatus());
|
||||
verify(onboarding, never()).register(eq("internal-token"), any());
|
||||
verify(accounts, never()).insert(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void phoneOwnedByAnotherUsernameDirectsTheUserBackToLogin() {
|
||||
AuthAccount account = new AuthAccount();
|
||||
account.setId(9001L);
|
||||
account.setUsername("registered_owner");
|
||||
account.setPhone("13800138000");
|
||||
when(accounts.findByPhone("13800138000")).thenReturn(account);
|
||||
|
||||
var failure = assertThrows(com.baiyue.common.core.exception.BizException.class,
|
||||
() -> service.register(new MerchantRegisterRequest(
|
||||
"another_owner", "Password123", "注册人", "测试企业", null,
|
||||
"13800138000", "owner@example.com", "CN", "深圳市宝安区")));
|
||||
|
||||
assertEquals("该手机号已注册,请直接登录后继续完善企业资质", failure.getMessage());
|
||||
verify(onboarding, never()).register(eq("internal-token"), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void failedAuthInsertCompensatesTheIamRegistration() {
|
||||
when(encoder.encode("Password123")).thenReturn("encoded-password");
|
||||
|
||||
Reference in New Issue
Block a user