新增游戏上报接口
This commit is contained in:
parent
1cbc7d5d29
commit
e55f3b909a
@ -1,6 +1,8 @@
|
||||
package com.red.circle.other.adapter.app.game.party3rd;
|
||||
|
||||
import com.red.circle.component.game.baishun.GameBaishunService;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd;
|
||||
import com.red.circle.other.app.service.game.override.service.GameBaishunReportService;
|
||||
import com.red.circle.component.game.baishun.request.BaishunChangeCurrencyRequest;
|
||||
import com.red.circle.component.game.baishun.request.BaishunTokenRequest;
|
||||
import com.red.circle.component.game.baishun.request.BaishunTokenUpdateRequest;
|
||||
@ -32,6 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class GameBaishunRestController extends BaseController {
|
||||
|
||||
private final GameBaishunService gameBaishunService;
|
||||
private final GameBaishunReportService gameBaishunReportService;
|
||||
|
||||
/**
|
||||
* 获取 SSToken: BAISHUN 服务器端获取调⽤接⼝的⻓期令牌(ss_token.
|
||||
@ -69,4 +72,13 @@ public class GameBaishunRestController extends BaseController {
|
||||
return gameBaishunService.changeBalance(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 游戏状态上报(game_start / game_settle).
|
||||
*/
|
||||
@IgnoreResultResponse
|
||||
@PostMapping("/report")
|
||||
public BaishunResponse<Void> report(@RequestBody @Validated GameBaishunReportCmd cmd) {
|
||||
return gameBaishunReportService.report(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,165 @@
|
||||
package com.red.circle.other.app.command.game;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.red.circle.auth.inner.endpoint.AuthClient;
|
||||
import com.red.circle.component.game.baishun.error.BaishunErrorCode;
|
||||
import com.red.circle.component.game.baishun.props.GameBaishunProperties;
|
||||
import com.red.circle.component.game.baishun.request.BaishunUserProfileRequest;
|
||||
import com.red.circle.component.game.baishun.response.BaishunResponse;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.security.UserCredential;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd.GameSettleInfo;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd.GameStartInfo;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd.PlayerResultInfo;
|
||||
import com.red.circle.tool.core.parse.DataTypeUtils;
|
||||
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.List;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Baishun游戏状态上报处理.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GameBaishunReportCmdExe {
|
||||
|
||||
private static final String REPORT_TYPE_START = "game_start";
|
||||
private static final String REPORT_TYPE_SETTLE = "game_settle";
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
private final GameBaishunProperties gameBaishunProperties;
|
||||
private final WalletGoldClient walletGoldClient;
|
||||
private final AuthClient authClient;
|
||||
|
||||
public BaishunResponse<Void> execute(GameBaishunReportCmd cmd) {
|
||||
if (!checkTokenStrict(cmd)) {
|
||||
log.error("BaishunReportCmdExe execute checkTokenStrict fail !");
|
||||
}
|
||||
|
||||
|
||||
log.info("Baishun game report: type={}, userId={}", cmd.getReportType(), cmd.getUserId());
|
||||
log.error("Baishun game report: {}", JSONObject.toJSONString(cmd));
|
||||
|
||||
/*switch (cmd.getReportType()) {
|
||||
case REPORT_TYPE_START:
|
||||
return handleGameStart(cmd);
|
||||
case REPORT_TYPE_SETTLE:
|
||||
return handleGameSettle(cmd);
|
||||
default:
|
||||
log.warn("Unknown report_type: {}", cmd.getReportType());
|
||||
return BaishunResponse.fail(BaishunErrorCode.DATE_ERROR);
|
||||
}*/
|
||||
return BaishunResponse.success(null);
|
||||
}
|
||||
|
||||
private BaishunResponse<Void> handleGameStart(GameBaishunReportCmd cmd) {
|
||||
GameStartInfo startInfo = parseReportMsg(cmd.getReportMsg(), GameStartInfo.class);
|
||||
if (startInfo == null) {
|
||||
return BaishunResponse.fail(BaishunErrorCode.READ_DATE_ERROR);
|
||||
}
|
||||
|
||||
// 扣除开局 bet(非AI玩家)
|
||||
if (startInfo.getPlayers() != null) {
|
||||
for (GameBaishunReportCmd.PlayerStartInfo player : startInfo.getPlayers()) {
|
||||
if (Objects.equals(player.getIsAi(), 1) || player.getBet() == null || player.getBet() <= 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Long userId = DataTypeUtils.toLong(player.getUserId());
|
||||
walletGoldClient.changeBalance(GoldReceiptCmd.builder()
|
||||
.appExpenditure()
|
||||
.userId(userId)
|
||||
.sysOrigin(resolveTokenSysOrigin(cmd.getSsToken()))
|
||||
.origin(GoldOrigin.BAISHUN_GAME.name())
|
||||
.originDescribe(GoldOrigin.BAISHUN_GAME.getDesc())
|
||||
.eventId(startInfo.getGameRoundId() + "_" + userId + "_start")
|
||||
.amount(BigDecimal.valueOf(player.getBet()))
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
log.error("Baishun game start deduct failed: userId={}, roundId={}", player.getUserId(), startInfo.getGameRoundId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BaishunResponse.success(null);
|
||||
}
|
||||
|
||||
private BaishunResponse<Void> handleGameSettle(GameBaishunReportCmd cmd) {
|
||||
GameSettleInfo settleInfo = parseReportMsg(cmd.getReportMsg(), GameSettleInfo.class);
|
||||
if (settleInfo == null) {
|
||||
return BaishunResponse.fail(BaishunErrorCode.READ_DATE_ERROR);
|
||||
}
|
||||
|
||||
List<PlayerResultInfo> players = settleInfo.getPlayers();
|
||||
if (players == null || players.isEmpty()) {
|
||||
return BaishunResponse.success(null);
|
||||
}
|
||||
|
||||
for (PlayerResultInfo player : players) {
|
||||
if (Objects.equals(player.getIsAi(), 1) || player.getReward() == null || player.getReward() <= 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Long userId = DataTypeUtils.toLong(player.getUserId());
|
||||
walletGoldClient.changeBalance(GoldReceiptCmd.builder()
|
||||
.appIncome()
|
||||
.userId(userId)
|
||||
.sysOrigin(resolveTokenSysOrigin(cmd.getSsToken()))
|
||||
.origin(GoldOrigin.BAISHUN_GAME.name())
|
||||
.originDescribe(GoldOrigin.BAISHUN_GAME.getDesc())
|
||||
.eventId(settleInfo.getGameRoundId() + "_" + userId + "_settle")
|
||||
.amount(BigDecimal.valueOf(player.getReward()))
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
log.error("Baishun game settle reward failed: userId={}, roundId={}", player.getUserId(), settleInfo.getGameRoundId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return BaishunResponse.success(null);
|
||||
}
|
||||
|
||||
private <T> T parseReportMsg(Object reportMsg, Class<T> clazz) {
|
||||
try {
|
||||
return objectMapper.convertValue(reportMsg, clazz);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to parse report_msg to {}: {}", clazz.getSimpleName(), reportMsg, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveTokenSysOrigin(String ssToken) {
|
||||
try {
|
||||
return com.red.circle.framework.core.security.UserCredential.parseToken(ssToken).getSysOrigin();
|
||||
} catch (Exception e) {
|
||||
return "LIKEI";
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkTokenStrict(GameBaishunReportCmd request) {
|
||||
UserCredential accessToken = ResponseAssert.requiredSuccess(
|
||||
authClient.getUserCredential(DataTypeUtils.toLong(request.getUserId())));
|
||||
|
||||
if (Objects.isNull(accessToken)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(accessToken.getUserId(), DataTypeUtils.toLong(request.getUserId()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(accessToken.token(), request.getSsToken());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.red.circle.other.app.service.game;
|
||||
|
||||
import com.red.circle.component.game.baishun.response.BaishunResponse;
|
||||
import com.red.circle.other.app.command.game.GameBaishunReportCmdExe;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd;
|
||||
import com.red.circle.other.app.service.game.override.service.GameBaishunReportService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author tf
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GameBaishunReportServiceImpl implements GameBaishunReportService {
|
||||
|
||||
private final GameBaishunReportCmdExe gameBaishunReportCmdExe;
|
||||
|
||||
@Override
|
||||
public BaishunResponse<Void> report(GameBaishunReportCmd cmd) {
|
||||
return gameBaishunReportCmdExe.execute(cmd);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.red.circle.other.app.service.game.override.service;
|
||||
|
||||
import com.red.circle.other.app.dto.cmd.game.GameBaishunReportCmd;
|
||||
import com.red.circle.component.game.baishun.response.BaishunResponse;
|
||||
|
||||
/**
|
||||
* Baishun游戏状态上报服务.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
public interface GameBaishunReportService {
|
||||
|
||||
BaishunResponse<Void> report(GameBaishunReportCmd cmd);
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
package com.red.circle.other.app.dto.cmd.game;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Baishun游戏状态上报.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Data
|
||||
public class GameBaishunReportCmd {
|
||||
|
||||
/** 上报类型: game_start / game_settle */
|
||||
@NotBlank
|
||||
@JsonProperty("report_type")
|
||||
private String reportType;
|
||||
|
||||
/** 上报数据体(对应 game_start_info 或 game_settle_info) */
|
||||
@NotNull
|
||||
@JsonProperty("report_msg")
|
||||
private Object reportMsg;
|
||||
|
||||
/** 用户ID */
|
||||
@NotBlank
|
||||
@JsonProperty("user_id")
|
||||
private String userId;
|
||||
|
||||
/** 用户ss_token */
|
||||
@NotBlank
|
||||
@JsonProperty("ss_token")
|
||||
private String ssToken;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 内嵌数据结构
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** 游戏开始上报数据 */
|
||||
@Data
|
||||
public static class GameStartInfo {
|
||||
|
||||
@JsonProperty("game_id")
|
||||
private Integer gameId;
|
||||
|
||||
@JsonProperty("room_id")
|
||||
private String roomId;
|
||||
|
||||
@JsonProperty("game_round_id")
|
||||
private String gameRoundId;
|
||||
|
||||
/** 开始时间戳(毫秒) */
|
||||
@JsonProperty("start_at")
|
||||
private Long startAt;
|
||||
|
||||
private List<PlayerStartInfo> players;
|
||||
|
||||
/** 货币类型,app定义,非必填 */
|
||||
@JsonProperty("currency_type")
|
||||
private Integer currencyType;
|
||||
}
|
||||
|
||||
/** 游戏结算上报数据 */
|
||||
@Data
|
||||
public static class GameSettleInfo {
|
||||
|
||||
@JsonProperty("game_id")
|
||||
private Integer gameId;
|
||||
|
||||
@JsonProperty("room_id")
|
||||
private String roomId;
|
||||
|
||||
@JsonProperty("game_round_id")
|
||||
private String gameRoundId;
|
||||
|
||||
/** 开始时间戳(毫秒) */
|
||||
@JsonProperty("start_at")
|
||||
private Long startAt;
|
||||
|
||||
/** 结束时间戳(毫秒) */
|
||||
@JsonProperty("end_at")
|
||||
private Long endAt;
|
||||
|
||||
private List<PlayerResultInfo> players;
|
||||
|
||||
/** 货币类型,app定义,非必填 */
|
||||
@JsonProperty("currency_type")
|
||||
private Integer currencyType;
|
||||
}
|
||||
|
||||
/** 开局玩家信息 */
|
||||
@Data
|
||||
public static class PlayerStartInfo {
|
||||
|
||||
@JsonProperty("user_id")
|
||||
private String userId;
|
||||
|
||||
/** 0: 玩家, 1: 机器人 */
|
||||
@JsonProperty("is_ai")
|
||||
private Integer isAi;
|
||||
|
||||
/** 扣除数量 */
|
||||
private Integer bet;
|
||||
}
|
||||
|
||||
/** 结算玩家信息 */
|
||||
@Data
|
||||
public static class PlayerResultInfo {
|
||||
|
||||
@JsonProperty("user_id")
|
||||
private String userId;
|
||||
|
||||
/** 0: 玩家, 1: 机器人 */
|
||||
@JsonProperty("is_ai")
|
||||
private Integer isAi;
|
||||
|
||||
private Integer rank;
|
||||
|
||||
private Integer reward;
|
||||
|
||||
private Integer score;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user