From 41a9e3dee4793e07dd87121c680a91866e2b6460 Mon Sep 17 00:00:00 2001 From: shi Date: Thu, 27 Mar 2025 11:07:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(game):=20=E6=B7=BB=E5=8A=A0=20DG=20?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E5=B9=B3=E5=8F=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 DG游戏平台的 API 接口和实现类 - 添加 DG游戏的登录、转账、获取游戏列表等功能 - 实现 DG 游戏的注单记录获取和处理 - 在数据库中添加 DG 游戏平台的相关配置 --- .../com/ff/base/constant/CacheConstants.java | 5 +- .../java/com/ff/base/constant/Constants.java | 6 + .../java/com/ff/base/enums/GamePlatforms.java | 1 + .../api/dg/address/MyDGAddressSource.java | 31 + .../com/ff/game/api/dg/client/DGClient.java | 105 ++++ .../api/dg/dto/DGBetRecordResponseDTO.java | 129 ++++ .../dto/DGLoginWithoutRedirectResponse.java | 74 +++ .../com/ff/game/api/dg/dto/DGResponse.java | 26 + .../api/dg/dto/DGTransactionResponseDTO.java | 45 ++ .../api/dg/dto/DGUserAccountResponse.java | 40 ++ .../dg/service/impl/GamesDGServiceImpl.java | 569 ++++++++++++++++++ .../game/api/sa/impl/GamesSAServiceImpl.java | 3 +- .../ff/game/domain/GameBettingDetails.java | 2 + .../ff/game/domain/GameSecretKeyCurrency.java | 4 + ff-game/src/main/resources/logback.xml | 2 +- .../game/GameSecretKeyCurrencyMapper.xml | 12 +- 16 files changed, 1048 insertions(+), 6 deletions(-) create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/address/MyDGAddressSource.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/client/DGClient.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/dto/DGBetRecordResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/dto/DGLoginWithoutRedirectResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/dto/DGResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/dto/DGTransactionResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/dto/DGUserAccountResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java diff --git a/ff-base/src/main/java/com/ff/base/constant/CacheConstants.java b/ff-base/src/main/java/com/ff/base/constant/CacheConstants.java index 1a2895d..0dbb96e 100644 --- a/ff-base/src/main/java/com/ff/base/constant/CacheConstants.java +++ b/ff-base/src/main/java/com/ff/base/constant/CacheConstants.java @@ -69,7 +69,10 @@ public class CacheConstants public static final String SA_GAMES= "sa_games:"; - + /** + * dg游戏 + */ + public static final String DG_GAMES= "dg_games:"; /** * pg游戏投注货币 */ 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 9018b0a..4f76fe7 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 @@ -204,6 +204,12 @@ public class Constants { public static final String XK_API_BASE_URL = "xk.api.base.url"; + /** + * dg-api基本url + */ + public static final String DG_API_BASE_URL = "dg.api.base.url"; + + /** * sa-api基本url */ diff --git a/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java b/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java index 1343a79..ddb0e04 100644 --- a/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java +++ b/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java @@ -9,6 +9,7 @@ public enum GamePlatforms { PG("PG", "PG"), FC("FC", "FC"), SA("SA", "SA"), + DG("DG", "DG"), ; private final String code; diff --git a/ff-game/src/main/java/com/ff/game/api/dg/address/MyDGAddressSource.java b/ff-game/src/main/java/com/ff/game/api/dg/address/MyDGAddressSource.java new file mode 100644 index 0000000..9bf5985 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/address/MyDGAddressSource.java @@ -0,0 +1,31 @@ +package com.ff.game.api.dg.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 MyDGAddressSource implements AddressSource { + + @Resource + private ISysConfigService configService; + + + @Override + public ForestAddress getAddress(ForestRequest request) { + String apiBaseUrl = configService.selectConfigByKey(Constants.DG_API_BASE_URL); + return new ForestAddress("http",apiBaseUrl, 80,""); + } +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/dg/client/DGClient.java b/ff-game/src/main/java/com/ff/game/api/dg/client/DGClient.java new file mode 100644 index 0000000..c1e84b2 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/client/DGClient.java @@ -0,0 +1,105 @@ +package com.ff.game.api.dg.client; + +import com.dtflys.forest.annotation.*; +import com.ff.game.api.dg.address.MyDGAddressSource; +import com.ff.game.api.dg.dto.*; +import com.ff.game.api.jili.dto.*; +import com.ff.game.api.xk.address.MyXKAddressSource; +import com.ff.game.api.xk.dto.*; + +import java.util.Map; + +/** + * dg 请求 + * + * @author shi + * @date 2025/02/10 + */ +@Address(source = MyDGAddressSource.class) +public interface DGClient { + /** + * 创建成员 + * + * @param params 参数 + * @param header 头球 + * @return {@link DGResponse } + */ + @Post("/v2/api/signup") + DGResponse createMember(@JSONBody Map params, @Header Map header); + + /** + * 获取会员信息 + * + * @param params 参数 + */ + @Post("/v2/api/balance") + DGUserAccountResponse getMemberInfo(@JSONBody Map params, @Header Map header); + + /** + * 无重定向登录 + * + * @param params 参数 + * @param header 头球 + * @return {@link DGLoginWithoutRedirectResponse } + */ + @Post("/v2/api/login") + DGLoginWithoutRedirectResponse loginWithoutRedirect(@JSONBody Map params, @Header Map header); + + /** + * 获取游戏列表 + * + * @param params 参数 + * @return {@link JILIGamesDTO } + */ + @Post("/getGameList") + XKGamesDTO getGameList(@JSONBody Map params); + + /** + * 按代理id进行交换转账 + * + * @param params 参数 + * @return {@link DGTransactionResponseDTO } + */ + @Post(url = "/v2/api/transfer") + DGTransactionResponseDTO exchangeTransferByAgentId(@JSONBody Map params, @Header Map header); + + /** + * 按时间获取投注记录 + * + * @param params 参数 + * @return {@link XKBetRecordResponseDTO } + */ + @Post(url ="/v2/api/report", + headers = { + "Content-type: application/x-www-form-urlencoded" + }) + DGBetRecordResponseDTO getBetRecordByTime(@Header Map params); + + /** + * 标记报告 + * + * @param params 参数 + * @return {@link DGResponse } + */ + @Post(url = "/v2/api/markReport") + DGResponse markReport(@JSONBody Map params, @Header Map header); + /** + * 踢出队员 + * + * @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/dg/dto/DGBetRecordResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGBetRecordResponseDTO.java new file mode 100644 index 0000000..4b7e534 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGBetRecordResponseDTO.java @@ -0,0 +1,129 @@ +package com.ff.game.api.dg.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * dgbet记录响应数据 + * + * @author shi + * @date 2025/03/27 + */ +@Data +public class DGBetRecordResponseDTO { + + /** 错误码 (参考文档定义) */ + @JsonProperty("codeId") + private Integer codeId; + + /** 错误信息 */ + @JsonProperty("msg") + private String msg; + + /** 注单报告 */ + @JsonProperty("report") + private List report; + + /** + * 注单报告类 + */ + @Data + public static class ReportDTO { + + /** 注单ID(唯一) */ + @JsonProperty("id") + private Long id; + + /** 游戏桌号(红包小费记录没有) */ + @JsonProperty("tableId") + private Integer tableId; + + /** 游戏靴号(红包小费记录没有) */ + @JsonProperty("shoeId") + private Long shoeId; + + /** 当靴局号(红包小费记录没有) */ + @JsonProperty("playId") + private Long playId; + + /** 游戏厅号(1:旗舰厅;2:亚洲厅;3,4:现场厅;5:性感厅;8,9:区块链厅) */ + @JsonProperty("lobbyId") + private Integer lobbyId; + + /** 注单类型(1:注单,2:红包小费) */ + @JsonProperty("gameType") + private Integer gameType; + + /** 游戏类型(百家乐,龙虎等) */ + @JsonProperty("gameId") + private Integer gameId; + + /** 下注时间 */ + @JsonProperty("betTime") + private Date betTime; + + /** 结算时间 */ + @JsonProperty("calTime") + private Date calTime; + + /** 派彩金额(含本金) */ + @JsonProperty("winOrLoss") + private BigDecimal winOrLoss; + + /** 下注前余额(仅作参考) */ + @JsonProperty("balanceBefore") + private BigDecimal balanceBefore; + + /** 下注金额(下注扣款金额) */ + @JsonProperty("betPoints") + private BigDecimal betPoints; + + /** 洗码金额(用于计算佣金) */ + @JsonProperty("availableBet") + private BigDecimal availableBet; + + /** 会员账号 */ + @JsonProperty("userName") + private String userName; + + /** 游戏结果 */ + @JsonProperty("result") + private String result; + + /** 注单详情 */ + @JsonProperty("betDetail") + private String betDetail; + + /** 客户端IP */ + @JsonProperty("ip") + private String ip; + + /** 游戏唯一局号 */ + @JsonProperty("ext") + private String ext; + + /** 结算状态(0:未结算,1:已结算,2:已撤销,3:冻结) */ + @JsonProperty("isRevocation") + private Integer isRevocation; + + /** 更改单时对应的注单记录 */ + @JsonProperty("parentBetId") + private Long parentBetId; + + /** 币种ID(请参考对应关系说明) */ + @JsonProperty("currencyId") + private Integer currencyId; + + /** 客户端平台ID(1: PC 2: 安卓 3: 苹果 5: H5) */ + @JsonProperty("deviceType") + private Integer deviceType; + + /** 钱包扣款记录(转账模式API没有) */ + @JsonProperty("transfers") + private String transfers; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/dg/dto/DGLoginWithoutRedirectResponse.java b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGLoginWithoutRedirectResponse.java new file mode 100644 index 0000000..6b71ace --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGLoginWithoutRedirectResponse.java @@ -0,0 +1,74 @@ +package com.ff.game.api.dg.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +/** + * 响应结果类 + */ +@Data +public class DGLoginWithoutRedirectResponse { + + /** + * 响应的代码ID + */ + @JsonProperty("codeId") + private int codeId; + + /** + * 响应的消息 + */ + @JsonProperty("msg") + private String msg; + + /** + * 响应的 token + */ + @JsonProperty("token") + private String token; + + /** + * 响应的域名信息 + */ + @JsonProperty("domains") + private String domains; + + /** + * 列表数据 + */ + @JsonProperty("list") + private List list; + + /** + * 限制组 + */ + @JsonProperty("limitGroup") + private String limitGroup; + + /** + * 限制区间 + */ + @JsonProperty("limits") + private List limits; + + /** + * 限制区间内部类 + */ + @Data + public static class Limit { + + /** + * 最小值 + */ + @JsonProperty("min") + private int min; + + /** + * 最大值 + */ + @JsonProperty("max") + private int max; + } +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/dg/dto/DGResponse.java b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGResponse.java new file mode 100644 index 0000000..814e55d --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGResponse.java @@ -0,0 +1,26 @@ +package com.ff.game.api.dg.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 响应类,用于返回基本的状态信息。 + * + * @author shi + * @date 2025/03/26 + */ +@Data +public class DGResponse { + + /** + * 响应的代码ID。 + */ + @JsonProperty("codeId") + private int codeId; + + /** + * 响应的消息。 + */ + @JsonProperty("msg") + private String msg; +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/dg/dto/DGTransactionResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGTransactionResponseDTO.java new file mode 100644 index 0000000..7e57f80 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGTransactionResponseDTO.java @@ -0,0 +1,45 @@ +package com.ff.game.api.dg.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 交易信息返回实体 + * + * @author shi + * @date 2025/03/27 + */ +@Data +public class DGTransactionResponseDTO { + + + /** 响应代码 */ + @JsonProperty("codeId") + private Integer codeId; + + /** 响应消息 */ + @JsonProperty("msg") + private String msg; + + /** 用户名 */ + @JsonProperty("username") + private String username; + + /** 交易金额 */ + @JsonProperty("amount") + private BigDecimal amount; + + /** 账户余额 */ + @JsonProperty("balance") + private BigDecimal balance; + + /** 交易流水号 */ + @JsonProperty("serial") + private String serial; + + /** 交易时间 */ + @JsonProperty("time") + private String time; +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/dg/dto/DGUserAccountResponse.java b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGUserAccountResponse.java new file mode 100644 index 0000000..576beb2 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/dto/DGUserAccountResponse.java @@ -0,0 +1,40 @@ +package com.ff.game.api.dg.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 用户账户信息响应类 + * + * @author shi + * @date 2025/03/26 + */ +@Data +public class DGUserAccountResponse { + + /** + * 响应的代码ID。 + */ + @JsonProperty("codeId") + private int codeId; + + /** + * 响应的消息。 + */ + @JsonProperty("msg") + private String msg; + + /** + * 用户名。 + */ + @JsonProperty("username") + private String username; + + /** + * 用户余额。 + */ + @JsonProperty("balance") + private BigDecimal balance; +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java new file mode 100644 index 0000000..890a633 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java @@ -0,0 +1,569 @@ +package com.ff.game.api.dg.service.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.SleepUtil; +import com.ff.base.utils.StringUtils; +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.dg.client.DGClient; +import com.ff.game.api.dg.dto.*; +import com.ff.game.api.ng.dto.ApiLoginResponseDTO; +import com.ff.game.api.ng.dto.ApiMemberInfoResponseDTO; +import com.ff.game.api.ng.dto.ApiNGResponseDTO; +import com.ff.game.api.request.*; +import com.ff.game.api.xk.client.XKClient; +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; + + +/** + * DG 游戏 impl + * + * @author shi + * @date 2024/11/12 + */ +@Service("DGService") +@Slf4j +public class GamesDGServiceImpl 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 DGClient DGClient; + + + @Resource + private KeyConfig keyConfig; + + @Resource + private IGameBettingDetailsService gameBettingDetailsService; + + @Resource + private IGameNameService gameNameService; + + + /** + * 游戏id + */ + private static final Long GAME_ID = 1904452832756003817L; + + /** + * 平台ID + */ + private static final Long PLATFORM_ID = 1904411420157108325L; + + /** + * 游戏名称id + */ + private static final Long GAME_NAME_ID = 1904452832756002317L; + + /** + * 获得就是成功 + * + * @param errorCode 错误代码 + * @return {@link Boolean } + */ + private Boolean getIsSuccess(Integer errorCode) { + ApiException.isTrue(103 != errorCode, ErrorCode.GAME_ACCOUNT_CREATION_FAILED.getCode()); + return 0 == errorCode; + } + + + /** + * 获取密钥 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + private Map getKey(GamesBaseRequestDTO gamesBaseRequestDTO) { + Long time = DateUtils.getNowDate(); + //取出对应的key跟密钥跟请求参数 + String agentKey = gamesBaseRequestDTO.getAgentKey(); + String agentId = gamesBaseRequestDTO.getAgentId(); + + String sign = Md5Utils.md5New(agentId + agentKey + time); + Map keyMap = new HashMap<>(); + keyMap.put("agent", agentId); + keyMap.put("sign", sign); + keyMap.put("time", time); + return keyMap; + } + + /** + * 创建成员 + * + * @param createMemberRequestDTO 创建成员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) { + log.info("GamesDGServiceImpl [createMember] 请求参数 {}", createMemberRequestDTO); + + Map params = new LinkedHashMap<>(); + params.put("username", createMemberRequestDTO.getAccount()); + params.put("currencyName", createMemberRequestDTO.getCurrency()); + params.put("winLimit", 0); + params.put("password", Md5Utils.md5New(createMemberRequestDTO.getAccount())); + + Map headerMap = this.getKey(createMemberRequestDTO); + DGResponse response = DGClient.createMember(params, headerMap); + if (this.getIsSuccess(response.getCodeId())) { + return Boolean.TRUE; + } + //判断是否获取成功 + return Boolean.FALSE; + } + + + /** + * 获取会员信息 + * + * @param memberInfoRequestDTO 会员信息请求dto + * @return {@link MemberInfoResponseDTO } + */ + @Override + public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO) { + log.info("GamesDGServiceImpl [getMemberInfo] 请求参数 {}", memberInfoRequestDTO); + Map paramsMap = new HashMap<>(); + paramsMap.put("username", memberInfoRequestDTO.getAccounts()); + Map headerMap = this.getKey(memberInfoRequestDTO); + DGUserAccountResponse memberInfo = DGClient.getMemberInfo(paramsMap, headerMap); + int errorCode = memberInfo.getCodeId(); + if (this.getIsSuccess(errorCode)) { + return MemberInfoResponseDTO.builder().account(memberInfoRequestDTO.getAccounts()).balance(memberInfo.getBalance()).status(GameMemberStatus.UNKNOWN.getCode()).build(); + } else { + throw new ApiException(ErrorCode.ACCOUNT_NOT_EXIST.getCode()); + } + } + + /** + * 无重定向登录 + * + * @param gamesLogin 游戏登录 + * @return {@link String } + */ + @Override + public String loginWithoutRedirect(GamesLogin gamesLogin) { + log.info("GamesDGServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin); + Map paramsMap = new HashMap<>(); + paramsMap.put("username", gamesLogin.getAccount()); + paramsMap.put("currencyName", gamesLogin.getCurrency()); + paramsMap.put("winLimit", 0); + paramsMap.put("language", gamesLogin.getLang()); + Map headerMap = this.getKey(gamesLogin); + DGLoginWithoutRedirectResponse loginWithoutRedirectResponse = DGClient.loginWithoutRedirect(paramsMap, headerMap); + if (this.getIsSuccess(loginWithoutRedirectResponse.getCodeId())) { + String url = loginWithoutRedirectResponse.getList().get(0) + "&showapp=off"; + if (!StringUtils.isEmpty(gamesLogin.getHomeUrl())) { + url += "&backUrl=" + gamesLogin.getHomeUrl(); + } + return url; + } else { + throw new ApiException(ErrorCode.ACCOUNT_NOT_EXIST.getCode()); + } + } + + + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + @Transactional + @Override + public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) { + GamePlatform gamePlatform = gamePlatformService.selectGamePlatformById(PLATFORM_ID); + //没有此平台就新增一个平台 + if (ObjectUtils.isEmpty(gamePlatform)) { + gamePlatform = new GamePlatform(); + gamePlatform.setPlatformCode(GamePlatforms.DG.getInfo()); + gamePlatform.setPlatformType(PlatformType.CARD_GAME.getCode()); + gamePlatform.setPlatformName(GamePlatforms.DG.getInfo() + PlatformType.CARD_GAME.getName()); + gamePlatform.setSortNo(gamePlatformService.selectMaxSortNo() + 1); + gamePlatform.setCreateBy(Constants.SYSTEM); + gamePlatformService.insertGamePlatform(gamePlatform); + } + Game game = gameService.selectGameById(GAME_ID); + //不存在这个游戏 + if (ObjectUtils.isEmpty(game)) { + game = new Game(); + game.setSortNo(gameService.selectMaxSortNoByPlatformId(gamePlatform.getId()) + 1); + game.setPlatformId(gamePlatform.getId()); + game.setGameCode("1"); + game.setGameSourceType(1); + game.setGameName("真人棋牌"); + game.setCreateBy(Constants.SYSTEM); + gameService.insertGame(game); + } + GameName gameName = gameNameService.selectGameNameById(GAME_NAME_ID); + if (ObjectUtils.isEmpty(gameName)) { + gameNameService.insertGameName(GameName.builder() + .gameId(game.getId()) + .gameName(game.getGameName()) + .langCode("zh-CN") + .createBy(Constants.SYSTEM) + .build()); + } + return CacheConstants.DG_GAMES; + } + + /** + * 按代理id进行交换转账 + * + * @param exchangeTransferMoneyRequestDTO 外汇转账moeny dto + * @return {@link Long } + */ + @Override + @Transactional + public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { + log.info("GamesDGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); + GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() + .platformCode(GamePlatforms.DG.getInfo()) + .code(exchangeTransferMoneyRequestDTO.getAgentId()) + .build()); + + Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); + String transactionId = GamePlatforms.DG.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.DG.getCode()) + .build(); + exchangeMoney.setCreateBy(Constants.SYSTEM); + + BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); + if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { + // 获取第三方钱包余额 + MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() + .accounts(member.getGameAccount()) + .agentId(exchangeTransferMoneyRequestDTO.getAgentId()) + .currency(exchangeTransferMoneyRequestDTO.getCurrency()) + .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) + .build(); + + BigDecimal balance = this.getMemberInfo(gamesBaseRequestDTO).getBalance(); + amount = balance.compareTo(BigDecimal.ZERO) > 0 ? balance.negate() : balance; + } + + Map params = new LinkedHashMap<>(); + params.put("username", exchangeTransferMoneyRequestDTO.getAccount()); + params.put("amount", amount); + params.put("serial", transactionId); + + Map headerMap = this.getKey(exchangeTransferMoneyRequestDTO); + DGTransactionResponseDTO dgTransactionResponseDTO = DGClient.exchangeTransferByAgentId(params, headerMap); + //判断是否转移成功 + if (this.getIsSuccess(dgTransactionResponseDTO.getCodeId())) { + + //更新数据 + exchangeMoney.setBalance(dgTransactionResponseDTO.getAmount().abs()); + exchangeMoney.setCoinBefore(NumberUtil.sub(dgTransactionResponseDTO.getBalance(), dgTransactionResponseDTO.getAmount().abs()).abs()); + exchangeMoney.setCoinAfter(dgTransactionResponseDTO.getBalance()); + exchangeMoney.setCurrencyBefore(exchangeMoney.getCoinBefore()); + exchangeMoney.setCurrencyAfter(exchangeMoney.getCoinAfter()); + exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); + gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + } else { + log.error("GamesXKServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{},错误信息{}", dgTransactionResponseDTO.getCodeId(), dgTransactionResponseDTO.getMsg()); + throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode()); + } + + 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) { + //请求参数 + log.info("GamesDGServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO); + Map key = this.getKey(betRecordByTimeDTO); + DGBetRecordResponseDTO betRecordByTime = DGClient.getBetRecordByTime(key); + + //判断是否获取成功 + if (this.getIsSuccess(betRecordByTime.getCodeId())) { + this.batchInsert(betRecordByTime,betRecordByTimeDTO); + + + return Boolean.TRUE; + } else { + log.error("GamesXKServiceImpl [getBetRecordByTime] 获取投注记录失败,错误代码{},错误信息{}", betRecordByTime.getCodeId(), betRecordByTime.getMsg()); + throw new BaseException(betRecordByTime.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) { + return null; + } + + /** + * 踢成员全部 + * + * @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 dgBetRecordResponseDTO dg投注记录响应dto + */ + private void batchInsert(DGBetRecordResponseDTO dgBetRecordResponseDTO,GamesBaseRequestDTO gamesBaseRequestDTO) { + List gameBettingDetails = new ArrayList<>(); + List wagersIds = new ArrayList<>(); + //数据组装 + List report = dgBetRecordResponseDTO.getReport(); + //数据转化 + for (DGBetRecordResponseDTO.ReportDTO bean : report) { + 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.getId())); + } + 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); + Map key = this.getKey(gamesBaseRequestDTO); + Map params = new HashMap<>(); + params.put("list", wagersIds); + DGClient.markReport(params,key); + } + } + + } + + /** + * 数据构建 + * + * @param gamesDataBuildDTO 数据 + * @return {@link GameBettingDetails } + */ + @Override + public GameBettingDetails dataBuild(GamesDataBuildDTO gamesDataBuildDTO) { + //转化类 + DGBetRecordResponseDTO.ReportDTO resultBean = (DGBetRecordResponseDTO.ReportDTO) gamesDataBuildDTO.getData(); + + + GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() + .platformCode(GamePlatforms.DG.getInfo()) + .currencyId(String.valueOf(resultBean.getCurrencyId())) + .build()); + + + Member member = memberService.selectMemberByGameAccount(resultBean.getUserName()); + if (ObjectUtils.isEmpty(member)) { + return null; + } + //未结算的不要 + if (0 == resultBean.getIsRevocation()) { + return null; + } + + BigDecimal payoffAmount = BigDecimal.ZERO; + BigDecimal winOrLoss = resultBean.getWinOrLoss(); + //输赢状态 + Integer gameStatus = GameStatus.FLAT.getCode(); + if (winOrLoss.compareTo(resultBean.getBetPoints()) > 0) { + payoffAmount = NumberUtil.sub(winOrLoss, resultBean.getBetPoints()); + gameStatus = GameStatus.WIN.getCode(); + } else if (winOrLoss.compareTo(resultBean.getBetPoints()) < 0) { + payoffAmount = NumberUtil.sub(resultBean.getWinOrLoss(), resultBean.getBetPoints()).negate(); + gameStatus = GameStatus.FAIL.getCode(); + } + + + //数据构造 + GameBettingDetails gameBettingDetails = GameBettingDetails.builder() + .tenantKey(member.getTenantKey()) + //保存我们的币种id + .currencyCode(currencyDTO.getSystemCurrency()) + .memberId(member.getId()) + .gameCode(String.valueOf(resultBean.getGameId())) + .gameType(PlatformType.CARD_GAME.getCode()) + .platformCode(GamePlatforms.SA.getCode()) + .gameId(GAME_ID) + .gameName(String.valueOf(resultBean.getGameId())) + .gameStatus(gameStatus) + .gameStatusType(resultBean.getGameType()) + .gameCurrencyCode(currencyDTO.getCurrency()) + .account(String.valueOf(resultBean.getUserName())) + .wagersId(String.valueOf(resultBean.getId())) + .wagersTime(resultBean.getBetTime().getTime()) + .betAmount(resultBean.getBetPoints()) + .payoffTime(resultBean.getCalTime().getTime()) + .payoffAmount(payoffAmount) + .settlementTime(resultBean.getCalTime().getTime()) + .turnover(resultBean.getAvailableBet()) + .settlementStatus(SettlementStatusEnum.COMPLETED.getCode()) + .build(); + gameBettingDetails.setCreateBy(Constants.SYSTEM); + gameBettingDetails.setCreateTime(DateUtils.getNowDate()); + return gameBettingDetails; + } +} 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 index d3be6db..615f615 100644 --- 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 @@ -245,6 +245,7 @@ public class GamesSAServiceImpl implements IGamesService { //没有此平台就新增一个平台 if (ObjectUtils.isEmpty(gamePlatform)) { gamePlatform = new GamePlatform(); + gamePlatform.setPlatformCode(GamePlatforms.SA.getInfo()); gamePlatform.setPlatformType(PlatformType.CARD_GAME.getCode()); gamePlatform.setPlatformName(GamePlatforms.SA.getInfo() + PlatformType.CARD_GAME.getName()); gamePlatform.setSortNo(gamePlatformService.selectMaxSortNo() + 1); @@ -594,7 +595,7 @@ public class GamesSAServiceImpl implements IGamesService { .currencyCode(currencyDTO.getSystemCurrency()) .memberId(member.getId()) .gameCode(resultBean.getGameID()) - .gameType(1) + .gameType(PlatformType.CARD_GAME.getCode()) .platformCode(GamePlatforms.SA.getCode()) .gameId(GAME_ID) .gameName(game.getGameName()) diff --git a/ff-game/src/main/java/com/ff/game/domain/GameBettingDetails.java b/ff-game/src/main/java/com/ff/game/domain/GameBettingDetails.java index f384d10..04eb913 100644 --- a/ff-game/src/main/java/com/ff/game/domain/GameBettingDetails.java +++ b/ff-game/src/main/java/com/ff/game/domain/GameBettingDetails.java @@ -80,6 +80,8 @@ public class GameBettingDetails extends BaseEntity 18 满额必开 (开奖) 19 免费游戏 28 旋转奖金 + DG + (1:注单,2:红包小费) */ @Excel(name = "注单类型") diff --git a/ff-game/src/main/java/com/ff/game/domain/GameSecretKeyCurrency.java b/ff-game/src/main/java/com/ff/game/domain/GameSecretKeyCurrency.java index 7efb7f7..c081e8a 100644 --- a/ff-game/src/main/java/com/ff/game/domain/GameSecretKeyCurrency.java +++ b/ff-game/src/main/java/com/ff/game/domain/GameSecretKeyCurrency.java @@ -35,6 +35,10 @@ public class GameSecretKeyCurrency extends BaseEntity { @Excel(name = "平台", width = 30, dateFormat = "yyyy-MM-dd") private Long gameSecretKeyId; + /** + * 货币id + */ + private String currencyId; /** * 币种 */ diff --git a/ff-game/src/main/resources/logback.xml b/ff-game/src/main/resources/logback.xml index b94939f..e4f275d 100644 --- a/ff-game/src/main/resources/logback.xml +++ b/ff-game/src/main/resources/logback.xml @@ -1,7 +1,7 @@ - + diff --git a/ff-game/src/main/resources/mapper/game/GameSecretKeyCurrencyMapper.xml b/ff-game/src/main/resources/mapper/game/GameSecretKeyCurrencyMapper.xml index cd211e2..5c988ce 100644 --- a/ff-game/src/main/resources/mapper/game/GameSecretKeyCurrencyMapper.xml +++ b/ff-game/src/main/resources/mapper/game/GameSecretKeyCurrencyMapper.xml @@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -18,6 +19,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -29,7 +31,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, game_secret_key_id, currency, system_currency, create_by, create_time, update_by, update_time from ff_game_secret_key_currency + select id,currency_id, game_secret_key_id, currency, system_currency, create_by, create_time, update_by, update_time from ff_game_secret_key_currency - select gskc.currency, gskc.system_currency,gskc.game_secret_key_id,gsk.code ,gsk.`key`,gsk.platform as platform_code + select gskc.currency, gskc.system_currency,gskc.game_secret_key_id,gsk.code ,gsk.`key`,gsk.platform,gskc.currency_id as platform_code from ff_game_secret_key gsk inner join ff_game_secret_key_currency gskc on gsk.id = gskc.game_secret_key_id @@ -111,12 +116,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{platformCode} + and gskc.currency_id = #{currencyId} limit 1