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 a41b811..2b86c23 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
@@ -197,6 +197,13 @@ public class Constants {
* xk 接口请求前缀
*/
public static final String XK_API_BASE_URL = "xk.api.base.url";
+
+
+ /**
+ * sa-api基本url
+ */
+ public static final String SA_API_BASE_URL = "sa.api.base.url";
+
/**
* 服务
*/
diff --git a/ff-base/src/main/java/com/ff/base/utils/DESEncryptUtils.java b/ff-base/src/main/java/com/ff/base/utils/DESEncryptUtils.java
new file mode 100644
index 0000000..a359ebb
--- /dev/null
+++ b/ff-base/src/main/java/com/ff/base/utils/DESEncryptUtils.java
@@ -0,0 +1,48 @@
+package com.ff.base.utils;
+
+import com.ff.base.exception.base.BaseException;
+import lombok.Data;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+
+/**
+ * 解密有用
+ *
+ * @author shi
+ * @date 2025/03/24
+ */
+public class DESEncryptUtils {
+
+ /**
+ * 给…解密
+ *
+ * @param inString 字符串中
+ * @param secretKey 密钥
+ * @return {@link String }
+ * @throws Exception 例外
+ */
+ public static String DESEncrypt(String inString, String secretKey) {
+ try {
+ // 使用相同的密钥进行加密
+ SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.US_ASCII), "DES");
+
+ // 使用DES加密算法
+ Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+
+ // 加密输入字符串
+ byte[] encrypted = cipher.doFinal(inString.getBytes(StandardCharsets.UTF_8));
+
+ // 返回Base64编码的密文
+ return Base64.getEncoder().encodeToString(encrypted);
+ } catch (Exception e) {
+ throw new BaseException("加密失败");
+ }
+
+ }
+
+}
diff --git a/ff-game/pom.xml b/ff-game/pom.xml
index ee0cfce..5d435ed 100644
--- a/ff-game/pom.xml
+++ b/ff-game/pom.xml
@@ -23,6 +23,11 @@
spring-boot-devtools
true
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+
org.springframework
diff --git a/ff-game/src/main/java/com/ff/game/api/sa/address/MySAAddressSource.java b/ff-game/src/main/java/com/ff/game/api/sa/address/MySAAddressSource.java
new file mode 100644
index 0000000..5ee8a89
--- /dev/null
+++ b/ff-game/src/main/java/com/ff/game/api/sa/address/MySAAddressSource.java
@@ -0,0 +1,31 @@
+package com.ff.game.api.sa.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 MySAAddressSource implements AddressSource {
+
+ @Resource
+ private ISysConfigService configService;
+
+
+ @Override
+ public ForestAddress getAddress(ForestRequest request) {
+ String apiBaseUrl = configService.selectConfigByKey(Constants.SA_API_BASE_URL);
+ return new ForestAddress("https",apiBaseUrl, 443,"api");
+ }
+}
\ No newline at end of file
diff --git a/ff-game/src/main/java/com/ff/game/api/sa/client/SAClient.java b/ff-game/src/main/java/com/ff/game/api/sa/client/SAClient.java
new file mode 100644
index 0000000..a652356
--- /dev/null
+++ b/ff-game/src/main/java/com/ff/game/api/sa/client/SAClient.java
@@ -0,0 +1,96 @@
+package com.ff.game.api.sa.client;
+
+import com.dtflys.forest.annotation.*;
+import com.ff.game.api.jili.dto.*;
+import com.ff.game.api.sa.address.MySAAddressSource;
+import com.ff.game.api.sa.dto.SARegUserInfoResponse;
+import com.ff.game.api.xk.dto.*;
+
+import java.util.Map;
+
+/**
+ * xk 请求
+ *
+ * @author shi
+ * @date 2025/02/10
+ */
+@Address(source = MySAAddressSource.class)
+public interface SAClient {
+ /**
+ * 创建成员
+ *
+ * @param parameters 参数
+ * @return {@link String }
+ */
+ @Post( url ="/api.aspx/RegUserInfo?${parameters}",
+ headers = {
+ "Content-type: application/x-www-form-urlencoded"
+ })
+ SARegUserInfoResponse createMember(@Var("parameters") String parameters);
+
+ /**
+ * 获取会员信息
+ *
+ * @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/sa/dto/SARegUserInfoResponse.java b/ff-game/src/main/java/com/ff/game/api/sa/dto/SARegUserInfoResponse.java
new file mode 100644
index 0000000..1356d5a
--- /dev/null
+++ b/ff-game/src/main/java/com/ff/game/api/sa/dto/SARegUserInfoResponse.java
@@ -0,0 +1,46 @@
+package com.ff.game.api.sa.dto;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+
+/**
+ *
+ * sa 创建用户返回类
+ * @author shi
+ * @date 2025/03/25
+ */
+@XmlRootElement(name = "RegUserInfoResponse")
+public class SARegUserInfoResponse {
+
+ private String errorMsgId;
+ private String errorMsg;
+ private String username;
+
+ @XmlElement(name = "ErrorMsgId")
+ public String getErrorMsgId() {
+ return errorMsgId;
+ }
+
+ public void setErrorMsgId(String errorMsgId) {
+ this.errorMsgId = errorMsgId;
+ }
+
+ @XmlElement(name = "ErrorMsg")
+ public String getErrorMsg() {
+ return errorMsg;
+ }
+
+ public void setErrorMsg(String errorMsg) {
+ this.errorMsg = errorMsg;
+ }
+
+ @XmlElement(name = "Username")
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
\ No newline at end of file
diff --git a/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java
new file mode 100644
index 0000000..d337f90
--- /dev/null
+++ b/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java
@@ -0,0 +1,607 @@
+package com.ff.game.api.sa.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.DESEncryptUtils;
+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.request.*;
+import com.ff.game.api.sa.client.SAClient;
+import com.ff.game.api.sa.dto.SARegUserInfoResponse;
+import com.ff.game.api.xk.dto.*;
+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;
+
+
+/**
+ * SA 游戏 impl
+ *
+ * @author shi
+ * @date 2024/11/12
+ */
+@Service("SAService")
+@Slf4j
+public class GamesSAServiceImpl 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 SAClient SAClient;
+
+
+ @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 String }
+ */
+ private String getKey(GamesBaseRequestDTO gamesBaseRequestDTO,String method) {
+ String dateTimeNow = DateUtils.dateTimeNow();
+ String query="method="+method+"&Key="+gamesBaseRequestDTO.getAgentKey()+"&Time="+dateTimeNow+"&"+gamesBaseRequestDTO.getQuery();
+ String q = DESEncryptUtils.DESEncrypt(query, "g9G16nTs");
+ String s=Md5Utils.md5New(query+gamesBaseRequestDTO.getAgentId()+dateTimeNow+gamesBaseRequestDTO.getAgentKey());
+ return "q="+q+"&s="+s;
+ }
+
+
+
+ /**
+ * 创建成员
+ *
+ * @param createMemberRequestDTO 创建成员请求dto
+ * @return {@link Boolean }
+ */
+ @Override
+ public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) {
+ log.info("GamesXKServiceImpl [createMember] 请求参数 {}", createMemberRequestDTO);
+
+ Map params = new LinkedHashMap<>();
+ params.put("Username", createMemberRequestDTO.getAccount());
+ params.put("CurrencyType", createMemberRequestDTO.getCurrency());
+ String query = JsonUtil.mapToQueryString(params);
+ createMemberRequestDTO.setQuery(query);
+ String key = this.getKey(createMemberRequestDTO,"RegUserInfo");
+ SARegUserInfoResponse saRegUserInfoResponse = SAClient.createMember(key);
+ String errorCode = saRegUserInfoResponse.getErrorMsgId();
+ //判断是否获取成功
+ return Boolean.FALSE;
+ }
+
+
+ /**
+ * 获取会员信息
+ *
+ * @param memberInfoRequestDTO 会员信息请求dto
+ * @return {@link MemberInfoResponseDTO }
+ */
+ @Override
+ public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO) {
+ log.info("GamesXKServiceImpl [getMemberInfo] 请求参数 {}", memberInfoRequestDTO);
+ Map params = new LinkedHashMap<>();
+ params.put("accounts", memberInfoRequestDTO.getAccounts());
+ params.put("agentId", memberInfoRequestDTO.getAgentId());
+ String query = JsonUtil.mapToQueryString(params);
+ memberInfoRequestDTO.setQuery(query);
+ String key = this.getKey(memberInfoRequestDTO,null);
+ params.put("key", key);
+ XKMemberInfoDTO xkMemberInfoDTO = SAClient.getMemberInfo(params);
+ //判断是否获取成功
+ if (this.getIsSuccess(xkMemberInfoDTO.getCode())) {
+ List memberInfoResponseDTOS = new ArrayList<>();
+ xkMemberInfoDTO.getData().forEach(e -> {
+ memberInfoResponseDTOS.add(MemberInfoResponseDTO.builder()
+ .status(e.getStatus())
+ .balance(e.getBalance())
+ .account(e.getAccount())
+ .build());
+ });
+ return memberInfoResponseDTOS.get(0);
+ } else {
+ throw new BaseException(xkMemberInfoDTO.getMsg());
+ }
+ }
+
+ /**
+ * 无重定向登录
+ *
+ * @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);
+ String key = this.getKey(gamesLogin,null);
+ params.put("key", key);
+ params.put("disableFullScreen", gamesLogin.getDisableFullScreen());
+ params.put("homeUrl", gamesLogin.getHomeUrl());
+ params.put("platform", gamesLogin.getPlatform());
+ XKLoginWithoutRedirectResponseDTO xkLoginWithoutRedirectResponseDTO = SAClient.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);
+ String key = this.getKey(gamesBaseRequestDTO,null);
+ params.put("key", key);
+
+ XKGamesDTO xkGamesDTO = SAClient.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(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().toString());
+ params.put("transferType", exchangeTransferMoneyRequestDTO.getTransferType());
+ params.put("agentId", exchangeTransferMoneyRequestDTO.getAgentId());
+ String query = JsonUtil.mapToQueryString(params);
+ exchangeTransferMoneyRequestDTO.setQuery(query);
+ String key = this.getKey(exchangeTransferMoneyRequestDTO,null);
+ params.put("key", key);
+ XKExchangeMoneyResponseDTO exchangeMoneyResponse = SAClient.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);
+ String key = this.getKey(betRecordByTimeDTO,null);
+ params.put("key", key);
+ XKBetRecordResponseDTO xkBetRecordResponseDTO = SAClient.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,null);
+ params.put("key", key);
+ xkBetRecordResponseDTO = SAClient.getBetRecordByTime(params);
+ this.batchInsert(xkBetRecordResponseDTO);
+ }
+
+
+ return Boolean.TRUE;
+ } else {
+ log.error("GamesXKServiceImpl [getBetRecordByTime] 获取投注记录失败,错误代码{},错误信息{}", xkBetRecordResponseDTO.getCode(), xkBetRecordResponseDTO.getMsg());
+ throw new BaseException(xkBetRecordResponseDTO.getMsg());
+ }
+
+ }
+
+ /**
+ * 赠送免费局数
+ *
+ * @param createFreeSpinRequest 创建自由旋转请求
+ * @return {@link Boolean }
+ */
+ @Override
+ public Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest) {
+ throw new BaseException("当前平台不支持");
+ }
+
+ /**
+ * 获取游戏详细信息
+ *
+ * @param getGameDetailRequestDTO 获取游戏详细信息请求dto
+ * @return {@link GetGameDetailResponseDTO }
+ */
+ @Override
+ public GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO) {
+ throw new BaseException("当前平台不支持");
+ }
+
+ /**
+ * 强制会员从游戏注销
+ *
+ * @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);
+ String key = this.getKey(kickMemberRequestDTO,null);
+ params.put("key", key);
+ XKKickMemberDTO xkKickMemberDTO = SAClient.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 BaseException("当前平台不支持");
+ }
+
+ /**
+ * 免费游戏玩家使用的纪录
+ *
+ * @param getFreeSpinDashflowRequestDTO 获取自由旋转dashflow请求dto
+ * @return {@link List }<{@link GameFreeRecord }>
+ */
+ @Override
+ public List getFreeSpinDashflow(GetFreeSpinDashflowRequestDTO getFreeSpinDashflowRequestDTO) {
+ throw new BaseException("当前平台不支持");
+ }
+
+ /**
+ * 取消赠送免费局数
+ *
+ * @param cancelFreeSpinRequestDTO 取消免费旋转请求
+ * @return {@link Boolean }
+ */
+ @Override
+ public Boolean cancelFreeSpin(CancelFreeSpinRequestDTO cancelFreeSpinRequestDTO) {
+ throw new BaseException("当前平台不支持");
+ }
+
+
+ /**
+ * 批量插入
+ *
+ * @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(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(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;
+ }
+}