From 8732f3e85f24dbe04dfaf0b34938aeffddc81b25 Mon Sep 17 00:00:00 2001 From: shi Date: Fri, 28 Mar 2025 19:23:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor(game):=20=E4=BC=98=E5=8C=96=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 GamesPPServiceImpl 中,将 JSONUtils.toJSONString(params) 替换为直接使用 params - 在 PPClient 中,修改 getGameList 方法参数类型从 String 改为 Map --- .../java/com/ff/base/constant/Constants.java | 5 +- .../api/ae/address/MyAEAddressSource.java | 31 + .../com/ff/game/api/ae/client/AEClient.java | 97 +++ .../com/ff/game/api/ae/dto/AEResponse.java | 26 + .../api/ae/dto/XKBetRecordResponseDTO.java | 54 ++ .../api/ae/dto/XKCreateMemberResponseDTO.java | 32 + .../ae/dto/XKExchangeMoneyResponseDTO.java | 46 ++ .../game/api/ae/dto/XKKickMemberAllDTO.java | 27 + .../ff/game/api/ae/dto/XKKickMemberDTO.java | 13 + .../XKLoginWithoutRedirectResponseDTO.java | 29 + .../ff/game/api/ae/dto/XKMemberInfoDTO.java | 49 ++ .../game/api/ae/impl/GamesAEServiceImpl.java | 594 ++++++++++++++++++ 12 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/address/MyAEAddressSource.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/client/AEClient.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/AEResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKBetRecordResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKCreateMemberResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKExchangeMoneyResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberAllDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKLoginWithoutRedirectResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/dto/XKMemberInfoDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java diff --git a/ff-base/src/main/java/com/ff/base/constant/Constants.java b/ff-base/src/main/java/com/ff/base/constant/Constants.java index cfb844f..50e62d9 100644 --- a/ff-base/src/main/java/com/ff/base/constant/Constants.java +++ b/ff-base/src/main/java/com/ff/base/constant/Constants.java @@ -213,7 +213,10 @@ public class Constants { */ public static final String DG_API_BASE_URL = "dg.api.base.url"; - + /** + * ae api基本url + */ + public static final String AE_API_BASE_URL = "ae.api.base.url"; /** * sa-api基本url */ diff --git a/ff-game/src/main/java/com/ff/game/api/ae/address/MyAEAddressSource.java b/ff-game/src/main/java/com/ff/game/api/ae/address/MyAEAddressSource.java new file mode 100644 index 0000000..21eba22 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/address/MyAEAddressSource.java @@ -0,0 +1,31 @@ +package com.ff.game.api.ae.address; + +import com.dtflys.forest.callback.AddressSource; +import com.dtflys.forest.http.ForestAddress; +import com.dtflys.forest.http.ForestRequest; +import com.ff.base.constant.Constants; +import com.ff.base.system.service.ISysConfigService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + + +/** + * 我jili address来源 + * + * @author shi + * @date 2025/02/10 + */ +@Component +public class MyAEAddressSource implements AddressSource { + + @Resource + private ISysConfigService configService; + + + @Override + public ForestAddress getAddress(ForestRequest request) { + String apiBaseUrl = configService.selectConfigByKey(Constants.AE_API_BASE_URL); + return new ForestAddress("https",apiBaseUrl, 443,""); + } +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/ae/client/AEClient.java b/ff-game/src/main/java/com/ff/game/api/ae/client/AEClient.java new file mode 100644 index 0000000..4427faf --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/client/AEClient.java @@ -0,0 +1,97 @@ +package com.ff.game.api.ae.client; + +import com.dtflys.forest.annotation.*; +import com.ff.game.api.ae.address.MyAEAddressSource; +import com.ff.game.api.ae.dto.*; +import com.ff.game.api.ae.impl.GamesAEServiceImpl; +import com.ff.game.api.jili.dto.*; +import com.ff.game.api.xk.dto.XKGamesDTO; + +import java.util.Map; + +/** + * xk 请求 + * + * @author shi + * @date 2025/02/10 + */ +@Address(source = MyAEAddressSource.class) +public interface AEClient { + /** + * 创建成员 + * + * @param params 参数 + * @return {@link String } + */ + @Post(url ="/wallet/createMember", + headers = { + "Content-type: application/x-www-form-urlencoded" + }) + AEResponse createMember(@Body Map params); + + /** + * 获取会员信息 + * + * @param params 参数 + * @return {@link XKMemberInfoDTO } + */ + @Post("/getMemberInfo") + XKMemberInfoDTO getMemberInfo(@JSONBody Map params); + + /** + * 无重定向登录 + * + * @param params 参数 + * @return {@link JILILoginWithoutRedirectResponseDTO } + */ + @Post("/loginWithoutRedirect") + XKLoginWithoutRedirectResponseDTO loginWithoutRedirect(@JSONBody Map params); + + /** + * 获取游戏列表 + * + * @param params 参数 + * @return {@link JILIGamesDTO } + */ + @Post("/getGameList") + XKGamesDTO getGameList(@JSONBody Map params); + + /** + * 按代理id进行交换转账 + * + * @param params 参数 + * @return {@link JILIExchangeMoneyResponseDTO } + */ + @Post(url = "/exchangeTransferByAgentId") + XKExchangeMoneyResponseDTO exchangeTransferByAgentId(@JSONBody Map params); + + /** + * 按时间获取投注记录 + * + * @param params 参数 + * @return {@link XKBetRecordResponseDTO } + */ + @Post(url = "/getGameRecordByTime") + XKBetRecordResponseDTO getBetRecordByTime(@JSONBody Map params); + + + /** + * 踢出队员 + * + * @param params 参数 + * @return {@link JILIKickMemberDTO } + */ + @Post("/kickMember") + XKKickMemberDTO kickMember(@JSONBody Map params); + + /** + * 踢出所有队员 + * + * @param params 参数 + * @return {@link JILIKickMemberAllDTO } + */ + @Get("/kickMemberAll") + XKKickMemberAllDTO kickMemberAll(@JSONBody Map params); + + +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/AEResponse.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/AEResponse.java new file mode 100644 index 0000000..499a484 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/AEResponse.java @@ -0,0 +1,26 @@ +package com.ff.game.api.ae.dto; + +import lombok.Data; + +/** + * 航空响应 + * + * @author shi + * @date 2025/03/28 + */ +@Data +public class AEResponse { + /** + * 状态码 (String类型) + * 0000 - 成功 + * 其他 - 错误状态码 + */ + private String status; + + /** + * 描述信息 (String类型) + * "Success" - 请求成功 + * 其他 - 错误信息 + */ + private String desc; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKBetRecordResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKBetRecordResponseDTO.java new file mode 100644 index 0000000..a4c3540 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKBetRecordResponseDTO.java @@ -0,0 +1,54 @@ +package com.ff.game.api.ae.dto; + +import io.jsonwebtoken.lang.Collections; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +@NoArgsConstructor +@Data +public class XKBetRecordResponseDTO { + + private Integer code; + private String msg; + private DataBean data; + + @NoArgsConstructor + @Data + public static class DataBean { + private Integer currentPage; + private Integer totalPages; + private Integer pageLimit; + private Integer totalNumber; + private List result; + + public List getResult() { + if (Collections.isEmpty(result)) { + return new ArrayList<>(); + } + return result; + } + + @NoArgsConstructor + @Data + public static class ResultBean { + private String account; + private Long wagersId; + private String gameId; + private Long wagersTime; + private BigDecimal betAmount; + private Long payoffTime; + private BigDecimal payoffAmount; + private Integer status; + private Long settlementTime; + private Integer gameCategoryId; + private Integer type; + private String agentId; + private BigDecimal turnover; + private Long roundIndex; + } + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKCreateMemberResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKCreateMemberResponseDTO.java new file mode 100644 index 0000000..01578a0 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKCreateMemberResponseDTO.java @@ -0,0 +1,32 @@ +package com.ff.game.api.ae.dto; + + +import com.ff.game.api.request.GamesBaseRequestDTO; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * 创建成员响应dto + * + * @author shi + * @date 2024/10/22 + */ +@NoArgsConstructor +@Data +public class XKCreateMemberResponseDTO extends GamesBaseRequestDTO { + + + /** + * 代码 + */ + private int code; + /** + * 数据 + */ + private String data; + /** + * msg + */ + private String msg; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKExchangeMoneyResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKExchangeMoneyResponseDTO.java new file mode 100644 index 0000000..be8a729 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKExchangeMoneyResponseDTO.java @@ -0,0 +1,46 @@ +package com.ff.game.api.ae.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@NoArgsConstructor +@Data +public class XKExchangeMoneyResponseDTO { + + private int code; + private String msg; + private DataBean data; + + @NoArgsConstructor + @Data + public static class DataBean { + /** + * 交易序号,额度转移纪录唯一值, 长度上限 50 + */ + private String transactionId; + /** + * 转账前金额(游戏币) + */ + private BigDecimal coinBefore; + /** + * 转账后金额(游戏币) + */ + private BigDecimal coinAfter; + /** + * 转账前金额(指定货币) + */ + private BigDecimal currencyBefore; + /** + * 转账后金额(指定货币) + */ + private BigDecimal currencyAfter; + /** + * 状态: + * 1: 成功 + * 2: 失败 + */ + private Integer status; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberAllDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberAllDTO.java new file mode 100644 index 0000000..ea17acc --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberAllDTO.java @@ -0,0 +1,27 @@ +package com.ff.game.api.ae.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * xkkick会员全部dto + * + * @author shi + * @date 2024/11/13 + */ +@Data +@NoArgsConstructor +public class XKKickMemberAllDTO { + /** + * 代码 + */ + private int code; + /** + * 数据 + */ + private String data; + /** + * msg + */ + private String msg; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberDTO.java new file mode 100644 index 0000000..ac5ea42 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKKickMemberDTO.java @@ -0,0 +1,13 @@ +package com.ff.game.api.ae.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Data +public class XKKickMemberDTO { + + private int code; + private String msg; + private Object data; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKLoginWithoutRedirectResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKLoginWithoutRedirectResponseDTO.java new file mode 100644 index 0000000..e622416 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKLoginWithoutRedirectResponseDTO.java @@ -0,0 +1,29 @@ +package com.ff.game.api.ae.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 登录时不重定向响应dto + * + * @author shi + * @date 2024/10/22 + */ +@NoArgsConstructor +@Data +public class XKLoginWithoutRedirectResponseDTO { + + + /** + * 代码 + */ + private int code; + /** + * 数据 + */ + private String data; + /** + * msg + */ + private String msg; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/dto/XKMemberInfoDTO.java b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKMemberInfoDTO.java new file mode 100644 index 0000000..ae6a3bb --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/dto/XKMemberInfoDTO.java @@ -0,0 +1,49 @@ +package com.ff.game.api.ae.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 会员信息dto + * + * @author shi + * @date 2024/10/30 + */ +@NoArgsConstructor +@Data +public class XKMemberInfoDTO { + + + /** + * 代码 + */ + private Integer code; + /** + * msg + */ + private String msg; + /** + * 数据 + */ + private List data; + + @NoArgsConstructor + @Data + public static class DataBean { + /** + * 账户 + */ + private String account; + /** + * 平衡 + */ + private BigDecimal balance; + /** + * 地位 + */ + private Integer status; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java new file mode 100644 index 0000000..0bd6601 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java @@ -0,0 +1,594 @@ +package com.ff.game.api.ae.impl; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.NumberUtil; +import com.ff.base.constant.CacheConstants; +import com.ff.base.constant.Constants; +import com.ff.base.core.redis.RedisCache; +import com.ff.base.enums.*; +import com.ff.base.exception.base.ApiException; +import com.ff.base.exception.base.BaseException; +import com.ff.base.system.service.ISysConfigService; +import com.ff.base.utils.DateUtils; +import com.ff.base.utils.JsonUtil; +import com.ff.base.utils.sign.Md5Utils; +import com.ff.base.utils.uuid.IdUtils; +import com.ff.config.KeyConfig; +import com.ff.game.api.IGamesService; +import com.ff.game.api.ae.client.AEClient; +import com.ff.game.api.ae.dto.*; +import com.ff.game.api.request.*; +import com.ff.game.api.xk.dto.XKGamesDTO; +import com.ff.game.domain.*; +import com.ff.game.dto.GameSecretKeyCurrencyDTO; +import com.ff.game.service.*; +import com.ff.member.domain.Member; +import com.ff.member.service.IMemberService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + + +/** + * AE 游戏 impl + * + * @author shi + * @date 2024/11/12 + */ +@Service("AEService") +@Slf4j +public class GamesAEServiceImpl implements IGamesService { + + + @Resource + private ISysConfigService configService; + + @Resource + private RedisCache redisCache; + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + + @Resource + private IGamePlatformService gamePlatformService; + + + @Resource + private IGameService gameService; + + + @Resource + private IMemberService memberService; + + @Resource + private IGameFreeRecordService gameFreeRecordService; + @Resource + private IGameSecretKeyService gameSecretKeyService; + + @Resource + private IGameSecretKeyCurrencyService gameSecretKeyCurrencyService; + + @Resource + private AEClient AEClient; + + + @Resource + private KeyConfig keyConfig; + + @Resource + private IGameBettingDetailsService gameBettingDetailsService; + + @Resource + private IGameNameService gameNameService; + + + /** + * 获得就是成功 + * + * @param errorCode 错误代码 + * @return {@link Boolean } + */ + private Boolean getIsSuccess(Integer errorCode) { + return 0 == errorCode; + } + + + /** + * 获取密钥 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link Map }<{@link String }, {@link Object }> + */ + private Map getKey(GamesBaseRequestDTO gamesBaseRequestDTO ) { + Map params = new LinkedHashMap<>(); + params.put("cert",gamesBaseRequestDTO.getAgentKey()); + params.put("agentId",gamesBaseRequestDTO.getAgentId()); + return params; + } + + /** + * 创建成员 + * + * @param createMemberRequestDTO 创建成员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) { + log.info("GamesAEServiceImpl [createMember] 请求参数 {}", createMemberRequestDTO); + + Map params = this.getKey(createMemberRequestDTO); + params.put("userId", createMemberRequestDTO.getAccount()); + params.put("currency", createMemberRequestDTO.getCurrency()); + params.put("betLimit", "{}"); + AEResponse aeResponse = AEClient.createMember(params); + String errorCode = aeResponse.getStatus(); + if (this.getIsSuccess(Integer.valueOf(errorCode))) { + return Boolean.TRUE; + } + //判断是否获取成功 + return Boolean.FALSE; + } + + + /** + * 获取会员信息 + * + * @param memberInfoRequestDTO 会员信息请求dto + * @return {@link MemberInfoResponseDTO } + */ + @Override + public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO) { + log.info("GamesXKServiceImpl [getMemberInfo] 请求参数 {}", memberInfoRequestDTO); + return null; + } + + /** + * 无重定向登录 + * + * @param gamesLogin 游戏登录 + * @return {@link String } + */ + @Override + public String loginWithoutRedirect(GamesLogin gamesLogin) { + log.info("GamesXKServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin); + + Map params = new LinkedHashMap<>(); + params.put("account", gamesLogin.getAccount()); + params.put("gameId", Integer.valueOf(gamesLogin.getGameId())); + params.put("lang", gamesLogin.getLang()); + params.put("agentId", gamesLogin.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + gamesLogin.setQuery(query); + Map key = this.getKey(gamesLogin); + params.put("key", key); + params.put("disableFullScreen", gamesLogin.getDisableFullScreen()); + params.put("homeUrl", gamesLogin.getHomeUrl()); + params.put("platform", gamesLogin.getPlatform()); + XKLoginWithoutRedirectResponseDTO xkLoginWithoutRedirectResponseDTO = AEClient.loginWithoutRedirect(params); + //判断是否获取成功 + if (this.getIsSuccess(xkLoginWithoutRedirectResponseDTO.getCode())) { + return xkLoginWithoutRedirectResponseDTO.getData(); + } else { + throw new BaseException(xkLoginWithoutRedirectResponseDTO.getMsg()); + } + } + + + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + @Transactional + @Override + public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) { + + List gamesDatas = redisCache.getCacheList(CacheConstants.XK_GAMES); + if (!CollectionUtils.isEmpty(gamesDatas)) { + return CacheConstants.XK_GAMES; + } + + + Map params = new LinkedHashMap<>(); + params.put("agentId", gamesBaseRequestDTO.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + gamesBaseRequestDTO.setQuery(query); + Map key = this.getKey(gamesBaseRequestDTO); + params.put("key", key); + + XKGamesDTO xkGamesDTO = AEClient.getGameList(params); + //判断是否获取成功 + if (this.getIsSuccess(xkGamesDTO.getCode())) { + + for (XKGamesDTO.DataBean gamesDataDTO : xkGamesDTO.getData()) { + GamePlatform gamePlatform = GamePlatform.builder() + .platformType(XKGameType.findSystemByCode(gamesDataDTO.getGameCategoryId())) + .platformCode(GamePlatforms.XK.getCode()) + .build(); + List gamePlatforms = gamePlatformService.selectGamePlatformList(gamePlatform); + //没有此平台就新增一个平台 + if (CollectionUtils.isEmpty(gamePlatforms)) { + gamePlatform.setPlatformName(GamePlatforms.XK.getInfo() + XKGameType.findInfoByCode(gamesDataDTO.getGameCategoryId())); + gamePlatform.setSortNo(gamePlatformService.selectMaxSortNo() + 1); + gamePlatform.setCreateBy(Constants.SYSTEM); + gamePlatformService.insertGamePlatform(gamePlatform); + } else { + gamePlatform = gamePlatforms.get(0); + } + Game game = Game.builder() + .platformId(gamePlatform.getId()) + .gameCode(String.valueOf(gamesDataDTO.getGameId())) + .build(); + List games = gameService.selectGameList(game); + //不存在这个游戏 + if (CollectionUtils.isEmpty(games)) { + game.setGameSourceType(String.valueOf(gamesDataDTO.getGameCategoryId())); + game.setFreespin(gamesDataDTO.isFreeSpin()); + game.setSortNo(gameService.selectMaxSortNoByPlatformId(gamePlatform.getId()) + 1); + game.setGameName(gamesDataDTO.getName()); + game.setCreateBy(Constants.SYSTEM); + gameService.insertGame(game); + } else { + game = games.get(0); + } + gamesDataDTO.setSystemGameId(game.getId()); + List gameNames = gameNameService.selectGameNameList(GameName.builder().gameId(game.getId()).gameName(game.getGameName()).build()); + if (CollectionUtils.isEmpty(gameNames)){ + gameNameService.insertGameName(GameName.builder() + .gameId(game.getId()) + .gameName(game.getGameName()) + .langCode("zh-CN") + .createBy(Constants.SYSTEM) + .build()); + } + + } + + redisCache.deleteObject(CacheConstants.XK_GAMES); + redisCache.setCacheList(CacheConstants.XK_GAMES, xkGamesDTO.getData()); + redisCache.expire(CacheConstants.XK_GAMES, 5L, TimeUnit.HOURS); + } else { + throw new BaseException(xkGamesDTO.getMsg()); + + } + + return CacheConstants.XK_GAMES; + } + + /** + * 按代理id进行交换转账 + * + * @param exchangeTransferMoneyRequestDTO 外汇转账moeny dto + * @return {@link Long } + */ + @Override + @Transactional + public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { + log.info("GamesXKServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); + GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() + .platformCode(GamePlatforms.XK.getInfo()) + .code(exchangeTransferMoneyRequestDTO.getAgentId()) + .build()); + + Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); + String transactionId = GamePlatforms.XK.getCode() + IdUtils.simpleUUID(); + List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) + .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) + .build() + ); + Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + + //获取下一个自增id + GameExchangeMoney exchangeMoney = GameExchangeMoney + .builder() + .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) + .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) + .quota(exchangeTransferMoneyRequestDTO.getQuota()) + .balance(exchangeTransferMoneyRequestDTO.getAmount()) + .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) + .currencyCode(currencyDTO.getSystemCurrency()) + .memberId(member.getId()) + .transactionId(transactionId) + .platformCode(GamePlatforms.XK.getCode()) + .build(); + exchangeMoney.setCreateBy(Constants.SYSTEM); + //接口限制限制50字符 + exchangeMoney.setTransactionId(GamePlatforms.XK.getCode() + IdUtils.simpleUUID()); + Map params = new LinkedHashMap<>(); + params.put("account", exchangeTransferMoneyRequestDTO.getAccount()); + params.put("transactionId", exchangeMoney.getTransactionId()); + params.put("amount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toPlainString()); + params.put("transferType", exchangeTransferMoneyRequestDTO.getTransferType()); + params.put("agentId", exchangeTransferMoneyRequestDTO.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + exchangeTransferMoneyRequestDTO.setQuery(query); + Map key = this.getKey(exchangeTransferMoneyRequestDTO); + params.put("key", key); + XKExchangeMoneyResponseDTO exchangeMoneyResponse = AEClient.exchangeTransferByAgentId(params); + //判断是否转移成功 + if (this.getIsSuccess(exchangeMoneyResponse.getCode())) { + XKExchangeMoneyResponseDTO.DataBean exchangeMoneyResponseData = exchangeMoneyResponse.getData(); + ApiException.isTrue(!StatusType.FAILURE.getValue().equals(exchangeMoneyResponseData.getStatus()), ErrorCode.BALANCE_TRANSFER_FAILED.getCode()); + + //更新数据 + exchangeMoney.setBalance(NumberUtil.sub(exchangeMoneyResponseData.getCurrencyAfter(), exchangeMoneyResponseData.getCurrencyBefore()).abs()); + exchangeMoney.setCoinBefore(exchangeMoneyResponseData.getCoinBefore()); + exchangeMoney.setCoinAfter(exchangeMoneyResponseData.getCoinAfter()); + exchangeMoney.setCurrencyBefore(exchangeMoneyResponseData.getCurrencyBefore()); + exchangeMoney.setCurrencyAfter(exchangeMoneyResponseData.getCurrencyAfter()); + exchangeMoney.setStatus(exchangeMoneyResponseData.getStatus()); + gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + } else { + log.error("GamesXKServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{},错误信息{}", exchangeMoneyResponse.getCode(), exchangeMoneyResponse.getMsg()); + throw new BaseException(exchangeMoneyResponse.getMsg()); + } + + return exchangeMoney.getId(); + } + + /** + * 汇兑转移状态 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { + return Boolean.TRUE; + } + + + /** + * 按时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link List }<{@link GameBettingDetails }> + */ + @Override + public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) { + List gameBettingDetails = new ArrayList<>(); + //请求参数 + log.info("GamesXKServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO); + Map params = new LinkedHashMap<>(); + params.put("startTime", betRecordByTimeDTO.getStartTime()); + params.put("endTime", betRecordByTimeDTO.getEndTime()); + params.put("page", betRecordByTimeDTO.getPage()); + params.put("pageLimit", betRecordByTimeDTO.getPageLimit()); + params.put("agentId", betRecordByTimeDTO.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + betRecordByTimeDTO.setQuery(query); + Map key = this.getKey(betRecordByTimeDTO); + params.put("key", key); + XKBetRecordResponseDTO xkBetRecordResponseDTO = AEClient.getBetRecordByTime(params); + + //判断是否获取成功 + if (this.getIsSuccess(xkBetRecordResponseDTO.getCode())) { + //数据组装 + XKBetRecordResponseDTO.DataBean dataBean = xkBetRecordResponseDTO.getData(); + this.batchInsert(xkBetRecordResponseDTO); + + //获取下一页数据 + while (!Objects.equals(dataBean.getCurrentPage(), dataBean.getTotalPages()) && dataBean.getTotalPages() > 0) { + betRecordByTimeDTO.setPage(dataBean.getCurrentPage() + 1); + //请求参数 + params = new LinkedHashMap<>(); + params.put("startTime", betRecordByTimeDTO.getStartTime()); + params.put("endTime", betRecordByTimeDTO.getEndTime()); + params.put("page", betRecordByTimeDTO.getPage()); + params.put("pageLimit", betRecordByTimeDTO.getPageLimit()); + params.put("agentId", betRecordByTimeDTO.getAgentId()); + query = JsonUtil.mapToQueryString(params); + betRecordByTimeDTO.setQuery(query); + key = this.getKey(betRecordByTimeDTO); + params.put("key", key); + xkBetRecordResponseDTO = AEClient.getBetRecordByTime(params); + this.batchInsert(xkBetRecordResponseDTO); + } + + + return Boolean.TRUE; + } else { + log.error("GamesXKServiceImpl [getBetRecordByTime] 获取投注记录失败,错误代码{},错误信息{}", xkBetRecordResponseDTO.getCode(), xkBetRecordResponseDTO.getMsg()); + throw new BaseException(xkBetRecordResponseDTO.getMsg()); + } + + } + + /** + * 按历史时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO betRecordByTimeDTO) { + return null; + } + + /** + * 赠送免费局数 + * + * @param createFreeSpinRequest 创建自由旋转请求 + * @return {@link Boolean } + */ + @Override + public Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 获取游戏详细信息 + * + * @param getGameDetailRequestDTO 获取游戏详细信息请求dto + * @return {@link GetGameDetailResponseDTO } + */ + @Override + public GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 强制会员从游戏注销 + * + * @param kickMemberRequestDTO 踢会员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean kickMember(KickMemberRequestDTO kickMemberRequestDTO) { + log.info("GamesXKServiceImpl [kickMember] 请求参数 {}", kickMemberRequestDTO); + Map params = new LinkedHashMap<>(); + params.put("account", kickMemberRequestDTO.getAccount()); + params.put("agentId", kickMemberRequestDTO.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + kickMemberRequestDTO.setQuery(query); + Map key = this.getKey(kickMemberRequestDTO); + params.put("key", key); + XKKickMemberDTO xkKickMemberDTO = AEClient.kickMember(params); + //判断是否获取成功 + if (this.getIsSuccess(xkKickMemberDTO.getCode())) { + return Boolean.TRUE; + } else { + throw new BaseException(xkKickMemberDTO.getMsg()); + } + } + + /** + * 踢成员全部 + * + * @param kickMemberAllDTO 踢成员全部dto + * @return {@link Boolean } + */ + @Override + public Boolean kickMemberAll(KickMemberAllDTO kickMemberAllDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 免费游戏玩家使用的纪录 + * + * @param getFreeSpinDashflowRequestDTO 获取自由旋转dashflow请求dto + * @return {@link List }<{@link GameFreeRecord }> + */ + @Override + public List getFreeSpinDashflow(GetFreeSpinDashflowRequestDTO getFreeSpinDashflowRequestDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 取消赠送免费局数 + * + * @param cancelFreeSpinRequestDTO 取消免费旋转请求 + * @return {@link Boolean } + */ + @Override + public Boolean cancelFreeSpin(CancelFreeSpinRequestDTO cancelFreeSpinRequestDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + + /** + * 批量插入 + * + * @param xkBetRecordResponseDTO xk下注记录响应dto + */ + private void batchInsert(XKBetRecordResponseDTO xkBetRecordResponseDTO) { + List gameBettingDetails = new ArrayList<>(); + List wagersIds = new ArrayList<>(); + //数据组装 + XKBetRecordResponseDTO.DataBean dataBean = xkBetRecordResponseDTO.getData(); + //数据转化 + for (XKBetRecordResponseDTO.DataBean.ResultBean bean : dataBean.getResult()) { + GameBettingDetails bettingDetails = this.dataBuild(GamesDataBuildDTO.builder().data(bean).build()); + if (!ObjectUtils.isEmpty(bettingDetails)) { + bettingDetails.setId(IdUtil.getSnowflakeNextId()); + gameBettingDetails.add(bettingDetails); + } + wagersIds.add(String.valueOf(bean.getWagersId())); + } + if (!CollectionUtils.isEmpty(gameBettingDetails)) { + //查询重复数据id + List removeWagersIds = gameBettingDetailsService.selectGameBettingDetailsByWagersId(wagersIds); + //用steam流清除list中与wagersIds集合相同的数据 + gameBettingDetails = gameBettingDetails.stream() + .filter(detail -> !removeWagersIds.contains(detail.getWagersId())) + .collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(gameBettingDetails)) { + gameBettingDetailsService.batchInsert(gameBettingDetails); + } + } + + } + + /** + * 数据构建 + * + * @param gamesDataBuildDTO 数据 + * @return {@link GameBettingDetails } + */ + @Override + public GameBettingDetails dataBuild(GamesDataBuildDTO gamesDataBuildDTO) { + //转化类 + XKBetRecordResponseDTO.DataBean.ResultBean resultBean = (XKBetRecordResponseDTO.DataBean.ResultBean) gamesDataBuildDTO.getData(); + + GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() + .platformCode(GamePlatforms.XK.getInfo()) + .code(resultBean.getAgentId()) + .build()); + + Member member = memberService.selectMemberByGameAccount(resultBean.getAccount()); + if (ObjectUtils.isEmpty(member)) { + return null; + } + List gamesDatas = redisCache.getCacheList(CacheConstants.XK_GAMES); + Map dataDTOMap = gamesDatas.stream().collect(Collectors.toMap(XKGamesDTO.DataBean::getGameId, e -> e)); + XKGamesDTO.DataBean gamesDataDTO = dataDTOMap.get(resultBean.getGameId()); + BigDecimal payoffAmount = BigDecimal.ZERO; + + if (GameStatus.WIN.getCode().equals(resultBean.getStatus())) { + payoffAmount = NumberUtil.sub(resultBean.getPayoffAmount(), resultBean.getTurnover()); + } else if (GameStatus.FAIL.getCode().equals(resultBean.getStatus())) { + payoffAmount = NumberUtil.sub(resultBean.getPayoffAmount(), resultBean.getTurnover()).negate(); + } + //数据构造 + GameBettingDetails gameBettingDetails = GameBettingDetails.builder() + .tenantKey(member.getTenantKey()) + //保存我们的币种id + .currencyCode(currencyDTO.getSystemCurrency()) + .memberId(member.getId()) + .gameCode(resultBean.getGameId()) + .gameType(XKGameType.findSystemByCode(resultBean.getGameCategoryId())) + .platformCode(GamePlatforms.XK.getCode()) + .gameId(gamesDataDTO.getSystemGameId()) + .gameName(gamesDataDTO.getName()) + .gameStatus(resultBean.getStatus()) + .gameStatusType(resultBean.getType()) + .gameCurrencyCode(resultBean.getAgentId()) + .account(String.valueOf(resultBean.getAccount())) + .wagersId(String.valueOf(resultBean.getWagersId())) + .wagersTime(resultBean.getWagersTime()) + .betAmount(resultBean.getBetAmount().abs()) + .payoffTime(resultBean.getPayoffTime()) + .payoffAmount(payoffAmount) + .settlementTime(resultBean.getSettlementTime()) + .turnover(resultBean.getTurnover()) + .orderNo(String.valueOf(resultBean.getRoundIndex())) + .settlementStatus(SettlementStatusEnum.COMPLETED.getCode()) + .build(); + gameBettingDetails.setCreateBy(Constants.SYSTEM); + gameBettingDetails.setCreateTime(DateUtils.getNowDate()); + return gameBettingDetails; + } +}