feat(channel): add channel account event receiver endpoint
This commit is contained in:
@@ -18,7 +18,8 @@ public class AuthInterceptor implements HandlerInterceptor {
|
||||
|| ("POST".equals(method) && isExactPath(path, "/api/v1/account/tenant"))
|
||||
|| ("POST".equals(method) && isExactPath(path, "/api/v1/account/user"))
|
||||
|| isExactPath(path, "/api/v1/health")
|
||||
|| ("POST".equals(method) && isExactPath(path, "/api/v1/channel-account/heartbeat"))) {
|
||||
|| ("POST".equals(method) && isExactPath(path, "/api/v1/channel-account/heartbeat"))
|
||||
|| ("POST".equals(method) && isExactPath(path, "/api/v1/channel-account/event"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.sino.mci.channel.controller;
|
||||
|
||||
import com.sino.mci.channel.dto.ChannelAccountEventRequest;
|
||||
import com.sino.mci.channel.service.ChannelAccountEventService;
|
||||
import com.sino.mci.shared.web.ApiResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/channel-account")
|
||||
@RequiredArgsConstructor
|
||||
public class ChannelAccountEventController {
|
||||
|
||||
private final ChannelAccountEventService eventService;
|
||||
|
||||
@PostMapping("/event")
|
||||
public ApiResponse<?> receiveEvent(@Valid @RequestBody ChannelAccountEventRequest request) {
|
||||
eventService.handleEvent(request);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.sino.mci.channel.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sino.mci.channel.dto.ChannelAccountEventRequest;
|
||||
import com.sino.mci.channel.entity.ChannelAccount;
|
||||
import com.sino.mci.channel.repository.ChannelAccountMapper;
|
||||
import com.sino.mci.channel.repository.ChannelEventRecordMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@Sql(scripts = "/sql/test-channel-account.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
|
||||
class ChannelAccountEventControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Autowired
|
||||
private ChannelAccountMapper accountMapper;
|
||||
|
||||
@Autowired
|
||||
private ChannelEventRecordMapper eventRecordMapper;
|
||||
|
||||
@Test
|
||||
void shouldUpdateAccountOnHeartbeat() throws Exception {
|
||||
ChannelAccountEventRequest request = new ChannelAccountEventRequest();
|
||||
request.setEventId("evt-001");
|
||||
request.setEventType("heartbeat");
|
||||
request.setAccountId("wx-bot-01");
|
||||
request.setTenantCode("rescue");
|
||||
request.setData(Map.of(
|
||||
"login_status", "success",
|
||||
"online_status", "online",
|
||||
"risk_level", 10));
|
||||
|
||||
mockMvc.perform(post("/msg-platform/api/v1/channel-account/event")
|
||||
.contextPath("/msg-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0));
|
||||
|
||||
ChannelAccount account = accountMapper.selectById(1L);
|
||||
assertThat(account.getOnlineStatus()).isEqualTo(1);
|
||||
assertThat(account.getRiskLevel()).isEqualTo(10);
|
||||
assertThat(eventRecordMapper.selectById("evt-001")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIgnoreDuplicateEvent() throws Exception {
|
||||
ChannelAccountEventRequest request = new ChannelAccountEventRequest();
|
||||
request.setEventId("evt-dup-001");
|
||||
request.setEventType("heartbeat");
|
||||
request.setAccountId("wx-bot-01");
|
||||
request.setTenantCode("rescue");
|
||||
request.setData(Map.of("online_status", "online"));
|
||||
|
||||
mockMvc.perform(post("/msg-platform/api/v1/channel-account/event")
|
||||
.contextPath("/msg-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
mockMvc.perform(post("/msg-platform/api/v1/channel-account/event")
|
||||
.contextPath("/msg-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(eventRecordMapper.selectCount(null)).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
DELETE FROM mci_channel_event_record;
|
||||
DELETE FROM mci_channel_account;
|
||||
DELETE FROM mci_tenant;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
INSERT INTO mci_tenant (id, tenant_code, tenant_name, status, create_time)
|
||||
VALUES (1, 'rescue', '救援', 1, NOW());
|
||||
|
||||
INSERT INTO mci_channel_account (id, tenant_code, account_type, channel_type, account_id, account_name, login_status, online_status, risk_level, status, create_time)
|
||||
VALUES (1, 'rescue', 3, 'wechat_personal', 'wx-bot-01', '测试号', 0, 0, 0, 1, NOW());
|
||||
Reference in New Issue
Block a user