红包、任务需求

This commit is contained in:
hy001 2026-05-08 18:49:00 +08:00
parent 33b970a033
commit 3e4251ba3b
22 changed files with 1191 additions and 218 deletions

View File

@ -1,2 +1,10 @@
spring:
task:
center:
go:
enabled: ${TASK_CENTER_GO_ENABLED:true}
base-url: ${TASK_CENTER_GO_URL:${LIKEI_GATEWAY_ROUTE_GO_URI:http://golang:2900}}
internal-token: ${GAME_INTERNAL_CALLBACK_SECRET:}
timeout-millis: ${TASK_CENTER_GO_TIMEOUT_MILLIS:3000}

View File

@ -71,3 +71,11 @@ red-circle:
telegram:
bot-token: ${LIKEI_ORDER_TELEGRAM_BOT_TOKEN}
webhook-url: ${LIKEI_ORDER_TELEGRAM_WEBHOOK_URL}
task:
center:
go:
enabled: ${TASK_CENTER_GO_ENABLED:true}
base-url: ${TASK_CENTER_GO_URL:${LIKEI_GATEWAY_ROUTE_GO_URI:http://golang:2900}}
internal-token: ${GAME_INTERNAL_CALLBACK_SECRET:}
timeout-millis: ${TASK_CENTER_GO_TIMEOUT_MILLIS:3000}

View File

@ -115,6 +115,22 @@ invite:
internal-token: ${GAME_INTERNAL_CALLBACK_SECRET:}
timeout-millis: ${INVITE_CAMPAIGN_GO_TIMEOUT_MILLIS:10000}
task:
center:
go:
enabled: ${TASK_CENTER_GO_ENABLED:true}
base-url: ${TASK_CENTER_GO_URL:${LIKEI_GATEWAY_ROUTE_GO_URI:http://golang:2900}}
internal-token: ${GAME_INTERNAL_CALLBACK_SECRET:}
timeout-millis: ${TASK_CENTER_GO_TIMEOUT_MILLIS:3000}
voice-room:
region-broadcast:
go:
enabled: ${VOICE_ROOM_REGION_BROADCAST_GO_ENABLED:true}
base-url: ${VOICE_ROOM_REGION_BROADCAST_GO_URL:${TASK_CENTER_GO_URL:${LIKEI_GATEWAY_ROUTE_GO_URI:http://golang:2900}}}
internal-token: ${GAME_INTERNAL_CALLBACK_SECRET:}
timeout-millis: ${VOICE_ROOM_REGION_BROADCAST_GO_TIMEOUT_MILLIS:3000}
activity:
ranking:
reward:

View File

@ -17,13 +17,18 @@ public enum GiftSpecialEnum {
*/
MUSIC,
/**
* 全局通报.
*/
NOTICE,
/**
* 周星.
/**
* 全局通报.
*/
NOTICE,
/**
* 全局广播礼物.
*/
GLOBAL_GIFT,
/**
* 周星.
*/
STAR,

View File

@ -17,9 +17,10 @@ import com.red.circle.live.domain.gateway.LiveMicrophoneGateway;
import com.red.circle.live.domain.live.LiveMicrophone;
import com.red.circle.live.domain.online.LiveRoomUser;
import com.red.circle.live.infra.database.cache.service.LiveMicCacheService;
import com.red.circle.live.infra.database.cache.service.LiveMicUserCacheService;
import com.red.circle.live.infra.database.cache.service.LiveRoomCacheService;
import com.red.circle.live.infra.util.DateTimeAsiaRiyadhUtils;
import com.red.circle.live.infra.database.cache.service.LiveMicUserCacheService;
import com.red.circle.live.infra.database.cache.service.LiveRoomCacheService;
import com.red.circle.live.infra.client.TaskCenterGoClient;
import com.red.circle.live.infra.util.DateTimeAsiaRiyadhUtils;
import com.red.circle.mq.business.model.event.user.UserHeartbeatEvent;
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
import com.red.circle.mq.rocket.business.streams.UserHeartbeatSink;
@ -80,6 +81,7 @@ public class UserHeartbeatListener implements MessageListener {
private final AgoraRoomStateService agoraRoomStateService;
private final AgoraMicMissingConfirmService agoraMicMissingConfirmService;
private final AgoraMicStateCleanupService agoraMicStateCleanupService;
private final TaskCenterGoClient taskCenterGoClient;
private static final int HEARTBEAT_INTERVAL_SECONDS = 60;
@ -336,8 +338,18 @@ public class UserHeartbeatListener implements MessageListener {
return;
}
Long previousRefreshTime = liveMicrophone.getRefreshTime();
liveMicrophone.updateLastActivityTime();
Long currentRefreshTime = liveMicrophone.getRefreshTime();
liveMicCacheService.goUp(roomProfile.getId(), liveMicrophone.getMicIndex(), liveMicrophone);
taskCenterGoClient.reportMicDuration(
Objects.nonNull(event.getSysOrigin()) ? event.getSysOrigin().name() : "",
roomProfile.getId(),
liveMicrophone.getMicIndex(),
event.getUserId(),
previousRefreshTime,
currentRefreshTime,
"HEARTBEAT");
liveMicrophoneGateway.refreshNotActiveUser(roomProfile);
}

View File

@ -0,0 +1,156 @@
package com.red.circle.live.infra.client;
import com.alibaba.fastjson.JSON;
import com.red.circle.live.domain.constant.ActiveSecondConstant;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class TaskCenterGoClient {
private static final String EVENT_TYPE_MIC_DURATION_SECONDS = "MIC_DURATION_SECONDS";
@Value("${task.center.go.enabled:true}")
private boolean enabled;
@Value("${task.center.go.base-url:}")
private String baseUrl;
@Value("${task.center.go.internal-token:}")
private String internalToken;
@Value("${task.center.go.timeout-millis:3000}")
private Integer timeoutMillis;
public void reportMicDuration(String sysOrigin,
Long roomId,
Integer micIndex,
Long userId,
Long previousRefreshTime,
Long currentTime,
String source) {
if (Objects.isNull(userId) || Objects.isNull(previousRefreshTime) || Objects.isNull(currentTime)) {
return;
}
long deltaSeconds = calculateMicDurationSeconds(previousRefreshTime, currentTime);
if (deltaSeconds <= 0) {
return;
}
Map<String, Object> payload = new HashMap<>();
payload.put("source", source);
payload.put("roomId", roomId);
payload.put("micIndex", micIndex);
payload.put("previousRefreshTime", previousRefreshTime);
payload.put("currentTime", currentTime);
reportEvent(new TaskCenterEventRequest()
.setSysOrigin(sysOrigin)
.setEventId("MIC_DURATION:" + Objects.toString(source, "UNKNOWN")
+ ":" + Objects.toString(roomId, "")
+ ":" + Objects.toString(micIndex, "")
+ ":" + userId
+ ":" + previousRefreshTime
+ ":" + currentTime)
.setEventType(EVENT_TYPE_MIC_DURATION_SECONDS)
.setUserId(userId)
.setDeltaValue(deltaSeconds)
.setOccurredAt(Instant.ofEpochMilli(currentTime).toString())
.setPayload(payload));
}
private long calculateMicDurationSeconds(long previousRefreshTime, long currentTime) {
long deltaSeconds = (currentTime - previousRefreshTime) / 1000;
if (deltaSeconds <= 0) {
return 0;
}
return Math.min(deltaSeconds, ActiveSecondConstant.MIC_EXPIRATION_SECOND);
}
private void reportEvent(TaskCenterEventRequest request) {
if (!enabled) {
return;
}
String normalizedBaseUrl = trimRightSlash(Objects.toString(baseUrl, "").trim());
if (normalizedBaseUrl.isEmpty()) {
log.warn("Task center go baseUrl is blank, skip event report. eventId={}", request.getEventId());
return;
}
HttpURLConnection connection = null;
try {
URL url = new URL(normalizedBaseUrl + "/internal/task-center/event");
connection = (HttpURLConnection) url.openConnection();
int timeout = Objects.requireNonNullElse(timeoutMillis, 3000);
connection.setConnectTimeout(timeout);
connection.setReadTimeout(timeout);
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("X-Internal-Token", Objects.toString(internalToken, ""));
byte[] body = JSON.toJSONString(request).getBytes(StandardCharsets.UTF_8);
try (OutputStream outputStream = connection.getOutputStream()) {
outputStream.write(body);
}
int status = connection.getResponseCode();
if (status < 200 || status >= 300) {
log.warn("Task center go report failed. status={}, body={}, eventId={}",
status, readResponse(connection), request.getEventId());
}
} catch (Exception e) {
log.warn("Task center go report error. eventId={}", request.getEventId(), e);
} finally {
if (Objects.nonNull(connection)) {
connection.disconnect();
}
}
}
private String readResponse(HttpURLConnection connection) {
try (InputStream inputStream = connection.getErrorStream() != null
? connection.getErrorStream()
: connection.getInputStream()) {
if (Objects.isNull(inputStream)) {
return "";
}
return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
} catch (Exception e) {
return "";
}
}
private String trimRightSlash(String value) {
while (value.endsWith("/")) {
value = value.substring(0, value.length() - 1);
}
return value;
}
@Data
@Accessors(chain = true)
private static class TaskCenterEventRequest {
private String sysOrigin;
private String eventId;
private String eventType;
private Long userId;
private Long deltaValue;
private String occurredAt;
private Map<String, Object> payload;
}
}

View File

@ -15,9 +15,10 @@ import com.red.circle.live.domain.live.LiveMicrophone;
import com.red.circle.live.domain.live.LiveMusicStatus;
import com.red.circle.live.domain.live.dto.LiveMicrophoneDTO;
import com.red.circle.live.domain.live.dto.LiveMicrophoneNoticeDTO;
import com.red.circle.live.domain.online.LiveRoomUser;
import com.red.circle.live.domain.online.LiveRoomUserRefresh;
import com.red.circle.live.infra.database.cache.service.LiveRoomCacheService;
import com.red.circle.live.domain.online.LiveRoomUser;
import com.red.circle.live.domain.online.LiveRoomUserRefresh;
import com.red.circle.live.infra.client.TaskCenterGoClient;
import com.red.circle.live.infra.database.cache.service.LiveRoomCacheService;
import com.red.circle.live.infra.repository.dto.RefreshOnlineUserNoticeDTO;
import com.red.circle.live.infra.repository.dto.RefreshOnlineUserNoticeDTO.RefreshOnlineUserType;
import com.red.circle.live.infra.convertor.LiveMicInfraConvertor;
@ -90,10 +91,11 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
private final LiveMusicHeartbeatService liveMusicHeartbeatService;
private final LiveMicrophoneInfraConvertor liveMicrophoneInfraConvertor;
private final UserLevelClient userLevelClient;
private final UserOnlineClient userOnlineClient;
private final UserCpClient userCpClient;
private final LiveRoomCacheService liveRoomCacheService;
// private final RedissonClient redissonClient;
private final UserOnlineClient userOnlineClient;
private final UserCpClient userCpClient;
private final LiveRoomCacheService liveRoomCacheService;
private final TaskCenterGoClient taskCenterGoClient;
// private final RedissonClient redissonClient;
@Value("${rtc.authKey}")
private String authKey;
@ -194,12 +196,15 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
// 下掉已上麦克风
List<LiveMicrophone> lives = liveMicCacheService.listLiveMicrophone(roomId, userId);
if (CollectionUtils.isNotEmpty(lives)) {
List<Integer> goDownMicIndex = lives.stream()
List<LiveMicrophone> goDownMicrophones = lives.stream()
.filter(mic -> !Objects.equals(mic.getMicIndex(), micIndex))
.toList();
List<Integer> goDownMicIndex = goDownMicrophones.stream()
.map(LiveMicrophone::getMicIndex)
.filter(index -> !Objects.equals(index, micIndex))
.toList();
if (CollectionUtils.isNotEmpty(goDownMicIndex)) {
liveMicCacheService.goDown(roomId, goDownMicIndex);
reportMicDuration(roomProfile, roomId, goDownMicrophones, "SWITCH_MIC");
}
}
@ -240,18 +245,20 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
// 房间是否真实存在
ResponseAssert.notNull(RoomErrorCode.ROOM_NOT_EXISTS, roomProfile);
// 验证自己是否在当前麦克风
ResponseAssert.isTrue(LiveMicErrorCode.MIC_PERMISSIONS,
liveMicCacheService.checkEqSelf(
roomId,
micIndex,
userId
)
);
// 下麦克风
goDownMic(roomId, micIndex, roomProfile);
}catch (Exception e){
ResponseAssert.isTrue(RoomErrorCode.ROOM_MEMBER_IS_MAX,false);
} finally {
ResponseAssert.isTrue(LiveMicErrorCode.MIC_PERMISSIONS,
liveMicCacheService.checkEqSelf(
roomId,
micIndex,
userId
)
);
LiveMicrophone liveMicrophone = liveMicCacheService.getLiveMicrophone(roomId, micIndex);
// 下麦克风
goDownMic(roomId, micIndex, roomProfile);
reportMicDuration(roomProfile, roomId, liveMicrophone, "GO_DOWN");
}catch (Exception e){
ResponseAssert.isTrue(RoomErrorCode.ROOM_MEMBER_IS_MAX,false);
} finally {
// lock.unlock();
micOpsUnlock(roomId, micIndex);
}
@ -285,27 +292,58 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
micOpsLock(roomId, micIndex);
try {
// 检查权限
checkKillMicRoleOpsPermissions(reqUserRole,
RoomUserRolesEnum.valueOf(liveMicrophone.getUser().getRoles()));
goDownMic(roomId, micIndex, roomProfile);
} finally {
checkKillMicRoleOpsPermissions(reqUserRole,
RoomUserRolesEnum.valueOf(liveMicrophone.getUser().getRoles()));
goDownMic(roomId, micIndex, roomProfile);
reportMicDuration(roomProfile, roomId, liveMicrophone, "KILL_MIC");
} finally {
micOpsUnlock(roomId, micIndex);
}
}
private void goDownMic(Long roomId, Integer micIndex, RoomProfileDTO roomProfile) {
// 下麦克风
liveMicCacheService.goDown(roomId, micIndex);
// 清理活跃用户
liveMicCacheService.refreshNotActiveUser(roomId);
private void goDownMic(Long roomId, Integer micIndex, RoomProfileDTO roomProfile) {
// 下麦克风
liveMicCacheService.goDown(roomId, micIndex);
// 清理活跃用户
liveMicCacheService.refreshNotActiveUser(roomId);
// 发送通知
micUserChangeNotice(roomProfile);
}
private void checkKillMicRoleOpsPermissions(RoomUserRolesEnum reqUserRole,
RoomUserRolesEnum micUserRole) {
micUserChangeNotice(roomProfile);
}
private void reportMicDuration(RoomProfileDTO roomProfile,
Long roomId,
List<LiveMicrophone> microphones,
String source) {
if (Objects.isNull(roomProfile) || CollectionUtils.isEmpty(microphones)) {
return;
}
microphones.forEach(microphone -> reportMicDuration(roomProfile, roomId, microphone, source));
}
private void reportMicDuration(RoomProfileDTO roomProfile,
Long roomId,
LiveMicrophone liveMicrophone,
String source) {
if (Objects.isNull(roomProfile)
|| Objects.isNull(liveMicrophone)
|| Objects.isNull(liveMicrophone.getUser())
|| Objects.isNull(liveMicrophone.getUser().getId())) {
return;
}
taskCenterGoClient.reportMicDuration(
roomProfile.getSysOrigin(),
roomId,
liveMicrophone.getMicIndex(),
liveMicrophone.getUser().getId(),
liveMicrophone.getRefreshTime(),
System.currentTimeMillis(),
source);
}
private void checkKillMicRoleOpsPermissions(RoomUserRolesEnum reqUserRole,
RoomUserRolesEnum micUserRole) {
ResponseAssert.isFalse(LiveMicErrorCode.MIC_PERMISSIONS,
Objects.equals(micUserRole, RoomUserRolesEnum.HOMEOWNER));
ResponseAssert.isFalse(LiveMicErrorCode.MIC_PERMISSIONS,
@ -332,14 +370,16 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
micOpsLock(roomId, mickIndex);
try {
LiveMicSettingSeat settingSeat = liveMicSettingService.getMicSeat(roomId, mickIndex);
ResponseAssert.notNull(LiveMicErrorCode.MIC_INDEX_NOT_FOUND, settingSeat);
settingSeat.setMicLock(Objects.equals(lock, Boolean.TRUE));
liveMicSettingService.updateMicSeat(roomId, settingSeat);
// 下麦克风
liveMicCacheService.goDown(roomId, mickIndex);
// 清理活跃用户
liveMicCacheService.refreshNotActiveUser(roomId);
LiveMicSettingSeat settingSeat = liveMicSettingService.getMicSeat(roomId, mickIndex);
ResponseAssert.notNull(LiveMicErrorCode.MIC_INDEX_NOT_FOUND, settingSeat);
settingSeat.setMicLock(Objects.equals(lock, Boolean.TRUE));
liveMicSettingService.updateMicSeat(roomId, settingSeat);
LiveMicrophone liveMicrophone = liveMicCacheService.getLiveMicrophone(roomId, mickIndex);
// 下麦克风
liveMicCacheService.goDown(roomId, mickIndex);
reportMicDuration(roomProfile, roomId, liveMicrophone, "MIC_LOCK");
// 清理活跃用户
liveMicCacheService.refreshNotActiveUser(roomId);
// 发送通知
micUserChangeNotice(roomProfile, settingSeat);
} finally {
@ -364,34 +404,42 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
}
}
@Override
public void updateMickSize(Long roomId, Integer micSize) {
LiveMicSetting liveMicSetting = liveMicSettingService.updateMicSize(roomId, micSize);
// T下所有麦克风用户
if (CollectionUtils.isEmpty(liveMicSetting.getMicSeats())) {
liveMicCacheService.goDownAll(roomId);
}
List<LiveMicrophone> microphones = liveMicCacheService.listLiveMicrophone(roomId);
if (CollectionUtils.isNotEmpty(microphones)) {
List<Integer> existsMicIndex = microphones.stream().map(LiveMicrophone::getMicIndex)
.toList();
@Override
public void updateMickSize(Long roomId, Integer micSize) {
List<LiveMicrophone> microphones = liveMicCacheService.listLiveMicrophone(roomId);
LiveMicSetting liveMicSetting = liveMicSettingService.updateMicSize(roomId, micSize);
// T下所有麦克风用户
if (CollectionUtils.isEmpty(liveMicSetting.getMicSeats())) {
liveMicCacheService.goDownAll(roomId);
reportMicDuration(roomManagerClient.getById(roomId).getBody(), roomId, microphones, "MIC_SIZE_UPDATE");
micUserChangeNotice(liveMicSetting);
return;
}
if (CollectionUtils.isNotEmpty(microphones)) {
List<Integer> existsMicIndex = microphones.stream().map(LiveMicrophone::getMicIndex)
.toList();
List<Integer> thisNewSeats = liveMicSetting.getMicSeats().stream()
.map(LiveMicSettingSeat::getMicIndex).toList();
List<Integer> removeMicIndex = existsMicIndex.stream()
.filter(micIndex -> !thisNewSeats.contains(micIndex))
.toList();
liveMicCacheService.goDown(roomId, removeMicIndex);
}
micUserChangeNotice(liveMicSetting);
}
.filter(micIndex -> !thisNewSeats.contains(micIndex))
.toList();
if (CollectionUtils.isNotEmpty(removeMicIndex)) {
List<LiveMicrophone> removedMicrophones = microphones.stream()
.filter(mic -> removeMicIndex.contains(mic.getMicIndex()))
.toList();
liveMicCacheService.goDown(roomId, removeMicIndex);
reportMicDuration(roomManagerClient.getById(roomId).getBody(), roomId, removedMicrophones, "MIC_SIZE_UPDATE");
}
}
micUserChangeNotice(liveMicSetting);
}
private RoomProfileDTO checkMicMutePermissions(Long roomId, Long opsUserId) {
RoomProfileDTO roomProfile = roomManagerClient.getById(roomId).getBody();

View File

@ -0,0 +1,143 @@
package com.red.circle.order.app.common.task;
import com.alibaba.fastjson.JSON;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class TaskCenterGoClient {
private static final String EVENT_TYPE_RECHARGE_GOLD = "RECHARGE_GOLD";
@Value("${task.center.go.enabled:true}")
private boolean enabled;
@Value("${task.center.go.base-url:}")
private String baseUrl;
@Value("${task.center.go.internal-token:}")
private String internalToken;
@Value("${task.center.go.timeout-millis:3000}")
private Integer timeoutMillis;
public void reportRechargeGold(String sysOrigin,
Long userId,
Long purchaseHistoryId,
BigDecimal candyQuantity,
String platform,
String payPlatform,
Instant occurredAt) {
if (Objects.isNull(userId) || Objects.isNull(purchaseHistoryId) || Objects.isNull(candyQuantity)) {
return;
}
long deltaValue = candyQuantity.setScale(0, RoundingMode.DOWN).longValue();
if (deltaValue <= 0) {
return;
}
Map<String, Object> payload = new HashMap<>();
payload.put("purchaseHistoryId", purchaseHistoryId);
payload.put("candyQuantity", candyQuantity);
payload.put("platform", platform);
payload.put("payPlatform", payPlatform);
reportEvent(new TaskCenterEventRequest()
.setSysOrigin(sysOrigin)
.setEventId("RECHARGE_GOLD:" + purchaseHistoryId)
.setEventType(EVENT_TYPE_RECHARGE_GOLD)
.setUserId(userId)
.setDeltaValue(deltaValue)
.setOccurredAt(Objects.requireNonNullElse(occurredAt, Instant.now()).toString())
.setPayload(payload));
}
private void reportEvent(TaskCenterEventRequest request) {
if (!enabled) {
return;
}
String normalizedBaseUrl = trimRightSlash(Objects.toString(baseUrl, "").trim());
if (normalizedBaseUrl.isEmpty()) {
log.warn("Task center go baseUrl is blank, skip event report. eventId={}", request.getEventId());
return;
}
HttpURLConnection connection = null;
try {
URL url = new URL(normalizedBaseUrl + "/internal/task-center/event");
connection = (HttpURLConnection) url.openConnection();
int timeout = Objects.requireNonNullElse(timeoutMillis, 3000);
connection.setConnectTimeout(timeout);
connection.setReadTimeout(timeout);
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("X-Internal-Token", Objects.toString(internalToken, ""));
byte[] body = JSON.toJSONString(request).getBytes(StandardCharsets.UTF_8);
try (OutputStream outputStream = connection.getOutputStream()) {
outputStream.write(body);
}
int status = connection.getResponseCode();
if (status < 200 || status >= 300) {
log.warn("Task center go report failed. status={}, body={}, eventId={}",
status, readResponse(connection), request.getEventId());
}
} catch (Exception e) {
log.warn("Task center go report error. eventId={}", request.getEventId(), e);
} finally {
if (Objects.nonNull(connection)) {
connection.disconnect();
}
}
}
private String readResponse(HttpURLConnection connection) {
try (InputStream inputStream = connection.getErrorStream() != null
? connection.getErrorStream()
: connection.getInputStream()) {
if (Objects.isNull(inputStream)) {
return "";
}
return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
} catch (Exception e) {
return "";
}
}
private String trimRightSlash(String value) {
while (value.endsWith("/")) {
value = value.substring(0, value.length() - 1);
}
return value;
}
@Data
@Accessors(chain = true)
private static class TaskCenterEventRequest {
private String sysOrigin;
private String eventId;
private String eventType;
private Long userId;
private Long deltaValue;
private String occurredAt;
private Map<String, Object> payload;
}
}

View File

@ -14,10 +14,11 @@ import com.red.circle.component.mq.service.ConsumerMessage;
import com.red.circle.component.mq.service.MessageListener;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
import com.red.circle.mq.business.model.event.pay.PurchaseProductEvent;
import com.red.circle.mq.rocket.business.streams.BuySuccessSink;
import com.red.circle.other.inner.endpoint.activity.CumulativeRechargeClient;
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
import com.red.circle.mq.business.model.event.pay.PurchaseProductEvent;
import com.red.circle.mq.rocket.business.streams.BuySuccessSink;
import com.red.circle.order.app.common.task.TaskCenterGoClient;
import com.red.circle.other.inner.endpoint.activity.CumulativeRechargeClient;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.endpoint.sys.EnumConfigClient;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
@ -67,8 +68,9 @@ public class BuySuccessListener implements MessageListener {
private final WalletDiamondClient walletDiamondClient;
private final MessageEventProcess messageEventProcess;
private final UserOneTimeTaskClient userOneTimeTaskClient;
private final CumulativeRechargeClient cumulativeRechargeClient;
private final RedisService redisService;
private final CumulativeRechargeClient cumulativeRechargeClient;
private final RedisService redisService;
private final TaskCenterGoClient taskCenterGoClient;
@Override
public Action consume(ConsumerMessage message) {
@ -121,10 +123,18 @@ public class BuySuccessListener implements MessageListener {
if (!ArithmeticUtils.gt(eventBody.getCandyQuantity(), BigDecimal.ZERO)
|| Objects.equals(eventBody.getTrialPeriod(), Boolean.TRUE)) {
return;
}
userExpandClient.updatePurchasingToTrue(eventBody.getUserId());
return;
}
taskCenterGoClient.reportRechargeGold(eventBody.getSysOrigin(),
eventBody.getUserId(),
eventBody.getPurchaseHistoryId(),
eventBody.getCandyQuantity(),
eventBody.getPlatform(),
eventBody.getPayPlatform(),
Objects.nonNull(eventBody.getBuyDateTime()) ? eventBody.getBuyDateTime().toInstant() : null);
userExpandClient.updatePurchasingToTrue(eventBody.getUserId());
//累计今日充值每日累计充值抽奖活动
cumulativeRechargeClient.incrTodayRechargeScore(

View File

@ -19,8 +19,9 @@ import com.red.circle.framework.core.security.UserCredential;
import com.red.circle.framework.web.annotation.IgnoreResultResponse;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.common.task.TaskCenterGoClient;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.game.GameLxwlUpdateBalanceCmd;
import com.red.circle.other.app.dto.cmd.game.GameLxwlUserInfoCmd;
import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskProgressUpdateCmd;
@ -49,8 +50,9 @@ import com.red.circle.tool.core.parse.DataTypeUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.tool.crypto.SecurityUtils;
import java.math.BigDecimal;
import java.util.Map;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -87,8 +89,9 @@ public class GameHkysRestController {
private final RankingActivityService rankingActivityService;
private final GameActivityService gameActivityService;
private final RedisService redisService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final TaskCenterGoClient taskCenterGoClient;
@IgnoreResultResponse
@PostMapping("/getUserInfo")
@ -193,10 +196,13 @@ public class GameHkysRestController {
// 累加用户获得的金币并发送抽奖券
// activityRechargeTicketService.accumulatedRechargeAndAddTicket(userId, Math.abs(cmd.getCoin()), MonthlyRechargeType.UNDEFINED);
} else {
updateRoomDailyTask(cmd.getCoin(), userId);
}
} else {
updateRoomDailyTask(cmd.getCoin(), userId);
reportTaskCenterGameEvents(sysOrigin, userId, "LINGXIAN", cmd.getOrderId(),
Math.abs(cmd.getCoin()), gameTaskPayload("LINGXIAN", cmd.getOrderId(), cmd.getGameId(),
cmd.getRoundId(), cmd.getRoomId()));
}
return new HkysResponse<JSONObject>()
@ -204,7 +210,7 @@ public class GameHkysRestController {
.setData(jsonObject);
}
private void updateRoomDailyTask(Long coins, Long userId) {
private void updateRoomDailyTask(Long coins, Long userId) {
RoomDailyTaskCode taskType = RoomDailyTaskCode.PERSONAL_GAME_CONSUME;
String redisKey = "room:daily:task:progress:" + taskType.name() + ":" + userId + ":" + ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
Long total = redisService.increment(redisKey, Math.abs(coins.intValue()));
@ -215,9 +221,28 @@ public class GameHkysRestController {
.setTaskCode(taskType.name())
.setProgressValue(total.intValue())
);
}
private void incGameRankingRecord(GameLxwlUpdateBalanceCmd request, GameListConfig gameListConfig) {
}
private void reportTaskCenterGameEvents(String sysOrigin,
Long userId,
String provider,
String orderId,
Long consumeGold,
Map<String, Object> payload) {
taskCenterGoClient.reportGameConsumeGold(sysOrigin, userId, provider, orderId, consumeGold, payload);
}
private Map<String, Object> gameTaskPayload(String provider, String orderId, String gameId, String roundId, String roomId) {
Map<String, Object> payload = new HashMap<>();
payload.put("provider", provider);
payload.put("orderId", orderId);
payload.put("gameId", gameId);
payload.put("roundId", roundId);
payload.put("roomId", roomId);
return payload;
}
private void incGameRankingRecord(GameLxwlUpdateBalanceCmd request, GameListConfig gameListConfig) {
if (request.getType() != 2 || gameListConfig == null || request.getCoin() <= 0) {
return;
}

View File

@ -15,10 +15,10 @@ import com.red.circle.framework.core.response.ResponseErrorCode;
import com.red.circle.mq.business.model.event.approval.CensorContent;
import com.red.circle.mq.business.model.event.approval.CensorProfileEvent;
import com.red.circle.mq.business.model.event.dynamic.DynamicEvent;
import com.red.circle.mq.rocket.business.producer.CensorMqMessage;
import com.red.circle.mq.rocket.business.producer.DynamicMqMessage;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicListCO;
import com.red.circle.mq.rocket.business.producer.CensorMqMessage;
import com.red.circle.mq.rocket.business.producer.DynamicMqMessage;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicListCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicContentAddCmd;
import com.red.circle.other.app.enums.violation.ViolationTypeEnum;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
@ -84,12 +84,12 @@ public class DynamicContentAddCmdExe {
private final DynamicTimelineService dynamicTimelineService;
private final DynamicBlacklistService dynamicBlacklistService;
private final ApprovalDynamicContentService approvalDynamicContentService;
private final TaskMqMessage taskMqMessage;
private final UserAccountCommon userAccountCommon;
private final AdministratorService administratorService;
private final AdministratorAuthService administratorAuthService;
public DynamicListCO execute(DynamicContentAddCmd cmd) {
private final TaskMqMessage taskMqMessage;
private final UserAccountCommon userAccountCommon;
private final AdministratorService administratorService;
private final AdministratorAuthService administratorAuthService;
public DynamicListCO execute(DynamicContentAddCmd cmd) {
//校验参数
checkParameters(cmd);
@ -97,12 +97,12 @@ public class DynamicContentAddCmdExe {
Long contentId = IdWorkerUtils.getId();
//保存动态
DynamicListCO save = save(cmd, contentId);
dynamicCacheService.incrUserTodayDynamicCount(cmd.getReqUserId());
if (CollectionUtils.isEmpty(cmd.getPictures())) {
return save;
DynamicListCO save = save(cmd, contentId);
dynamicCacheService.incrUserTodayDynamicCount(cmd.getReqUserId());
if (CollectionUtils.isEmpty(cmd.getPictures())) {
return save;
}
sendViolationContentMq(cmd);

View File

@ -1,8 +1,9 @@
package com.red.circle.other.app.command.game.ludo;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.common.game.GameTurntableCommon;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.common.task.TaskCenterGoClient;
import com.red.circle.other.app.common.game.GameTurntableCommon;
import com.red.circle.other.app.dto.cmd.game.GameTurntableGameIdCmd;
import com.red.circle.other.infra.database.cache.key.GameListKeys;
import com.red.circle.other.infra.database.cache.service.other.MarkCacheService;
@ -13,10 +14,12 @@ import com.red.circle.other.inner.asserts.RoomErrorCode;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.dto.WalletReceiptDTO;
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -30,9 +33,10 @@ import org.springframework.stereotype.Service;
public class GameJoinCmdExe {
private final MarkCacheService markCacheService;
private final WalletGoldClient walletGoldClient;
private final GameTurntableCommon gameTurntableCommon;
private final RoomTurntableGameMongoService roomTurntableGameMongoService;
private final WalletGoldClient walletGoldClient;
private final GameTurntableCommon gameTurntableCommon;
private final RoomTurntableGameMongoService roomTurntableGameMongoService;
private final TaskCenterGoClient taskCenterGoClient;
/**
* 加入游戏.
@ -69,8 +73,9 @@ public class GameJoinCmdExe {
// 9104 游戏人数已满
ResponseAssert.isTrue(RoomErrorCode.GAME_THE_NUMBER_FULL,
getJoinQuantity(cmd.getGameId()) <= 12);
gameTurntableCommon.join(cmd.getReqUserId(), roomTurntableGame);
WalletReceiptDTO walletReceiptDTO = new WalletReceiptDTO();
gameTurntableCommon.join(cmd.getReqUserId(), roomTurntableGame);
reportTaskCenterGameEvents(cmd, roomTurntableGame);
WalletReceiptDTO walletReceiptDTO = new WalletReceiptDTO();
walletReceiptDTO.setBalance(walletReceipt.getBalance().getDollarAmount());
walletReceiptDTO.setProcessAmount(walletReceipt.getOpAmount().getDollarAmount());
return walletReceiptDTO;
@ -84,8 +89,19 @@ public class GameJoinCmdExe {
return GameListKeys.getKey("TGAME_USIZE", String.valueOf(gameId));
}
private String getJoinedKey(Long gameId, Long userId) {
return GameListKeys.getKey("TGAME_JOINED:" + gameId, String.valueOf(userId));
}
}
private String getJoinedKey(Long gameId, Long userId) {
return GameListKeys.getKey("TGAME_JOINED:" + gameId, String.valueOf(userId));
}
private void reportTaskCenterGameEvents(GameTurntableGameIdCmd cmd, RoomTurntableGame roomTurntableGame) {
Long consumeGold = roomTurntableGame.getGameGolds().longValue();
String orderId = roomTurntableGame.getGameId() + ":" + cmd.getReqUserId();
Map<String, Object> payload = new HashMap<>();
payload.put("provider", "TURNTABLE");
payload.put("gameId", roomTurntableGame.getGameId());
payload.put("roomId", roomTurntableGame.getRoomId());
taskCenterGoClient.reportGameConsumeGold(cmd.requireReqSysOrigin(), cmd.getReqUserId(),
"TURNTABLE", orderId, consumeGold, payload);
}
}

View File

@ -1,7 +1,8 @@
package com.red.circle.other.app.command.game.ludo;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.convertor.game.GameLudoAppConvertor;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.common.task.TaskCenterGoClient;
import com.red.circle.other.app.convertor.game.GameLudoAppConvertor;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.game.GameLudoJoinCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
@ -18,9 +19,11 @@ import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.math.BigDecimal;
import java.util.Objects;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@ -36,9 +39,10 @@ public class GameLudoJoinCmdExe {
private final GameCacheService gameCacheService;
private final WalletGoldClient walletGoldClient;
private final UserProfileGateway userProfileGateway;
private final GameLudoRunService gameLudoRunService;
private final GameLudoAppConvertor gameLudoAppConvertor;
private final UserProfileAppConvertor userProfileAppConvertor;
private final GameLudoRunService gameLudoRunService;
private final GameLudoAppConvertor gameLudoAppConvertor;
private final UserProfileAppConvertor userProfileAppConvertor;
private final TaskCenterGoClient taskCenterGoClient;
public void execute(GameLudoJoinCmd cmd) {
UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
@ -70,11 +74,12 @@ public class GameLudoJoinCmdExe {
.setPlayerProfile(gameLudoAppConvertor.userProfileToPlayerProfile(userProfile))
.setCreateTime(TimestampUtils.now())
);
gameLudoRunService.resetPlayers(gameLudoRun.getId(), gameLudoRun.getPlayers());
gameCacheService.setJoinGameLudo(gameLudoRun.getId(), cmd.getPlayerUserId());
}
gameLudoRunService.resetPlayers(gameLudoRun.getId(), gameLudoRun.getPlayers());
gameCacheService.setJoinGameLudo(gameLudoRun.getId(), cmd.getPlayerUserId());
reportTaskCenterGameEvents(cmd, gameLudoRun, consumeAmount);
}
private BigDecimal executeConsumeAmount(GameLudoJoinCmd cmd, BigDecimal amount) {
private BigDecimal executeConsumeAmount(GameLudoJoinCmd cmd, BigDecimal amount) {
if (Objects.isNull(amount) || ArithmeticUtils.lteZero(amount)) {
return BigDecimal.ZERO;
}
@ -86,6 +91,16 @@ public class GameLudoJoinCmdExe {
.origin(GoldOrigin.LUDO_GAME)
.amount(amount)
.build())
).getBalance().getDollarAmount();
}
}
).getBalance().getDollarAmount();
}
private void reportTaskCenterGameEvents(GameLudoJoinCmd cmd, GameLudoRun gameLudoRun, BigDecimal consumeAmount) {
String orderId = gameLudoRun.getId() + ":" + cmd.getPlayerUserId();
Map<String, Object> payload = new HashMap<>();
payload.put("provider", "LUDO");
payload.put("gameId", gameLudoRun.getId());
payload.put("roomId", gameLudoRun.getRoomId());
taskCenterGoClient.reportGameConsumeGold(cmd.requireReqSysOrigin(), cmd.getPlayerUserId(),
"LUDO", orderId, consumeAmount.longValue(), payload);
}
}

View File

@ -0,0 +1,89 @@
package com.red.circle.other.app.common.gift;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.Objects;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class VoiceRoomRegionBroadcastGoClient {
@Value("${voice-room.region-broadcast.go.enabled:true}")
private boolean enabled;
@Value("${voice-room.region-broadcast.go.base-url:}")
private String baseUrl;
@Value("${voice-room.region-broadcast.go.internal-token:}")
private String internalToken;
@Value("${voice-room.region-broadcast.go.timeout-millis:3000}")
private Integer timeoutMillis;
public boolean send(RegionBroadcastRequest request) {
if (!enabled) {
return false;
}
String normalizedBaseUrl = trimRightSlash(Objects.toString(baseUrl, "").trim());
if (normalizedBaseUrl.isEmpty()) {
log.warn("Voice room region broadcast go baseUrl is blank, skip broadcast. type={}, senderUserId={}",
request.getType(), request.getSenderUserId());
return false;
}
try (HttpResponse response = HttpUtil.createPost(normalizedBaseUrl
+ "/internal/voice-room/region-broadcast")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("X-Internal-Token", Objects.toString(internalToken, ""))
.timeout(Objects.requireNonNullElse(timeoutMillis, 3000))
.body(JSON.toJSONString(request))
.execute()) {
String responseBody = response.body();
if (response.getStatus() < 200 || response.getStatus() >= 300) {
log.warn("Voice room region broadcast go http failed. status={}, body={}, type={}, senderUserId={}",
response.getStatus(), responseBody, request.getType(), request.getSenderUserId());
return false;
}
if (responseBody == null || responseBody.trim().isEmpty()) {
return true;
}
JSONObject root = JSON.parseObject(responseBody);
if (root != null && root.containsKey("status") && !root.getBooleanValue("status")) {
log.warn("Voice room region broadcast go business failed. body={}, type={}, senderUserId={}",
responseBody, request.getType(), request.getSenderUserId());
return false;
}
return true;
} catch (Exception e) {
log.warn("Voice room region broadcast go error. type={}, senderUserId={}",
request.getType(), request.getSenderUserId(), e);
return false;
}
}
private String trimRightSlash(String value) {
while (value.endsWith("/")) {
value = value.substring(0, value.length() - 1);
}
return value;
}
@Data
@Accessors(chain = true)
public static class RegionBroadcastRequest {
private String sysOrigin;
private String regionCode;
private Long senderUserId;
private String type;
private Object data;
}
}

View File

@ -0,0 +1,99 @@
package com.red.circle.other.app.common.task;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class TaskCenterGoClient {
private static final String EVENT_TYPE_GAME_CONSUME_GOLD = "GAME_CONSUME_GOLD";
@Value("${task.center.go.enabled:true}")
private boolean enabled;
@Value("${task.center.go.base-url:}")
private String baseUrl;
@Value("${task.center.go.internal-token:}")
private String internalToken;
@Value("${task.center.go.timeout-millis:3000}")
private Integer timeoutMillis;
public void reportGameConsumeGold(String sysOrigin,
Long userId,
String provider,
String orderId,
Long deltaGold,
Map<String, Object> payload) {
if (Objects.isNull(userId) || Objects.isNull(deltaGold) || deltaGold <= 0) {
return;
}
String eventId = "GAME_CONSUME:" + Objects.toString(provider, "UNKNOWN") + ":"
+ Objects.toString(orderId, "");
reportEvent(new TaskCenterEventRequest()
.setSysOrigin(sysOrigin)
.setEventId(eventId)
.setEventType(EVENT_TYPE_GAME_CONSUME_GOLD)
.setUserId(userId)
.setDeltaValue(deltaGold)
.setOccurredAt(Instant.now().toString())
.setPayload(payload));
}
private void reportEvent(TaskCenterEventRequest request) {
if (!enabled) {
return;
}
String normalizedBaseUrl = trimRightSlash(Objects.toString(baseUrl, "").trim());
if (normalizedBaseUrl.isEmpty()) {
log.warn("Task center go baseUrl is blank, skip event report. eventId={}", request.getEventId());
return;
}
try (HttpResponse response = HttpUtil.createPost(normalizedBaseUrl + "/internal/task-center/event")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("X-Internal-Token", Objects.toString(internalToken, ""))
.timeout(Objects.requireNonNullElse(timeoutMillis, 3000))
.body(JSON.toJSONString(request))
.execute()) {
if (response.getStatus() < 200 || response.getStatus() >= 300) {
log.warn("Task center go report failed. status={}, body={}, eventId={}",
response.getStatus(), response.body(), request.getEventId());
}
} catch (Exception e) {
log.warn("Task center go report error. eventId={}", request.getEventId(), e);
}
}
private String trimRightSlash(String value) {
while (value.endsWith("/")) {
value = value.substring(0, value.length() - 1);
}
return value;
}
@Data
@Accessors(chain = true)
private static class TaskCenterEventRequest {
private String sysOrigin;
private String eventId;
private String eventType;
private Long userId;
private Long deltaValue;
private String occurredAt;
private Map<String, Object> payload;
}
}

View File

@ -30,11 +30,12 @@ import com.red.circle.mq.rocket.business.producer.GiftMqMessage;
import com.red.circle.mq.rocket.business.streams.GiveGiftSink;
import com.red.circle.other.app.command.game.barrage.BarrageGameBaishunExe;
import com.red.circle.other.app.command.game.burstcrystal.GameBurstCrystalScheduleTwoFunQueryExe;
import com.red.circle.other.app.command.game.roompk.GameRoomPkUserCmdExe;
import com.red.circle.other.app.command.game.teampk.GameTeamPkBaseInfoCmdExe;
import com.red.circle.other.app.common.gift.GameLuckyGiftCommon;
import com.red.circle.other.app.dto.clientobject.game.*;
import com.red.circle.other.app.dto.clientobject.gift.SendGiftNotifyCO;
import com.red.circle.other.app.command.game.roompk.GameRoomPkUserCmdExe;
import com.red.circle.other.app.command.game.teampk.GameTeamPkBaseInfoCmdExe;
import com.red.circle.other.app.common.gift.GameLuckyGiftCommon;
import com.red.circle.other.app.common.gift.VoiceRoomRegionBroadcastGoClient;
import com.red.circle.other.app.dto.clientobject.game.*;
import com.red.circle.other.app.dto.clientobject.gift.SendGiftNotifyCO;
import com.red.circle.other.app.dto.cmd.game.barrage.GameUserEffectsCmd;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.domain.live.LiveHeartbeatCache;
@ -91,9 +92,10 @@ public class GiveGiftsListener implements MessageListener {
private final GiftMqMessage giftMqMessage;
private final TeamMemberService teamMemberService;
private final UserRegionGateway userRegionGateway;
private final MessageEventProcess messageEventProcess;
private final GameLuckyGiftCommon gameLuckyGiftCommon;
private final TeamBillCycleService teamBillCycleService;
private final MessageEventProcess messageEventProcess;
private final GameLuckyGiftCommon gameLuckyGiftCommon;
private final VoiceRoomRegionBroadcastGoClient voiceRoomRegionBroadcastGoClient;
private final TeamBillCycleService teamBillCycleService;
private final TeamPolicyManagerService teamPolicyManagerService;
private final EnumConfigCacheService enumConfigCacheService;
private final LiveHeartbeatCacheService liveHeartbeatCacheService;
@ -418,7 +420,12 @@ public class GiveGiftsListener implements MessageListener {
return;
}
String special = event.getGiftConfig().getSpecial();
if (StringUtils.isBlank(special) || !special.contains(GiftSpecialEnum.NOTICE.name())) {
if (StringUtils.isBlank(special)) {
return;
}
boolean noticeGift = special.contains(GiftSpecialEnum.NOTICE.name());
boolean globalGift = special.contains(GiftSpecialEnum.GLOBAL_GIFT.name());
if (!noticeGift && !globalGift) {
return;
}
@ -442,15 +449,30 @@ public class GiveGiftsListener implements MessageListener {
.setActualAmount(runningWater.getGiftValue().getActualAmount())
.setGiftType(runningWater.getGiftValue().getGiftType());
imGroupClient.sendMessageBroadcast(
BroadcastGroupMsgBodyCmd.builder()
.toPlatform(event.getSysOrigin())
.type(GroupMessageTypeEnum.SEND_GIFT)
.data(notify)
.build()
);
log.warn("NOTICE礼物全服通报成功, trackId={}, giftId={}, sendUserId={}",
event.getTrackId(), event.getGiftConfig().getId(), event.getSendUserId());
if (globalGift) {
boolean success = voiceRoomRegionBroadcastGoClient.send(
new VoiceRoomRegionBroadcastGoClient.RegionBroadcastRequest()
.setSysOrigin(event.getSysOrigin().name())
.setSenderUserId(event.getSendUserId())
.setType(GroupMessageTypeEnum.SEND_GIFT.name())
.setData(notify)
);
log.warn("GLOBAL_GIFT礼物区域广播{}, trackId={}, giftId={}, sendUserId={}",
success ? "成功" : "失败", event.getTrackId(), event.getGiftConfig().getId(),
event.getSendUserId());
}
if (noticeGift) {
imGroupClient.sendMessageBroadcast(
BroadcastGroupMsgBodyCmd.builder()
.toPlatform(event.getSysOrigin())
.type(GroupMessageTypeEnum.SEND_GIFT)
.data(notify)
.build()
);
log.warn("NOTICE礼物全服通报成功, trackId={}, giftId={}, sendUserId={}",
event.getTrackId(), event.getGiftConfig().getId(), event.getSendUserId());
}
}
private Pair<GiftGiveRunningWater,Boolean> saveRunningWater(GiveAwayGiftBatchEvent event) {

View File

@ -22,8 +22,9 @@ import com.red.circle.framework.core.exception.ResponseException;
import com.red.circle.framework.core.security.UserCredential;
import com.red.circle.mq.business.model.event.task.TaskApprovalEvent;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.common.task.TaskCenterGoClient;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskProgressUpdateCmd;
import com.red.circle.other.app.enums.violation.GameOriginEnum;
@ -56,9 +57,10 @@ import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd.GoldReceiptCmdBuilder;
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Objects;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -89,9 +91,10 @@ public class GameBaishunServiceImpl implements GameBaishunService {
private final GameRankingGateway gameRankingGateway;
private final GameListCacheService gameListCacheService;
private final TaskService taskService;
private final GameActivityService gameActivityService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final GameActivityService gameActivityService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final TaskCenterGoClient taskCenterGoClient;
@Value("${red-circle.game-rank.gameid}")
private String gameId;
@ -227,10 +230,13 @@ public class GameBaishunServiceImpl implements GameBaishunService {
// 累加用户获得的金币并发送抽奖券
// activityRechargeTicketService.accumulatedRechargeAndAddTicket(userId, request.getCurrencyDiff(), MonthlyRechargeType.UNDEFINED);
} else {
updateRoomDailyTask(request.getCurrencyDiff(), userId);
}
}
} else {
updateRoomDailyTask(request.getCurrencyDiff(), userId);
reportTaskCenterGameEvents(sysOrigin, userId, "BAISHUN_LEGACY", request.getOrderId(),
Math.abs(request.getCurrencyDiff()), gameTaskPayload("BAISHUN_LEGACY",
request.getOrderId(), request.getGameId(), request.getGameRoundId(), null));
}
}
log.warn("{} 发送游戏获奖通知--金币数量{}", GoldOrigin.BAISHUN_GAME.name(), request.getCurrencyDiff());
return BaishunResponse.success(new BaishunChangeCurrencyResponse()
@ -254,7 +260,7 @@ public class GameBaishunServiceImpl implements GameBaishunService {
return baishunRuntimeConfigResolver.resolveByApp(appId, null);
}
private void updateRoomDailyTask(Long coins, Long userId) {
private void updateRoomDailyTask(Long coins, Long userId) {
RoomDailyTaskCode taskType = RoomDailyTaskCode.PERSONAL_GAME_CONSUME;
String redisKey = "room:daily:task:progress:" + taskType.name() + ":" + userId + ":" + ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
Long total = redisService.increment(redisKey, Math.abs(coins.intValue()));
@ -265,9 +271,28 @@ public class GameBaishunServiceImpl implements GameBaishunService {
.setTaskCode(taskType.name())
.setProgressValue(total.intValue())
);
}
private void sendBroadcast(BaishunChangeCurrencyRequest request, GameListConfig gameListConfig) {
}
private void reportTaskCenterGameEvents(String sysOrigin,
Long userId,
String provider,
String orderId,
Long consumeGold,
Map<String, Object> payload) {
taskCenterGoClient.reportGameConsumeGold(sysOrigin, userId, provider, orderId, consumeGold, payload);
}
private Map<String, Object> gameTaskPayload(String provider, String orderId, String gameId, String roundId, String roomId) {
Map<String, Object> payload = new HashMap<>();
payload.put("provider", provider);
payload.put("orderId", orderId);
payload.put("gameId", gameId);
payload.put("roundId", roundId);
payload.put("roomId", roomId);
return payload;
}
private void sendBroadcast(BaishunChangeCurrencyRequest request, GameListConfig gameListConfig) {
if (gameListConfig == null) {
return;
}

View File

@ -15,9 +15,10 @@ import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.dto.ReqSysOrigin;
import com.red.circle.framework.core.exception.ResponseException;
import com.red.circle.framework.core.security.UserCredential;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.common.task.TaskCenterGoClient;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskProgressUpdateCmd;
import com.red.circle.other.app.enums.violation.GameOriginEnum;
@ -93,9 +94,10 @@ public class HotGameServiceImpl implements HotGameService {
private final RankingActivityService rankingActivityService;
private final GameActivityService gameActivityService;
private final UserActivityRechargeService userActivityRechargeService;
private final GameVipLevelWeeklyService gameVipLevelWeeklyService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final GameVipLevelWeeklyService gameVipLevelWeeklyService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final TaskCenterGoClient taskCenterGoClient;
@Value("${red-circle.game-rank.gameid}")
private String gameId;
@ -339,9 +341,12 @@ public class HotGameServiceImpl implements HotGameService {
}
// 处理游戏消费人任务
else {
updateRoomDailyTask(param.getCoin(), userId);
}
else {
updateRoomDailyTask(param.getCoin(), userId);
reportTaskCenterGameEvents(sysOrigin, userId, "HOTGAME", param.getOrderId(),
Math.abs(param.getCoin()), gameTaskPayload("HOTGAME", param.getOrderId(),
param.getGameId()));
}
return new HotGameResponse<HotGameCoin>()
.setData(new HotGameCoin()
@ -363,7 +368,7 @@ public class HotGameServiceImpl implements HotGameService {
.setErrorCode(HotGameErrorEnum.SERVER_ERROR.getErrorCode());
}
private void updateRoomDailyTask(Long coins, Long userId) {
private void updateRoomDailyTask(Long coins, Long userId) {
RoomDailyTaskCode taskType = RoomDailyTaskCode.PERSONAL_GAME_CONSUME;
String redisKey = "room:daily:task:progress:" + taskType.name() + ":" + userId + ":" + ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
Long total = redisService.increment(redisKey, Math.abs(coins.intValue()));
@ -374,9 +379,26 @@ public class HotGameServiceImpl implements HotGameService {
.setTaskCode(taskType.name())
.setProgressValue(total.intValue())
);
}
private void incGameRankingTmpActivity(HotGameUserCoinUpdate request) {
}
private void reportTaskCenterGameEvents(String sysOrigin,
Long userId,
String provider,
String orderId,
Long consumeGold,
Map<String, Object> payload) {
taskCenterGoClient.reportGameConsumeGold(sysOrigin, userId, provider, orderId, consumeGold, payload);
}
private Map<String, Object> gameTaskPayload(String provider, String orderId, String gameId) {
Map<String, Object> payload = new HashMap<>();
payload.put("provider", provider);
payload.put("orderId", orderId);
payload.put("gameId", gameId);
return payload;
}
private void incGameRankingTmpActivity(HotGameUserCoinUpdate request) {
if (ZonedDateTimeAsiaRiyadhUtils.now().isAfter(getFinishTime())) {
return;
}

View File

@ -8,9 +8,10 @@ import com.red.circle.external.inner.model.cmd.message.BroadcastGroupMsgBodyCmd;
import com.red.circle.external.inner.model.enums.message.GroupMessageTypeEnum;
import com.red.circle.framework.core.dto.ReqSysOrigin;
import com.red.circle.framework.core.security.UserCredential;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.common.task.TaskCenterGoClient;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.party3rd.*;
import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskProgressUpdateCmd;
@ -73,9 +74,10 @@ public class YomiGameServiceImpl implements YomiGameService {
private final RankingActivityService rankingActivityService;
private final GameActivityService gameActivityService;
private final GameRankingGateway gameRankingGateway;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final RedisService redisService;
private final ActivityRechargeTicketService activityRechargeTicketService;
private final RoomDailyTaskProgressService roomDailyTaskProgressService;
private final RedisService redisService;
private final TaskCenterGoClient taskCenterGoClient;
@Override
public YomiTokenCO getToken(YomiGetTokenCmd cmd) {
@ -186,9 +188,12 @@ public class YomiGameServiceImpl implements YomiGameService {
// 累加用户获得的金币并发送抽奖券
// activityRechargeTicketService.accumulatedRechargeAndAddTicket(userId, Math.abs(changeValue.longValue()), MonthlyRechargeType.UNDEFINED);
} else {
updateRoomDailyTask(changeValue.longValue(), userId);
}
} else {
updateRoomDailyTask(changeValue.longValue(), userId);
reportTaskCenterGameEvents(sysOrigin, userId, "YOMI", cmd.getRecordId(),
Math.abs(changeValue.longValue()), gameTaskPayload("YOMI", cmd.getRecordId(),
cmd.getGameId(), cmd.getRoundId(), cmd.getRoomId()));
}
return new YomiBalanceCO(currentBalance);
@ -199,7 +204,7 @@ public class YomiGameServiceImpl implements YomiGameService {
}
}
private void updateRoomDailyTask(Long coins, Long userId) {
private void updateRoomDailyTask(Long coins, Long userId) {
RoomDailyTaskCode taskType = RoomDailyTaskCode.PERSONAL_GAME_CONSUME;
String redisKey = "room:daily:task:progress:" + taskType.name() + ":" + userId + ":" + ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
Long total = redisService.increment(redisKey, Math.abs(coins.intValue()));
@ -210,9 +215,28 @@ public class YomiGameServiceImpl implements YomiGameService {
.setTaskCode(taskType.name())
.setProgressValue(total.intValue())
);
}
private static boolean isConsume(YomiChangeBalanceCmd cmd) {
}
private void reportTaskCenterGameEvents(String sysOrigin,
Long userId,
String provider,
String orderId,
Long consumeGold,
Map<String, Object> payload) {
taskCenterGoClient.reportGameConsumeGold(sysOrigin, userId, provider, orderId, consumeGold, payload);
}
private Map<String, Object> gameTaskPayload(String provider, String orderId, String gameId, String roundId, String roomId) {
Map<String, Object> payload = new HashMap<>();
payload.put("provider", provider);
payload.put("orderId", orderId);
payload.put("gameId", gameId);
payload.put("roundId", roundId);
payload.put("roomId", roomId);
return payload;
}
private static boolean isConsume(YomiChangeBalanceCmd cmd) {
return "bet".equals(cmd.getChangeCause());
}
@ -339,4 +363,4 @@ public class YomiGameServiceImpl implements YomiGameService {
//游戏王日榜
gameActivityService.incKingGameDaily(userId, rewardAmount.longValue(), gameId);
}
}
}

View File

@ -23,6 +23,7 @@ import com.red.circle.other.app.command.game.burstcrystal.GameBurstCrystalSchedu
import com.red.circle.other.app.command.game.roompk.GameRoomPkUserCmdExe;
import com.red.circle.other.app.command.game.teampk.GameTeamPkBaseInfoCmdExe;
import com.red.circle.other.app.common.gift.GameLuckyGiftCommon;
import com.red.circle.other.app.common.gift.VoiceRoomRegionBroadcastGoClient;
import com.red.circle.other.app.dto.clientobject.gift.SendGiftNotifyCO;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
@ -45,6 +46,8 @@ import org.mockito.ArgumentCaptor;
class GiveGiftsListenerTest {
private final ImGroupClient imGroupClient = mock(ImGroupClient.class);
private final VoiceRoomRegionBroadcastGoClient voiceRoomRegionBroadcastGoClient = mock(
VoiceRoomRegionBroadcastGoClient.class);
private final RoomProfileManagerService roomProfileManagerService = mock(
RoomProfileManagerService.class);
private final GiveGiftsListener listener = new GiveGiftsListener(
@ -54,6 +57,7 @@ class GiveGiftsListenerTest {
mock(UserRegionGateway.class),
mock(MessageEventProcess.class),
mock(GameLuckyGiftCommon.class),
voiceRoomRegionBroadcastGoClient,
mock(TeamBillCycleService.class),
mock(TeamPolicyManagerService.class),
mock(EnumConfigCacheService.class),
@ -101,11 +105,35 @@ class GiveGiftsListenerTest {
assertEquals("NORMAL", data.getGiftType());
}
@Test
void sendNoticeGiftBroadcastShouldSendGlobalGiftToRegionBroadcastGo() {
when(voiceRoomRegionBroadcastGoClient.send(any())).thenReturn(true);
listener.sendNoticeGiftBroadcast(
event(GiftSpecialEnum.GLOBAL_GIFT.name(), "GOLD"),
runningWater()
);
ArgumentCaptor<VoiceRoomRegionBroadcastGoClient.RegionBroadcastRequest> captor =
ArgumentCaptor.forClass(VoiceRoomRegionBroadcastGoClient.RegionBroadcastRequest.class);
verify(voiceRoomRegionBroadcastGoClient).send(captor.capture());
verify(imGroupClient, never()).sendMessageBroadcast(any());
VoiceRoomRegionBroadcastGoClient.RegionBroadcastRequest request = captor.getValue();
assertEquals(SysOriginPlatformEnum.LIKEI.name(), request.getSysOrigin());
assertEquals(3001L, request.getSenderUserId());
assertEquals(GroupMessageTypeEnum.SEND_GIFT.name(), request.getType());
SendGiftNotifyCO data = (SendGiftNotifyCO) request.getData();
assertTrue(data.getGlobalNews());
assertEquals(5001L, data.getGiftId());
}
@Test
void sendNoticeGiftBroadcastShouldIgnoreNonNoticeGift() {
listener.sendNoticeGiftBroadcast(event("ANIMATION", "GOLD"), runningWater());
verify(imGroupClient, never()).sendMessageBroadcast(any());
verify(voiceRoomRegionBroadcastGoClient, never()).send(any());
}
@Test
@ -114,6 +142,7 @@ class GiveGiftsListenerTest {
runningWater());
verify(imGroupClient, never()).sendMessageBroadcast(any());
verify(voiceRoomRegionBroadcastGoClient, never()).send(any());
}
private GiveAwayGiftBatchEvent event(String special, String giftTab) {

View File

@ -1,9 +1,93 @@
SET NAMES utf8mb4;
ALTER TABLE `user_login_logger`
ADD COLUMN `ip_country_code` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '登录IP国家码' AFTER `ip`,
ADD COLUMN `ip_country_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '登录IP国家/地区名称' AFTER `ip_country_code`,
ADD COLUMN `ip_region` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '登录IP地区/省' AFTER `ip_country_name`,
ADD COLUMN `req_zone_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求时区' AFTER `ip_region`,
ADD COLUMN `login_blocked` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否被登录访问校验屏蔽' AFTER `req_zone_id`,
ADD COLUMN `block_reason` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '登录访问校验屏蔽原因' AFTER `login_blocked`;
SET @current_schema = DATABASE();
SET @ddl = IF(
EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @current_schema
AND TABLE_NAME = 'user_login_logger'
AND COLUMN_NAME = 'ip_country_code'
),
'SELECT 1',
'ALTER TABLE `user_login_logger` ADD COLUMN `ip_country_code` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''' COMMENT ''登录IP国家码'' AFTER `ip`'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl = IF(
EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @current_schema
AND TABLE_NAME = 'user_login_logger'
AND COLUMN_NAME = 'ip_country_name'
),
'SELECT 1',
'ALTER TABLE `user_login_logger` ADD COLUMN `ip_country_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''' COMMENT ''登录IP国家/地区名称'' AFTER `ip_country_code`'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl = IF(
EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @current_schema
AND TABLE_NAME = 'user_login_logger'
AND COLUMN_NAME = 'ip_region'
),
'SELECT 1',
'ALTER TABLE `user_login_logger` ADD COLUMN `ip_region` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''' COMMENT ''登录IP地区/省'' AFTER `ip_country_name`'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl = IF(
EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @current_schema
AND TABLE_NAME = 'user_login_logger'
AND COLUMN_NAME = 'req_zone_id'
),
'SELECT 1',
'ALTER TABLE `user_login_logger` ADD COLUMN `req_zone_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''' COMMENT ''请求时区'' AFTER `ip_region`'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl = IF(
EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @current_schema
AND TABLE_NAME = 'user_login_logger'
AND COLUMN_NAME = 'login_blocked'
),
'SELECT 1',
'ALTER TABLE `user_login_logger` ADD COLUMN `login_blocked` tinyint(1) NOT NULL DEFAULT 0 COMMENT ''是否被登录访问校验屏蔽'' AFTER `req_zone_id`'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @ddl = IF(
EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @current_schema
AND TABLE_NAME = 'user_login_logger'
AND COLUMN_NAME = 'block_reason'
),
'SELECT 1',
'ALTER TABLE `user_login_logger` ADD COLUMN `block_reason` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''' COMMENT ''登录访问校验屏蔽原因'' AFTER `login_blocked`'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@ -0,0 +1,117 @@
SET NAMES utf8mb4;
SET @payment_manager_menu_id := (
SELECT `id` FROM `sys_menu` WHERE `alias` = 'PaymentManager' LIMIT 1
);
SET @payment_manager_menu_id := IFNULL(@payment_manager_menu_id, 1700000600);
INSERT INTO `sys_menu` (
`id`, `parent_id`, `menu_name`, `path`, `menu_type`, `icon`, `create_user`, `update_user`,
`sort`, `status`, `router`, `alias`
)
SELECT
@payment_manager_menu_id, 0, '支付管理', '/payment/manager', 1, 'lucide:credit-card',
'0', '0', 193, 0, '/payment/manager', 'PaymentManager'
WHERE NOT EXISTS (
SELECT 1 FROM `sys_menu` WHERE `alias` = 'PaymentManager'
);
UPDATE `sys_menu`
SET
`parent_id` = 0,
`menu_name` = '支付管理',
`path` = '/payment/manager',
`menu_type` = 1,
`icon` = 'lucide:credit-card',
`create_user` = '0',
`update_user` = '0',
`sort` = 193,
`status` = 0,
`router` = '/payment/manager'
WHERE `alias` = 'PaymentManager';
UPDATE `sys_menu`
SET
`parent_id` = @payment_manager_menu_id,
`menu_name` = '订单列表',
`path` = 'operate/order-details',
`menu_type` = 2,
`icon` = 'form',
`sort` = 1,
`status` = 0,
`router` = 'payment/manager/order/list'
WHERE `alias` = 'OrderDetails';
UPDATE `sys_menu`
SET
`parent_id` = @payment_manager_menu_id,
`path` = 'operate/pay-country',
`menu_type` = 2,
`icon` = 'form',
`sort` = CASE `alias` WHEN 'PayCountry' THEN 2 ELSE 7 END,
`status` = 0,
`router` = 'payment/manager/country'
WHERE `alias` IN ('PayCountry', 'openPayCountry');
UPDATE `sys_menu`
SET
`parent_id` = @payment_manager_menu_id,
`path` = 'operate/region-relation',
`menu_type` = 2,
`icon` = 'form',
`sort` = 3,
`status` = 0,
`router` = 'payment/manager/region/relation'
WHERE `alias` = 'RegionRelation';
UPDATE `sys_menu`
SET
`parent_id` = @payment_manager_menu_id,
`path` = 'operate/pay-application',
`menu_type` = 2,
`icon` = 'form',
`sort` = 4,
`status` = 0,
`router` = 'payment/manager/application'
WHERE `alias` = 'PayApplication';
UPDATE `sys_menu`
SET
`parent_id` = @payment_manager_menu_id,
`path` = 'operate/pay-factory',
`menu_type` = 2,
`icon` = 'form',
`sort` = 5,
`status` = 0,
`router` = 'payment/manager/factory'
WHERE `alias` = 'PayFactory';
UPDATE `sys_menu`
SET
`parent_id` = @payment_manager_menu_id,
`path` = 'operate/pay-channel',
`menu_type` = 2,
`icon` = 'form',
`sort` = 6,
`status` = 0,
`router` = 'payment/manager/channel'
WHERE `alias` = 'PayChannel';
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`)
SELECT DISTINCT source.`role_id`, @payment_manager_menu_id
FROM `sys_role_menu` source
JOIN `sys_menu` child_menu ON child_menu.`id` = source.`menu_id`
WHERE child_menu.`alias` IN (
'OrderDetails',
'PayCountry',
'openPayCountry',
'RegionRelation',
'PayApplication',
'PayFactory',
'PayChannel'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_menu` target
WHERE target.`role_id` = source.`role_id`
AND target.`menu_id` = @payment_manager_menu_id
);