From bd1c3d9d9e0abdd0565ecbed7fea5cc0cf955f2c Mon Sep 17 00:00:00 2001 From: shi Date: Wed, 12 Mar 2025 17:55:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(game):=20=E6=96=B0=E5=A2=9E=20NG=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 - 新增 NG 游戏平台的相关接口和数据结构 - 实现 NG 游戏平台的余额转移和状态查询功能 - 更新数据库结构,增加支持终端类型和系统货币字段- 优化错误码处理,增加新的错误类型 --- .../com/ff/base/constant/CacheConstants.java | 5 +- .../java/com/ff/base/constant/Constants.java | 5 + .../java/com/ff/base/enums/ErrorCode.java | 2 + .../com/ff/base/enums/GameMemberStatus.java | 26 + .../java/com/ff/base/enums/GamePlatforms.java | 1 + .../java/com/ff/base/enums/IngressType.java | 24 + .../java/com/ff/base/enums/NGGameType.java | 67 +++ .../java/com/ff/base/enums/NGPlatforms.java | 32 ++ .../com/ff/base/enums/NGTransferType.java | 23 + .../com/ff/base/enums/PlatformHomeType.java | 25 + .../java/com/ff/base/enums/StatusType.java | 24 + .../ff/base/exception/base/ApiException.java | 14 + .../java/com/ff/base/utils/SleepUtil.java | 22 + .../java/com/ff/base/utils/StringUtils.java | 66 ++- .../ff/api/controller/ApiGameController.java | 22 +- .../api/controller/ApiMemberController.java | 9 +- .../request/GameExchangeBalanceRequest.java | 2 +- .../com/ff/api/response/GameResponse.java | 6 + .../impl/TenantGameQuotaServiceImpl.java | 3 +- .../java/com/ff/game/api/IGamesService.java | 17 +- .../service/impl/GamesJILIServiceImpl.java | 19 +- .../api/ng/address/MyNGAddressSource.java | 24 + .../com/ff/game/api/ng/client/NGClient.java | 88 +++ .../ApiExchangeTransferStatusResponseDTO.java | 50 ++ .../api/ng/dto/ApiGameInfoResponseDTO.java | 41 ++ .../game/api/ng/dto/ApiLoginResponseDTO.java | 20 + .../api/ng/dto/ApiMemberInfoResponseDTO.java | 19 + .../ff/game/api/ng/dto/ApiNGResponseDTO.java | 26 + .../ng/service/impl/GamesPGServiceImpl.java | 507 ++++++++++++++++++ .../ExchangeTransferStatusRequestDTO.java | 33 ++ .../game/api/request/GamesBaseRequestDTO.java | 8 + .../com/ff/game/api/request/GamesLogin.java | 7 +- .../ff/game/api/request/KickMemberAllDTO.java | 2 +- .../api/request/MemberInfoResponseDTO.java | 1 + .../xk/service/impl/GamesXKServiceImpl.java | 29 +- .../main/java/com/ff/game/domain/Game.java | 7 +- .../com/ff/game/domain/GameExchangeMoney.java | 2 +- .../com/ff/game/domain/GameSecretKey.java | 12 +- .../ff/game/mapper/GameSecretKeyMapper.java | 2 +- .../service/IGameExchangeMoneyService.java | 10 + .../game/service/IGameSecretKeyService.java | 2 +- .../impl/GameExchangeMoneyServiceImpl.java | 30 ++ .../impl/GameSecretKeyServiceImpl.java | 4 +- .../com/ff/system/SysLoginController.java | 2 +- .../main/resources/mapper/game/GameMapper.xml | 19 +- .../mapper/game/GameSecretKeyMapper.xml | 25 +- 46 files changed, 1318 insertions(+), 66 deletions(-) create mode 100644 ff-base/src/main/java/com/ff/base/enums/GameMemberStatus.java create mode 100644 ff-base/src/main/java/com/ff/base/enums/IngressType.java create mode 100644 ff-base/src/main/java/com/ff/base/enums/NGGameType.java create mode 100644 ff-base/src/main/java/com/ff/base/enums/NGPlatforms.java create mode 100644 ff-base/src/main/java/com/ff/base/enums/NGTransferType.java create mode 100644 ff-base/src/main/java/com/ff/base/enums/PlatformHomeType.java create mode 100644 ff-base/src/main/java/com/ff/base/enums/StatusType.java create mode 100644 ff-base/src/main/java/com/ff/base/utils/SleepUtil.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/address/MyNGAddressSource.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/client/NGClient.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/dto/ApiExchangeTransferStatusResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/dto/ApiGameInfoResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/dto/ApiLoginResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/dto/ApiMemberInfoResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/dto/ApiNGResponseDTO.java create mode 100644 ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java create mode 100644 ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferStatusRequestDTO.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 cc7b46b..7475779 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 @@ -52,7 +52,10 @@ public class CacheConstants */ public static final String XK_GAMES= "xk_games:"; - + /** + * pg游戏 + */ + public static final String PG_GAMES= "pg_games:"; /** * 通知窗口 */ 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 38b649b..a41b811 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 @@ -183,6 +183,11 @@ public class Constants { */ public static final String JILI_API_BASE_URL = "jili.api.base.url"; + /** + * ng 接口请求前缀 + */ + public static final String NG_API_BASE_URL = "ng.api.base.url"; + /** * 吉利测试地址 */ diff --git a/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java b/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java index 24595dd..e46daf7 100644 --- a/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java +++ b/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java @@ -20,6 +20,8 @@ public enum ErrorCode { CURRENCY_NOT_EXIST(1004, "游戏平台不支持的货币"), GAME_NOT_EXIST(1005, "游戏不存在"), CURRENCY_EXCHANGE(1006, "不支持币种的汇率"), + FREQUENT_INTERFACE_REQUESTS (1007, "接口请求频繁"), + BALANCE_TRANSFER_FAILED (1008, "余额转移失败"), ; // 获取错误码 diff --git a/ff-base/src/main/java/com/ff/base/enums/GameMemberStatus.java b/ff-base/src/main/java/com/ff/base/enums/GameMemberStatus.java new file mode 100644 index 0000000..bbf2486 --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/GameMemberStatus.java @@ -0,0 +1,26 @@ +package com.ff.base.enums; + +import lombok.Data; +import lombok.Getter; + +/** + * 游戏会员身份 + * + * @author shi + * @date 2025/03/12 + */ +@Getter +public enum GameMemberStatus { + ONLINE(1, "在线"), + OFFLINE(2, "脱机"), + ACCOUNT_NOT_EXIST(3, "账号不存在"), + UNKNOWN(4, "未知"); + + private final int code; + private final String description; + + GameMemberStatus(int code, String description) { + this.code = code; + this.description = description; + } +} 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 d58f3e4..6701f6f 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 @@ -6,6 +6,7 @@ import java.util.List; public enum GamePlatforms { JILI("JILI", "JILI"), XK("XK", "XK"), + PG("PG", "PG"), ; private final String code; diff --git a/ff-base/src/main/java/com/ff/base/enums/IngressType.java b/ff-base/src/main/java/com/ff/base/enums/IngressType.java new file mode 100644 index 0000000..af78b82 --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/IngressType.java @@ -0,0 +1,24 @@ +package com.ff.base.enums; + +import lombok.Getter; + +/** + * 入口类型 + * + * @author shi + * @date 2025/03/12 + */ +@Getter +public enum IngressType { + PC_WEB(1, "电脑网页"), + MOBILE_WEB(2, "手机网页"), + PC_AND_MOBILE_WEB(3, "电脑/手机网页"); + + private final Integer value; + private final String description; + + IngressType(Integer value, String description) { + this.value = value; + this.description = description; + } +} \ No newline at end of file diff --git a/ff-base/src/main/java/com/ff/base/enums/NGGameType.java b/ff-base/src/main/java/com/ff/base/enums/NGGameType.java new file mode 100644 index 0000000..633984d --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/NGGameType.java @@ -0,0 +1,67 @@ +package com.ff.base.enums; + + +import lombok.Getter; + +import java.util.Optional; +import java.util.stream.Stream; + + +/** + * xkgame类型 + * + * @author shi + * @date 2024/11/13 + */ +@Getter +public enum NGGameType { + + VIDEO(1, 6,"视讯"), + SLOT(2,5, "老虎机"), + LOTTERY(3,7, "彩票"), + SPORTS(4, 8,"体育"), + ESPORTS(5, 1,"电竞"), + HUNTING(6, 9,"捕猎"), + CHESS(7,2, "棋牌") + + ; + + private final Integer code; + private final Integer systemCode; + private final String info; + NGGameType(Integer code, Integer systemCode, String info) + { + this.code = code; + this.systemCode = systemCode; + this.info = info; + } + + + /** + * 按代码查找系统 + * + * @param code 代码 + * @return {@link String } + */ + public static Integer findSystemByCode(Integer code) { + Optional system = Stream.of(NGGameType.values()) + .filter(gameType -> gameType.getCode().equals(code)) + .map(NGGameType::getSystemCode) + .findFirst(); + return system.orElse(null); + } + + /** + * 按代码查找信息 + * + * @param code 代码 + * @return {@link String } + */ + public static String findInfoByCode(Integer code) { + Optional system = Stream.of(NGGameType.values()) + .filter(gameType -> gameType.getCode().equals(code)) + .map(NGGameType::getInfo) + .findFirst(); + return system.orElse(null); + } +} diff --git a/ff-base/src/main/java/com/ff/base/enums/NGPlatforms.java b/ff-base/src/main/java/com/ff/base/enums/NGPlatforms.java new file mode 100644 index 0000000..18a445c --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/NGPlatforms.java @@ -0,0 +1,32 @@ +package com.ff.base.enums; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * ng平台 支持游戏 + * + * @author shi + * @date 2025/03/11 + */ +@Getter +public enum NGPlatforms { + PG("pg", "PG") + ; + + private final String code; + private final String platform; + + NGPlatforms(String code, String platform) + { + this.code = code; + this.platform = platform; + } + + + + + +} diff --git a/ff-base/src/main/java/com/ff/base/enums/NGTransferType.java b/ff-base/src/main/java/com/ff/base/enums/NGTransferType.java new file mode 100644 index 0000000..3fa88c8 --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/NGTransferType.java @@ -0,0 +1,23 @@ +package com.ff.base.enums; + +import lombok.Getter; + +/** + * 长传输类型 + * + * @author shi + * @date 2025/03/12 + */ +@Getter +public enum NGTransferType { + TRANSFER_IN("1", "转入"), + TRANSFER_OUT("2", "转出"); + + private final String value; + private final String description; + + NGTransferType(String value, String description) { + this.value = value; + this.description = description; + } +} diff --git a/ff-base/src/main/java/com/ff/base/enums/PlatformHomeType.java b/ff-base/src/main/java/com/ff/base/enums/PlatformHomeType.java new file mode 100644 index 0000000..2f151d1 --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/PlatformHomeType.java @@ -0,0 +1,25 @@ +package com.ff.base.enums; + +import lombok.Data; +import lombok.Getter; + +/** + * 平台家庭类型 + * + * @author shi + * @date 2025/03/12 + */ +@Getter +public enum PlatformHomeType { + WEB("web", "Web 平台"), + APP("app", "App 平台"); + + private final String value; + private final String description; + + PlatformHomeType(String value, String description) { + this.value = value; + this.description = description; + } + +} diff --git a/ff-base/src/main/java/com/ff/base/enums/StatusType.java b/ff-base/src/main/java/com/ff/base/enums/StatusType.java new file mode 100644 index 0000000..138dd5d --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/StatusType.java @@ -0,0 +1,24 @@ +package com.ff.base.enums; + +import lombok.Getter; + +/** + * 状态类型 + * + * @author shi + * @date 2025/03/12 + */ +@Getter +public enum StatusType { + IN_PROGRESS(0, "进行中"), + SUCCESS(1, "成功"), + FAILURE(2, "失败"); + + private final Integer value; + private final String description; + + StatusType(Integer value, String description) { + this.value = value; + this.description = description; + } +} diff --git a/ff-base/src/main/java/com/ff/base/exception/base/ApiException.java b/ff-base/src/main/java/com/ff/base/exception/base/ApiException.java index 4b0b63b..f4b91c9 100644 --- a/ff-base/src/main/java/com/ff/base/exception/base/ApiException.java +++ b/ff-base/src/main/java/com/ff/base/exception/base/ApiException.java @@ -52,4 +52,18 @@ public class ApiException extends RuntimeException { throw new ApiException(code); } } + + + /** + * 是真 + * + * @param bool 布尔 + * @param code 代码 + */ + public static void isTrue(@Nullable Boolean bool, Integer code) { + if (Boolean.FALSE.equals(bool)) { + throw new ApiException(code); + } + } + } diff --git a/ff-base/src/main/java/com/ff/base/utils/SleepUtil.java b/ff-base/src/main/java/com/ff/base/utils/SleepUtil.java new file mode 100644 index 0000000..517076b --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/utils/SleepUtil.java @@ -0,0 +1,22 @@ +package com.ff.base.utils; + +/** + * 睡眠有用 + * + * @author shi + * @date 2025/03/12 + */ +public class SleepUtil { + /** + * 使当前线程休眠指定的毫秒数 + * + * @param millis 延迟时间(毫秒) + */ + public static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // 恢复中断状态 + } + } +} diff --git a/ff-base/src/main/java/com/ff/base/utils/StringUtils.java b/ff-base/src/main/java/com/ff/base/utils/StringUtils.java index 721c628..e8fbe8d 100644 --- a/ff-base/src/main/java/com/ff/base/utils/StringUtils.java +++ b/ff-base/src/main/java/com/ff/base/utils/StringUtils.java @@ -5,6 +5,8 @@ import com.ff.base.constant.Constants; import com.ff.base.core.text.StrFormatter; import org.springframework.util.AntPathMatcher; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.*; /** @@ -588,7 +590,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { * @return {@link String } */ public static String addSuffix(String account, String suffix) { - return account + "_" + suffix; + return account + suffix; } /** @@ -597,14 +599,64 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { * @param original 原始字符串 * @return 移除后的字符串 */ - public static String removeLastOccurrence(String original) { - // 查找下划线的位置 - int index = original.indexOf('_'); - if (index != -1) { - // 返回下划线前面的部分 - return original.substring(0, index); + public static String removeLastOccurrence(String original, String suffix) { + // 查找位置 + if (original.endsWith(suffix)) { + return original.substring(0, original.length() - suffix.length()); } return original; } + /** + * 生成唯一的订单号 + * + * @param prefix 前缀(例如:"PG") + * @param length 订单号中随机部分的总长度(不包括前缀) + * @return 生成的唯一订单号 + */ + public static String generateOrderId(String prefix, int length) { + if (length <= prefix.length()) { + throw new IllegalArgumentException("订单号长度必须大于前缀长度"); + } + // 获取当前时间戳 + long timestamp = System.currentTimeMillis(); + + // 使用UUID生成一个随机的字符串并去掉 "-" + String randomString = UUID.randomUUID().toString().replace("-", ""); + + // 拼接时间戳和随机字符串 + String source = prefix + timestamp + randomString; + + // 截取指定长度的部分(确保符合需求的长度) + String orderId = getMD5Hash(source).substring(0, length - prefix.length()); + + return prefix + orderId; + } + + /** + * 使用MD5算法生成哈希值 + * + * @param source 输入字符串 + * @return 哈希值 + */ + private static String getMD5Hash(String source) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] digest = md.digest(source.getBytes()); + StringBuilder hexString = new StringBuilder(); + + // 转换为16进制 + for (byte b : digest) { + String hex = Integer.toHexString(0xFF & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); // 返回32位MD5哈希 + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } } diff --git a/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java b/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java index 3fc8bdf..7c200ac 100644 --- a/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java +++ b/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java @@ -111,7 +111,7 @@ public class ApiGameController extends BaseController { List gameSecretKeys = gameSecretKeyService.selectGameSecretKeyList(GameSecretKey.builder() .platform(gameRespons.getPlatformCode()) .build()); - List currencyCode = gameSecretKeys.stream().map(GameSecretKey::getSystemCode).collect(Collectors.toList()); + List currencyCode = gameSecretKeys.stream().map(GameSecretKey::getSystemCurrency).collect(Collectors.toList()); gameRespons.setCurrencyCode(currencyCode); } return AjaxResult.success(gameResponses); @@ -138,7 +138,7 @@ public class ApiGameController extends BaseController { TenantSecretKey tenantSecretKey = keyConfig.get(); - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gamePlatform.getPlatformCode(), memberCreateApiRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gamePlatform.getPlatformCode(), memberCreateApiRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); GameSecretKey gameSecretKeyLang = gameSecretKeyService.findByPlatformAndSystemLangCode(gamePlatform.getPlatformCode(), memberCreateApiRequest.getLangCode()); @@ -151,6 +151,8 @@ public class ApiGameController extends BaseController { .agentId(gameSecretKey.getCode()) .agentKey(gameSecretKey.getKey()) .account(member.getGameAccount()) + .gameSecretKeyId(gameSecretKey.getId()) + .gameType(game.getGameSourceType()) .gameId(game.getGameCode()) .homeUrl(memberCreateApiRequest.getHomeUrl()) .platform(memberCreateApiRequest.getPlatform()) @@ -180,7 +182,7 @@ public class ApiGameController extends BaseController { TenantSecretKey tenantSecretKey = keyConfig.get(); - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameExchangeBalanceRequest.getPlatformCode(), gameExchangeBalanceRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameExchangeBalanceRequest.getPlatformCode(), gameExchangeBalanceRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); BigDecimal quota = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder() @@ -203,6 +205,7 @@ public class ApiGameController extends BaseController { .agentKey(gameSecretKey.getKey()) .orderId(gameExchangeBalanceRequest.getOrderId()) .account(member.getGameAccount()) + .gameSecretKeyId(gameSecretKey.getId()) .tenantKey(tenantSecretKey.getTenantKey()) .quota(quota) .amount(gameExchangeBalanceRequest.getAmount()) @@ -231,7 +234,7 @@ public class ApiGameController extends BaseController { TenantSecretKey tenantSecretKey = keyConfig.get(); - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameCreateFreeSpinRequest.getPlatformCode(), gameCreateFreeSpinRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameCreateFreeSpinRequest.getPlatformCode(), gameCreateFreeSpinRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameCreateFreeSpinRequest.getAccount(), gameCreateFreeSpinRequest.getCurrencyCode() + tenantSecretKey.getTenantSn())); @@ -300,7 +303,7 @@ public class ApiGameController extends BaseController { public AjaxResult getDetail(@Validated @RequestBody GameGetDetailRequest gameGetDetailRequest) { - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameGetDetailRequest.getPlatformCode(), gameGetDetailRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameGetDetailRequest.getPlatformCode(), gameGetDetailRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); @@ -328,7 +331,7 @@ public class ApiGameController extends BaseController { */ @PostMapping("/kick/member") public AjaxResult kickMember(@Validated @RequestBody GameKickMemeberRequest gameKickMemeberRequest) { - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameKickMemeberRequest.getPlatformCode(), gameKickMemeberRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameKickMemeberRequest.getPlatformCode(), gameKickMemeberRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); TenantSecretKey tenantSecretKey = keyConfig.get(); @@ -348,7 +351,7 @@ public class ApiGameController extends BaseController { @PostMapping("/kick/member/all") public AjaxResult kickMemberAll(@Validated @RequestBody GameKickMemeberAllRequest gameKickMemeberAllRequest) { - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameKickMemeberAllRequest.getPlatformCode(), gameKickMemeberAllRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameKickMemeberAllRequest.getPlatformCode(), gameKickMemeberAllRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); IGamesService iGamesService = gamesService.get(gameKickMemeberAllRequest.getPlatformCode() + Constants.SERVICE); @@ -410,7 +413,7 @@ public class ApiGameController extends BaseController { */ @PostMapping("/cancel/free/spin") public AjaxResult cancelFreeSpin(@Validated @RequestBody GameCancelFreeSpinRequest gameGetFreeSpinDashflowRequest) { - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameGetFreeSpinDashflowRequest.getPlatformCode(), gameGetFreeSpinDashflowRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameGetFreeSpinDashflowRequest.getPlatformCode(), gameGetFreeSpinDashflowRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); IGamesService iGamesService = gamesService.get(gameGetFreeSpinDashflowRequest.getPlatformCode() + Constants.SERVICE); @@ -438,7 +441,7 @@ public class ApiGameController extends BaseController { ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); - List gameSecretKeys = gameSecretKeyService.selectGameSecretKeyList(GameSecretKey.builder().systemCode(gameExchangeBalanceAllRequest.getCurrencyCode()).build()); + List gameSecretKeys = gameSecretKeyService.selectGameSecretKeyList(GameSecretKey.builder().systemCurrency(gameExchangeBalanceAllRequest.getCurrencyCode()).build()); // 创建线程池 @@ -459,6 +462,7 @@ public class ApiGameController extends BaseController { .agentId(gameSecretKey.getCode()) .agentKey(gameSecretKey.getKey()) .orderId(gameExchangeBalanceAllRequest.getOrderId()) + .gameSecretKeyId(gameSecretKey.getId()) .amount(BigDecimal.ONE) .tenantKey(tenantSecretKey.getTenantKey()) .account(member.getGameAccount()) diff --git a/ff-game/src/main/java/com/ff/api/controller/ApiMemberController.java b/ff-game/src/main/java/com/ff/api/controller/ApiMemberController.java index 05d2925..1908986 100644 --- a/ff-game/src/main/java/com/ff/api/controller/ApiMemberController.java +++ b/ff-game/src/main/java/com/ff/api/controller/ApiMemberController.java @@ -92,7 +92,7 @@ public class ApiMemberController extends BaseController { ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode()); TenantSecretKey tenantSecretKey = keyConfig.get(); - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(memberCreateApiRequest.getPlatformCode(), memberCreateApiRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(memberCreateApiRequest.getPlatformCode(), memberCreateApiRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); String gameAccount = StringUtils.addSuffix(memberCreateApiRequest.getAccount(), memberCreateApiRequest.getCurrencyCode() + tenantSecretKey.getTenantSn()); @@ -116,6 +116,7 @@ public class ApiMemberController extends BaseController { CreateMemberRequestDTO gamesBaseRequestDTO = CreateMemberRequestDTO.builder() .account(gameAccount) .agentId(gameSecretKey.getCode()) + .gameSecretKeyId(gameSecretKey.getId()) .agentKey(gameSecretKey.getKey()) .build(); Boolean result = iGamesService.createMember(gamesBaseRequestDTO); @@ -138,7 +139,7 @@ public class ApiMemberController extends BaseController { TenantSecretKey tenantSecretKey = keyConfig.get(); - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(memberInfoApiRequest.getPlatformCode(), memberInfoApiRequest.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(memberInfoApiRequest.getPlatformCode(), memberInfoApiRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(memberInfoApiRequest.getAccount(), memberInfoApiRequest.getCurrencyCode() + tenantSecretKey.getTenantSn())); @@ -148,6 +149,7 @@ public class ApiMemberController extends BaseController { MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() .accounts(member.getGameAccount()) .agentId(gameSecretKey.getCode()) + .gameSecretKeyId(gameSecretKey.getId()) .agentKey(gameSecretKey.getKey()) .build(); MemberInfoResponseDTO memberInfo = iGamesService.getMemberInfo(gamesBaseRequestDTO); @@ -171,7 +173,7 @@ public class ApiMemberController extends BaseController { ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); - List gameSecretKeys = gameSecretKeyService.selectGameSecretKeyList(GameSecretKey.builder().systemCode(memberInfoAllApiRequest.getCurrencyCode()).build()); + List gameSecretKeys = gameSecretKeyService.selectGameSecretKeyList(GameSecretKey.builder().systemCurrency(memberInfoAllApiRequest.getCurrencyCode()).build()); // 创建线程池 @@ -189,6 +191,7 @@ public class ApiMemberController extends BaseController { MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() .accounts(member.getGameAccount()) .agentId(gameSecretKey.getCode()) + .gameSecretKeyId(gameSecretKey.getId()) .agentKey(gameSecretKey.getKey()) .build(); //查询余额 diff --git a/ff-game/src/main/java/com/ff/api/request/GameExchangeBalanceRequest.java b/ff-game/src/main/java/com/ff/api/request/GameExchangeBalanceRequest.java index 80fb60e..a00f911 100644 --- a/ff-game/src/main/java/com/ff/api/request/GameExchangeBalanceRequest.java +++ b/ff-game/src/main/java/com/ff/api/request/GameExchangeBalanceRequest.java @@ -43,7 +43,7 @@ public class GameExchangeBalanceRequest implements Serializable { * 金额 */ @NotNull(message = "amount不能为空") - @DecimalMin(value = "0.01", message = "amount必须大于等于0.1") + @Min(value = 1, message = "amount最小值为1") @Max(value = 999999999, message = "amount最大值为999999999") private BigDecimal amount; diff --git a/ff-game/src/main/java/com/ff/api/response/GameResponse.java b/ff-game/src/main/java/com/ff/api/response/GameResponse.java index 84b84d0..1c7d003 100644 --- a/ff-game/src/main/java/com/ff/api/response/GameResponse.java +++ b/ff-game/src/main/java/com/ff/api/response/GameResponse.java @@ -49,6 +49,12 @@ public class GameResponse implements Serializable { */ private Integer platformType; + /** + * 支持的终端类型 1:电脑网页、2:手机网页、3:电脑/手机网页 + */ + private Integer ingress; + + /** * 支持货币代码 */ diff --git a/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java b/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java index 4b740d6..63c7dfd 100644 --- a/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java +++ b/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java @@ -282,7 +282,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { @Override public BigDecimal gameBalanceExchange(GameBalanceExchange gameBalanceExchange) { // 获取平台接口密钥 - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode()); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCurrency(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode()); // 检查平台密钥是否存在,否则抛出异常 ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); @@ -329,6 +329,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() .accounts(member.getGameAccount()) .agentId(gameSecretKey.getCode()) + .gameSecretKeyId(gameSecretKey.getId()) .agentKey(gameSecretKey.getKey()) .build(); balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); diff --git a/ff-game/src/main/java/com/ff/game/api/IGamesService.java b/ff-game/src/main/java/com/ff/game/api/IGamesService.java index 3236933..d567300 100644 --- a/ff-game/src/main/java/com/ff/game/api/IGamesService.java +++ b/ff-game/src/main/java/com/ff/game/api/IGamesService.java @@ -17,14 +17,6 @@ import java.util.List; public interface IGamesService { - /** - * 获取密钥 - * - * @param gamesBaseRequestDTO 游戏请求dto - * @return {@link String } - */ - String getKey(GamesBaseRequestDTO gamesBaseRequestDTO); - /** * 创建成员 * @@ -70,6 +62,15 @@ public interface IGamesService { Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO); + /** + * 汇兑转移状态确认 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO); + + /** * 按时间获取投注记录 * diff --git a/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java index 7f671fc..b21eb54 100644 --- a/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java @@ -102,8 +102,7 @@ public class GamesJILIServiceImpl implements IGamesService { * @param gamesBaseRequestDTO 游戏请求dto * @return {@link String } */ - @Override - public String getKey(GamesBaseRequestDTO gamesBaseRequestDTO) { + private String getKey(GamesBaseRequestDTO gamesBaseRequestDTO) { Random random = new Random(); //取出对应的key跟密钥跟请求参数 String agentKey = gamesBaseRequestDTO.getAgentKey(); @@ -247,7 +246,7 @@ public class GamesJILIServiceImpl implements IGamesService { } Game game = Game.builder() .platformId(gamePlatform.getId()) - .gameCode(gamesDataDTO.getGameId()) + .gameCode(String.valueOf(gamesDataDTO.getGameId())) .build(); List games = gameService.selectGameList(game); //不存在这个游戏 @@ -332,6 +331,9 @@ public class GamesJILIServiceImpl implements IGamesService { JILIExchangeMoneyResponseDTO.BeanData 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()); @@ -349,6 +351,17 @@ public class GamesJILIServiceImpl implements IGamesService { return exchangeMoney.getId(); } + /** + * 汇兑转移状态 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { + return Boolean.TRUE; + } + /** * 按时间获取投注记录 diff --git a/ff-game/src/main/java/com/ff/game/api/ng/address/MyNGAddressSource.java b/ff-game/src/main/java/com/ff/game/api/ng/address/MyNGAddressSource.java new file mode 100644 index 0000000..7f1a0d0 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/address/MyNGAddressSource.java @@ -0,0 +1,24 @@ +package com.ff.game.api.ng.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; + +@Component +public class MyNGAddressSource implements AddressSource { + + @Resource + private ISysConfigService configService; + + + @Override + public ForestAddress getAddress(ForestRequest request) { + String apiBaseUrl = configService.selectConfigByKey(Constants.NG_API_BASE_URL); + return new ForestAddress("https",apiBaseUrl, 443,"api"); + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/client/NGClient.java b/ff-game/src/main/java/com/ff/game/api/ng/client/NGClient.java new file mode 100644 index 0000000..ee57acd --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/client/NGClient.java @@ -0,0 +1,88 @@ +package com.ff.game.api.ng.client; + + +import com.dtflys.forest.annotation.*; +import com.ff.game.api.jili.address.MyJILIAddressSource; +import com.ff.game.api.jili.dto.JILICreateMemberResponseDTO; +import com.ff.game.api.jili.dto.JILIExchangeMoneyResponseDTO; +import com.ff.game.api.ng.address.MyNGAddressSource; +import com.ff.game.api.ng.dto.*; +import com.ff.game.api.xk.dto.XKExchangeMoneyResponseDTO; +import com.ff.game.api.xk.dto.XKLoginWithoutRedirectResponseDTO; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * ng客户端 + * + * @author shi + * @date 2025/03/11 + */ +@Address(source = MyNGAddressSource.class) +public interface NGClient { + + /** + * 创建成员 + * + * @param parameters 参数 + * @return {@link String } + */ + @Post("/server/create") + ApiNGResponseDTO createMember(@JSONBody Map parameters, @Header Map headerMap); + + /** + * 获取会员信息 + * + * @param parameters 范围 + * @param headerMap 标题映射 + * @return {@link ApiNGResponseDTO }<{@link String }> + */ + @Post("/server/balance") + ApiNGResponseDTO getMemberInfo(@JSONBody Map parameters, @Header Map headerMap); + + + /** + * 获取游戏列表 + * + * @param parameters 范围 + * @param headerMap 标题映射 + * @return {@link ApiNGResponseDTO }<{@link List }> + */ + @Post("/server/gameCode") + ApiNGResponseDTO> getGameList(@JSONBody Map parameters, @Header Map headerMap); + + + /** + * 无重定向登录 + * + * @param parameters 范围 + * @param headerMap 标题映射 + * @return {@link ApiNGResponseDTO }<{@link ApiLoginResponseDTO }> + */ + @Post("/server/gameUrl") + ApiNGResponseDTO loginWithoutRedirect(@JSONBody Map parameters, @Header Map headerMap); + + + /** + * 按代理id进行交换转账 + * + * @param parameters 范围 + * @param headerMap 标题映射 + * @return {@link ApiNGResponseDTO }<{@link ApiLoginResponseDTO }> + */ + @Post(url = "/server/transfer",connectTimeout = 70000) + ApiNGResponseDTO exchangeTransferByAgentId(@JSONBody Map parameters, @Header Map headerMap); + + + /** + * 汇兑转移状态 + * + * @param parameters 范围 + * @param headerMap 标题映射 + * @return {@link ApiNGResponseDTO }<{@link ApiExchangeTransferStatusResponseDTO }> + */ + @Post(url = "/server/transferStatus") + ApiNGResponseDTO exchangeTransferStatus(@JSONBody Map parameters, @Header Map headerMap); +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiExchangeTransferStatusResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiExchangeTransferStatusResponseDTO.java new file mode 100644 index 0000000..1bf9196 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiExchangeTransferStatusResponseDTO.java @@ -0,0 +1,50 @@ +package com.ff.game.api.ng.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * api交换传输状态响应dto + * + * @author shi + * @date 2025/03/12 + */ +@Data +public class ApiExchangeTransferStatusResponseDTO { + /** + * 玩家账号 + */ + private String playerId; + + /** + * 订单号 + */ + private String orderId; + + /** + * 创建时间 + * 使用 LocalDateTime 类型来处理日期和时间 + */ + private Date createTime; + + /** + * 转换额度,正数转入、负数转出 + * 使用 BigDecimal 类型以便精确处理货币和财务相关数据 + */ + private BigDecimal amount; + + /** + * 转换后玩家剩余额度 + * 使用 BigDecimal 类型以便精确处理货币和财务相关数据 + */ + private BigDecimal afterBalance; + + /** + * 状态,0:进行中、1:成功、2:失败 + */ + private int status; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiGameInfoResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiGameInfoResponseDTO.java new file mode 100644 index 0000000..b4e75db --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiGameInfoResponseDTO.java @@ -0,0 +1,41 @@ +package com.ff.game.api.ng.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * api游戏信息响应dto + * + * @author shi + * @date 2025/03/12 + */ +@Data +public class ApiGameInfoResponseDTO { + + /** + * 游戏平台 + */ + private String platType; + /** + * 游戏类型 + */ + private Integer gameType; + /** + * 游戏代码 + */ + private String gameCode; + /** + * 支持终端类型 + */ + private String ingress; + /** + * 游戏名称(多语言) + */ + private Map gameName; + + /** + * 系统游戏id + */ + private Long systemGameId; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiLoginResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiLoginResponseDTO.java new file mode 100644 index 0000000..208e37e --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiLoginResponseDTO.java @@ -0,0 +1,20 @@ +package com.ff.game.api.ng.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * api成员信息响应dto + * + * @author shi + * @date 2025/03/12 + */ +@Data +public class ApiLoginResponseDTO { + + /** + * 游戏链接 + */ + private String url; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiMemberInfoResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiMemberInfoResponseDTO.java new file mode 100644 index 0000000..ff63bd0 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiMemberInfoResponseDTO.java @@ -0,0 +1,19 @@ +package com.ff.game.api.ng.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * api成员信息响应dto + * + * @author shi + * @date 2025/03/12 + */ +@Data +public class ApiMemberInfoResponseDTO { + /** + * 余额 + */ + private BigDecimal balance; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiNGResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiNGResponseDTO.java new file mode 100644 index 0000000..e48042f --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/dto/ApiNGResponseDTO.java @@ -0,0 +1,26 @@ +package com.ff.game.api.ng.dto; + +import lombok.Data; +import org.apache.poi.ss.formula.functions.T; + +/** + * api对应于 + * + * @author shi + * @date 2025/03/11 + */ +@Data +public class ApiNGResponseDTO { + /** + * 状态码,10000 成功,其他失败 + */ + private int code; + /** + * 消息 + */ + private String msg; + /** + * 数据 + */ + private T data; +} diff --git a/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java new file mode 100644 index 0000000..0feecaf --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java @@ -0,0 +1,507 @@ +package com.ff.game.api.ng.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.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.jili.dto.*; +import com.ff.game.api.ng.client.NGClient; +import com.ff.game.api.ng.dto.*; +import com.ff.game.api.request.*; +import com.ff.game.domain.*; +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.security.SecureRandom; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + + +/** + * 游戏数据解析服务 + * + * @author shi + * @date 2024/10/21 + */ +@Service("PGService") +@Slf4j +public class GamesPGServiceImpl 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 NGClient ngClient; + + + @Resource + private KeyConfig keyConfig; + + @Resource + private IGameBettingDetailsService gameBettingDetailsService; + + + /** + * 获得就是成功 + * + * @param errorCode 错误代码 + * @return {@link Boolean } + */ + private Boolean getIsSuccess(Integer errorCode) { + ApiException.isTrue(10009 != errorCode, ErrorCode.FREQUENT_INTERFACE_REQUESTS.getCode()); + + return 10000 == errorCode; + } + + + /** + * 获取密钥 + * + * @param gamesBaseRequestDTO 游戏基础请求dto + * @return {@link Map }<{@link String }, {@link String }> + */ + private Map getKey(GamesBaseRequestDTO gamesBaseRequestDTO) { + Map headerMap = new HashMap<>(); + + String characters = "abcdefghijklmnopqrstuvwxyz0123456789"; + SecureRandom random = new SecureRandom(); + // 生成 16-32 之间的随机长度 + int length = 16 + random.nextInt(17); + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + sb.append(characters.charAt(random.nextInt(characters.length()))); + } + + //取出对应的key跟密钥跟请求参数 + String agentKey = gamesBaseRequestDTO.getAgentKey(); + String agentId = gamesBaseRequestDTO.getAgentId(); + String key = Md5Utils.md5New(sb + agentId + agentKey); + headerMap.put("sign", key); + headerMap.put("random", String.valueOf(sb)); + headerMap.put("sn", agentId); + headerMap.put("Content-Type", "application/json"); + return headerMap; + } + + /** + * 创建成员 + * + * @param createMemberRequestDTO 创建成员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) { + log.info("GamesNGServiceImpl [createMember] 请求参数 {}", createMemberRequestDTO); + GameSecretKey gameSecretKey = gameSecretKeyService.selectGameSecretKeyById(createMemberRequestDTO.getGameSecretKeyId()); + Map paramsMap = new HashMap<>(); + paramsMap.put("playerId", createMemberRequestDTO.getAccount()); + paramsMap.put("platType", NGPlatforms.PG.getCode()); + paramsMap.put("currency", gameSecretKey.getCurrency()); + Map headerMap = this.getKey(createMemberRequestDTO); + ApiNGResponseDTO apiNGResponseDTO = ngClient.createMember(paramsMap, headerMap); + int errorCode = apiNGResponseDTO.getCode(); + if (10000 == errorCode) { + return Boolean.TRUE; + } + if (10002 == errorCode) { + throw new ApiException(ErrorCode.GAME_ACCOUNT_CREATION_FAILED.getCode()); + } + //判断是否获取成功 + return Boolean.FALSE; + } + + + /** + * 获取会员信息 + * + * @param memberInfoRequestDTO 会员信息请求dto + * @return {@link MemberInfoResponseDTO } + */ + @Override + public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO) { + log.info("GamesNGServiceImpl [getMemberInfo] 请求参数 {}", memberInfoRequestDTO); + GameSecretKey gameSecretKey = gameSecretKeyService.selectGameSecretKeyById(memberInfoRequestDTO.getGameSecretKeyId()); + Map paramsMap = new HashMap<>(); + paramsMap.put("playerId", memberInfoRequestDTO.getAccounts()); + paramsMap.put("platType", NGPlatforms.PG.getCode()); + paramsMap.put("currency", gameSecretKey.getCurrency()); + Map headerMap = this.getKey(memberInfoRequestDTO); + //这个接口请求稍微重复一次就报错 + SleepUtil.sleep(500); + ApiNGResponseDTO apiNGResponseDTO = ngClient.getMemberInfo(paramsMap, headerMap); + int errorCode = apiNGResponseDTO.getCode(); + if (this.getIsSuccess(errorCode)) { + return MemberInfoResponseDTO.builder().account(memberInfoRequestDTO.getAccounts()).balance(apiNGResponseDTO.getData().getBalance()).status(GameMemberStatus.UNKNOWN.getCode()).build(); + } else { + throw new BaseException(apiNGResponseDTO.getMsg()); + } + } + + /** + * 无重定向登录 + * + * @param gamesLogin 游戏登录 + * @return {@link String } + */ + @Override + public String loginWithoutRedirect(GamesLogin gamesLogin) { + log.info("GamesNGServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin); + GameSecretKey gameSecretKey = gameSecretKeyService.selectGameSecretKeyById(gamesLogin.getGameSecretKeyId()); + Map paramsMap = new HashMap<>(); + paramsMap.put("playerId", gamesLogin.getAccount()); + paramsMap.put("platType", NGPlatforms.PG.getCode()); + paramsMap.put("currency", gameSecretKey.getCurrency()); + paramsMap.put("gameType", gamesLogin.getGameType()); + paramsMap.put("lang", gameSecretKey.getLang()); + paramsMap.put("gameCode", gamesLogin.getGameId()); + paramsMap.put("returnUrl", gamesLogin.getHomeUrl()); + paramsMap.put("ingress", PlatformHomeType.WEB.getValue().equals(gamesLogin.getPlatform()) ? IngressType.PC_WEB.getValue() : IngressType.MOBILE_WEB.getValue()); + Map headerMap = this.getKey(gamesLogin); + ApiNGResponseDTO apiLoginResponseDTOApiNGResponseDTO = ngClient.loginWithoutRedirect(paramsMap, headerMap); + if (this.getIsSuccess(apiLoginResponseDTOApiNGResponseDTO.getCode())) { + return apiLoginResponseDTOApiNGResponseDTO.getData().getUrl(); + } else { + throw new BaseException(apiLoginResponseDTOApiNGResponseDTO.getMsg()); + } + } + + + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + @Transactional + @Override + public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) { + List apiGameInfoResponseDTOS = redisCache.getCacheList(CacheConstants.PG_GAMES); + if (!CollectionUtils.isEmpty(apiGameInfoResponseDTOS)) { + return CacheConstants.PG_GAMES; + } + + + log.info("GamesNGServiceImpl [getGameList] 请求参数 {}", gamesBaseRequestDTO); + Map paramsMap = new HashMap<>(); + paramsMap.put("platType", NGPlatforms.PG.getCode()); + Map headerMap = this.getKey(gamesBaseRequestDTO); + ApiNGResponseDTO> gameList = ngClient.getGameList(paramsMap, headerMap); + if (this.getIsSuccess(gameList.getCode())) { + for (ApiGameInfoResponseDTO apiGameInfoResponseDTO : gameList.getData()) { + GamePlatform gamePlatform = GamePlatform.builder() + .platformType(NGGameType.findSystemByCode(apiGameInfoResponseDTO.getGameType())) + .platformCode(GamePlatforms.PG.getCode()) + .build(); + List gamePlatforms = gamePlatformService.selectGamePlatformList(gamePlatform); + //没有此平台就新增一个平台 + if (CollectionUtils.isEmpty(gamePlatforms)) { + gamePlatform.setPlatformName(GamePlatforms.PG.getInfo() + NGGameType.findInfoByCode(apiGameInfoResponseDTO.getGameType())); + 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(apiGameInfoResponseDTO.getGameCode()) + .build(); + List games = gameService.selectGameList(game); + //不存在这个游戏 + if (CollectionUtils.isEmpty(games)) { + game.setGameSourceType(apiGameInfoResponseDTO.getGameType()); + game.setFreespin(Boolean.FALSE); + game.setDemoStatus(Boolean.TRUE); + game.setSortNo(gameService.selectMaxSortNoByPlatformId(gamePlatform.getId()) + 1); + game.setGameName(apiGameInfoResponseDTO.getGameName().get("zh-hans")); + game.setCreateBy(Constants.SYSTEM); + gameService.insertGame(game); + } else { + game = games.get(0); + } + apiGameInfoResponseDTO.setSystemGameId(game.getId()); + + + } + redisCache.deleteObject(CacheConstants.PG_GAMES); + redisCache.setCacheList(CacheConstants.PG_GAMES, gameList.getData()); + redisCache.expire(CacheConstants.PG_GAMES, 5L, TimeUnit.HOURS); + } else { + throw new BaseException(gameList.getMsg()); + } + return CacheConstants.PG_GAMES; + } + + /** + * 按代理id进行交换转账 + * + * @param exchangeTransferMoneyRequestDTO 外汇转账moeny dto + * @return {@link Long } + */ + @Override + @Transactional + public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { + log.info("GamesNGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); + GameSecretKey gameSecretKey = gameSecretKeyService.selectGameSecretKeyById(exchangeTransferMoneyRequestDTO.getGameSecretKeyId()); + Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); + String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PG.getCode(), 32); + 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(gameSecretKey.getSystemCurrency()) + .memberId(member.getId()) + .transactionId(transactionId) + .platformCode(GamePlatforms.PG.getCode()) + .build(); + exchangeMoney.setCreateBy(Constants.SYSTEM); + + //获取余额 + String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? NGTransferType.TRANSFER_IN.getValue() : NGTransferType.TRANSFER_OUT.getValue(); + //获取当前游戏币 + MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() + .accounts(member.getGameAccount()) + .agentId(gameSecretKey.getCode()) + .gameSecretKeyId(gameSecretKey.getId()) + .agentKey(gameSecretKey.getKey()) + .build(); + MemberInfoResponseDTO memberInfo = this.getMemberInfo(gamesBaseRequestDTO); + //判断是不是转出 + if (NGTransferType.TRANSFER_OUT.getValue().equals(type)) { + exchangeTransferMoneyRequestDTO.setAmount(memberInfo.getBalance()); + } + + System.out.print("aa" + transactionId.length()); + Map paramsMap = new HashMap<>(); + paramsMap.put("platType", NGPlatforms.PG.getCode()); + paramsMap.put("playerId", exchangeTransferMoneyRequestDTO.getAccount()); + paramsMap.put("currency", gameSecretKey.getCurrency()); + paramsMap.put("type", type); + paramsMap.put("amount", String.valueOf(exchangeTransferMoneyRequestDTO.getAmount())); + paramsMap.put("orderId", transactionId); + + Map key = this.getKey(exchangeTransferMoneyRequestDTO); + ApiNGResponseDTO apiNGResponseDTO = ngClient.exchangeTransferByAgentId(paramsMap, key); + if (this.getIsSuccess(apiNGResponseDTO.getCode())) { + //更新数据 + exchangeMoney.setBalance(exchangeTransferMoneyRequestDTO.getAmount()); + exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); + gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + ExchangeTransferStatusRequestDTO exchangeTransferStatusRequestDTO=new ExchangeTransferStatusRequestDTO(); + exchangeTransferStatusRequestDTO.setAccount(exchangeTransferMoneyRequestDTO.getAccount()); + exchangeTransferStatusRequestDTO.setCurrency(gameSecretKey.getCurrency()); + exchangeTransferStatusRequestDTO.setOrderId(transactionId); + exchangeTransferStatusRequestDTO.setAgentId(exchangeTransferMoneyRequestDTO.getAgentId()); + exchangeTransferStatusRequestDTO.setAgentKey(exchangeTransferMoneyRequestDTO.getAgentKey()); + exchangeTransferStatusRequestDTO.setGameSecretKeyId(exchangeTransferMoneyRequestDTO.getGameSecretKeyId()); + this.exchangeTransferStatus(exchangeTransferStatusRequestDTO); + } else { + log.error("GamesPGServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{},错误信息{}", apiNGResponseDTO.getCode(), apiNGResponseDTO.getMsg()); + throw new BaseException(apiNGResponseDTO.getMsg()); + } + return exchangeMoney.getId(); + } + + /** + * 汇兑转移状态 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { + + + Map paramsMap = new HashMap<>(); + paramsMap.put("playerId", exchangeTransferMoneyRequestDTO.getAccount()); + paramsMap.put("currency", exchangeTransferMoneyRequestDTO.getCurrency()); + paramsMap.put("orderId", exchangeTransferMoneyRequestDTO.getOrderId()); + Map key = this.getKey(exchangeTransferMoneyRequestDTO); + ApiNGResponseDTO apiNGResponseDTO = ngClient.exchangeTransferStatus(paramsMap, key); + if (this.getIsSuccess(apiNGResponseDTO.getCode())) { + ApiExchangeTransferStatusResponseDTO apiNGResponseDTOData = apiNGResponseDTO.getData(); + List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .platformCode(GamePlatforms.PG.getCode()) + .transactionId(exchangeTransferMoneyRequestDTO.getOrderId()) + .build() + ); + + for (GameExchangeMoney exchangeMoney : gameExchangeMonies) { + //更新数据 + exchangeMoney.setBalance(apiNGResponseDTOData.getAmount().abs()); + exchangeMoney.setCoinBefore(NumberUtil.add(apiNGResponseDTOData.getAmount(), apiNGResponseDTOData.getAfterBalance())); + exchangeMoney.setCoinAfter(apiNGResponseDTOData.getAfterBalance()); + exchangeMoney.setCurrencyBefore(exchangeMoney.getCoinBefore()); + exchangeMoney.setCurrencyAfter(exchangeMoney.getCoinAfter()); + exchangeMoney.setStatus(apiNGResponseDTOData.getStatus()); + gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney); + } + return Boolean.TRUE; + } else { + log.error("GamesPGServiceImpl [exchangeTransferStatus]错误代码{},错误信息{}", apiNGResponseDTO.getCode(), apiNGResponseDTO.getMsg()); + return Boolean.FALSE; + } + + + } + + + /** + * 按时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) { + + return null; + } + + /** + * 赠送免费局数 + * + * @param createFreeSpinRequest 创建自由旋转请求 + * @return {@link Boolean } + */ + @Override + public Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest) { + + + return null; + } + + /** + * 获取游戏详细信息 + * + * @param getGameDetailRequestDTO 获取游戏详细信息请求dto + * @return {@link GetGameDetailResponseDTO } + */ + @Override + public GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO) { + + return null; + } + + /** + * 强制会员从游戏注销 + * + * @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) { + + return null; + } + + /** + * 免费游戏玩家使用的纪录 + * + * @param getFreeSpinDashflowRequestDTO 获取自由旋转dashflow请求dto + * @return {@link List }<{@link GameFreeRecord }> + */ + @Override + public List getFreeSpinDashflow(GetFreeSpinDashflowRequestDTO getFreeSpinDashflowRequestDTO) { + + + return Collections.emptyList(); + } + + /** + * 取消赠送免费局数 + * + * @param cancelFreeSpinRequestDTO 取消免费旋转请求 + * @return {@link Boolean } + */ + @Override + public Boolean cancelFreeSpin(CancelFreeSpinRequestDTO cancelFreeSpinRequestDTO) { + + return null; + } + + + /** + * 数据构建 + * + * @param gamesDataBuildDTO 数据 + * @return {@link GameBettingDetails } + */ + @Override + public GameBettingDetails dataBuild(GamesDataBuildDTO gamesDataBuildDTO) { + + return null; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferStatusRequestDTO.java b/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferStatusRequestDTO.java new file mode 100644 index 0000000..353c3fd --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferStatusRequestDTO.java @@ -0,0 +1,33 @@ +package com.ff.game.api.request; + +import lombok.Data; + +/** + * 兑换转账状态请求dto + * + * @author shi + * @date 2025/03/12 + */ +@Data +public class ExchangeTransferStatusRequestDTO extends GamesBaseRequestDTO { + + + + + /** + * 账户 + */ + private String account; + + /** + * 货币 + */ + private String currency; + + /** + * 订单ID + */ + private String orderId; + + +} diff --git a/ff-game/src/main/java/com/ff/game/api/request/GamesBaseRequestDTO.java b/ff-game/src/main/java/com/ff/game/api/request/GamesBaseRequestDTO.java index e5025ff..2751f06 100644 --- a/ff-game/src/main/java/com/ff/game/api/request/GamesBaseRequestDTO.java +++ b/ff-game/src/main/java/com/ff/game/api/request/GamesBaseRequestDTO.java @@ -34,4 +34,12 @@ public class GamesBaseRequestDTO implements Serializable { * 查询 */ private String query; + + + /** + * 游戏密钥id + */ + private Long gameSecretKeyId; + + } diff --git a/ff-game/src/main/java/com/ff/game/api/request/GamesLogin.java b/ff-game/src/main/java/com/ff/game/api/request/GamesLogin.java index 061450d..da7249c 100644 --- a/ff-game/src/main/java/com/ff/game/api/request/GamesLogin.java +++ b/ff-game/src/main/java/com/ff/game/api/request/GamesLogin.java @@ -24,7 +24,7 @@ public class GamesLogin extends GamesBaseRequestDTO{ /** * 游戏唯一识别值(同等 GameList 各游戏的 GameId) */ - private Integer gameId; + private String gameId; /** * UI 语系, 请参考 附录 – 语系参数 */ @@ -41,4 +41,9 @@ public class GamesLogin extends GamesBaseRequestDTO{ * 不列入 md5 加密, 带入 1 即关闭全屏幕模式 */ private Integer disableFullScreen; + + /** + * 游戏类型 + */ + private Integer gameType; } diff --git a/ff-game/src/main/java/com/ff/game/api/request/KickMemberAllDTO.java b/ff-game/src/main/java/com/ff/game/api/request/KickMemberAllDTO.java index 158621d..6a0ee14 100644 --- a/ff-game/src/main/java/com/ff/game/api/request/KickMemberAllDTO.java +++ b/ff-game/src/main/java/com/ff/game/api/request/KickMemberAllDTO.java @@ -23,6 +23,6 @@ public class KickMemberAllDTO extends GamesBaseRequestDTO { /** * 游戏id */ - private Integer gameId; + private String gameId; } diff --git a/ff-game/src/main/java/com/ff/game/api/request/MemberInfoResponseDTO.java b/ff-game/src/main/java/com/ff/game/api/request/MemberInfoResponseDTO.java index 4d5ec47..306f62e 100644 --- a/ff-game/src/main/java/com/ff/game/api/request/MemberInfoResponseDTO.java +++ b/ff-game/src/main/java/com/ff/game/api/request/MemberInfoResponseDTO.java @@ -34,6 +34,7 @@ public class MemberInfoResponseDTO { * 1: 在线 * 2: 脱机 * 3: 账号不存在 + * 4:未知 */ private Integer status; } diff --git a/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java index 752d35f..5f18f10 100644 --- a/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java @@ -5,10 +5,7 @@ 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.ErrorCode; -import com.ff.base.enums.GamePlatforms; -import com.ff.base.enums.GameStatus; -import com.ff.base.enums.XKGameType; +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; @@ -105,8 +102,7 @@ public class GamesXKServiceImpl implements IGamesService { * @param gamesBaseRequestDTO 游戏请求dto * @return {@link String } */ - @Override - public String getKey(GamesBaseRequestDTO gamesBaseRequestDTO) { + private String getKey(GamesBaseRequestDTO gamesBaseRequestDTO) { Random random = new Random(); //取出对应的key跟密钥跟请求参数 String agentKey = gamesBaseRequestDTO.getAgentKey(); @@ -142,10 +138,10 @@ public class GamesXKServiceImpl implements IGamesService { params.put("key", key); XKCreateMemberResponseDTO xkCreateMemberResponseDTO = xkClient.createMember(params); int errorCode = xkCreateMemberResponseDTO.getCode(); - if (0 == errorCode){ + if (0 == errorCode) { return Boolean.TRUE; } - if (101 == errorCode){ + if (101 == errorCode) { throw new ApiException(ErrorCode.GAME_ACCOUNT_CREATION_FAILED.getCode()); } //判断是否获取成功 @@ -198,7 +194,7 @@ public class GamesXKServiceImpl implements IGamesService { Map params = new LinkedHashMap<>(); params.put("account", gamesLogin.getAccount()); - params.put("gameId", gamesLogin.getGameId()); + params.put("gameId", Integer.valueOf(gamesLogin.getGameId())); params.put("lang", gamesLogin.getLang()); params.put("agentId", gamesLogin.getAgentId()); String query = JsonUtil.mapToQueryString(params); @@ -262,7 +258,7 @@ public class GamesXKServiceImpl implements IGamesService { } Game game = Game.builder() .platformId(gamePlatform.getId()) - .gameCode(gamesDataDTO.getGameId()) + .gameCode(String.valueOf(gamesDataDTO.getGameId())) .build(); List games = gameService.selectGameList(game); //不存在这个游戏 @@ -343,6 +339,8 @@ public class GamesXKServiceImpl implements IGamesService { //判断是否转移成功 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()); @@ -359,6 +357,17 @@ public class GamesXKServiceImpl implements IGamesService { return exchangeMoney.getId(); } + /** + * 汇兑转移状态 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { + return Boolean.TRUE; + } + /** * 按时间获取投注记录 diff --git a/ff-game/src/main/java/com/ff/game/domain/Game.java b/ff-game/src/main/java/com/ff/game/domain/Game.java index 68213cb..5761265 100644 --- a/ff-game/src/main/java/com/ff/game/domain/Game.java +++ b/ff-game/src/main/java/com/ff/game/domain/Game.java @@ -38,7 +38,12 @@ public class Game extends BaseEntity /** 游戏第三方id */ @Excel(name = "游戏第三方id") - private Integer gameCode; + private String gameCode; + + /** + * 支持的终端类型 1:电脑网页、2:手机网页、3:电脑/手机网页 + */ + private Integer ingress; /** 第三方来源分类 */ @Excel(name = "第三方来源分类") diff --git a/ff-game/src/main/java/com/ff/game/domain/GameExchangeMoney.java b/ff-game/src/main/java/com/ff/game/domain/GameExchangeMoney.java index a02b518..a3d968b 100644 --- a/ff-game/src/main/java/com/ff/game/domain/GameExchangeMoney.java +++ b/ff-game/src/main/java/com/ff/game/domain/GameExchangeMoney.java @@ -85,7 +85,7 @@ public class GameExchangeMoney extends BaseEntity @Excel(name = "转出类型 1游戏商转入到用户全部转出 2 用户转移到游戏商 3 游戏商转移额度到平台商") private Integer exchangeType; - /** 状态 1 成功 2失败 */ + /** 状态,0:进行中、1:成功、2:失败 */ @Excel(name = "状态 1 成功 2失败") private Integer status; diff --git a/ff-game/src/main/java/com/ff/game/domain/GameSecretKey.java b/ff-game/src/main/java/com/ff/game/domain/GameSecretKey.java index e3784f2..01f4744 100644 --- a/ff-game/src/main/java/com/ff/game/domain/GameSecretKey.java +++ b/ff-game/src/main/java/com/ff/game/domain/GameSecretKey.java @@ -39,9 +39,15 @@ public class GameSecretKey extends BaseEntity @Excel(name = "密钥") private String key; - /** 系统代码 */ - @Excel(name = "系统代码") - private String systemCode; + + /** + * 货币 + */ + private String currency; + + /** 系统币种 */ + @Excel(name = "系统币种") + private String systemCurrency; /** 语言 */ @Excel(name = "语言") diff --git a/ff-game/src/main/java/com/ff/game/mapper/GameSecretKeyMapper.java b/ff-game/src/main/java/com/ff/game/mapper/GameSecretKeyMapper.java index e317992..7fe1b1b 100644 --- a/ff-game/src/main/java/com/ff/game/mapper/GameSecretKeyMapper.java +++ b/ff-game/src/main/java/com/ff/game/mapper/GameSecretKeyMapper.java @@ -77,7 +77,7 @@ public interface GameSecretKeyMapper * @param systemCode 系统代码 * @return {@link TenantSecretKey } */ - GameSecretKey findSecretKeyByPlatformAndSystemCode(@Param("platform") String platform, @Param("systemCode") String systemCode); + GameSecretKey findSecretKeyByPlatformAndSystemCurrency(@Param("platform") String platform, @Param("systemCurrency") String systemCode); /** * 按平台和系统查找lang代码 diff --git a/ff-game/src/main/java/com/ff/game/service/IGameExchangeMoneyService.java b/ff-game/src/main/java/com/ff/game/service/IGameExchangeMoneyService.java index eb8ab59..111afbe 100644 --- a/ff-game/src/main/java/com/ff/game/service/IGameExchangeMoneyService.java +++ b/ff-game/src/main/java/com/ff/game/service/IGameExchangeMoneyService.java @@ -46,6 +46,16 @@ public interface IGameExchangeMoneyService */ int insertGameExchangeMoney(GameExchangeMoney gameExchangeMoney); + + /** + * 获取交易id + * + * @param prefix 前缀 + * @param length 长 + * @return {@link String } + */ + String getTransactionId(String prefix, int length ); + /** * 修改会员金额转移记录 * diff --git a/ff-game/src/main/java/com/ff/game/service/IGameSecretKeyService.java b/ff-game/src/main/java/com/ff/game/service/IGameSecretKeyService.java index 0b9e1f9..740789d 100644 --- a/ff-game/src/main/java/com/ff/game/service/IGameSecretKeyService.java +++ b/ff-game/src/main/java/com/ff/game/service/IGameSecretKeyService.java @@ -78,7 +78,7 @@ public interface IGameSecretKeyService * @param systemCode 系统代码 * @return {@link GameSecretKey } */ - GameSecretKey findSecretKeyByPlatformAndSystemCode(String platform, String systemCode); + GameSecretKey findSecretKeyByPlatformAndSystemCurrency(String platform, String systemCode); /** diff --git a/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java b/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java index 0ce564c..9018a3f 100644 --- a/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java @@ -4,13 +4,16 @@ import java.util.Collections; import java.util.List; import cn.hutool.core.util.IdUtil; +import com.ff.base.enums.GamePlatforms; import com.ff.base.utils.DateUtils; +import com.ff.base.utils.StringUtils; import com.ff.game.dto.GameExchangeMoneyDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ff.game.mapper.GameExchangeMoneyMapper; import com.ff.game.domain.GameExchangeMoney; import com.ff.game.service.IGameExchangeMoneyService; +import org.springframework.util.CollectionUtils; /** * 会员金额转移记录Service业务层处理 @@ -67,6 +70,33 @@ public class GameExchangeMoneyServiceImpl implements IGameExchangeMoneyService return gameExchangeMoneyMapper.insertGameExchangeMoney(gameExchangeMoney); } + /** + * 获取交易id + * + * @param prefix 前缀 + * @param length 长 + * @return {@link String } + */ + @Override + public synchronized String getTransactionId(String prefix, int length) { + String transactionId = StringUtils.generateOrderId(prefix,length); + List gameExchangeMonies = this.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .transactionId(transactionId) + .build() + ); + while (!CollectionUtils.isEmpty(gameExchangeMonies)){ + transactionId = StringUtils.generateOrderId(prefix,length); + gameExchangeMonies = this.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .transactionId(transactionId) + .build() + ); + } + + return transactionId; + } + /** * 修改会员金额转移记录 * diff --git a/ff-game/src/main/java/com/ff/game/service/impl/GameSecretKeyServiceImpl.java b/ff-game/src/main/java/com/ff/game/service/impl/GameSecretKeyServiceImpl.java index 396ca36..7a9f65b 100644 --- a/ff-game/src/main/java/com/ff/game/service/impl/GameSecretKeyServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/service/impl/GameSecretKeyServiceImpl.java @@ -118,8 +118,8 @@ public class GameSecretKeyServiceImpl implements IGameSecretKeyService * @return {@link GameSecretKey } */ @Override - public GameSecretKey findSecretKeyByPlatformAndSystemCode(String platform, String systemCode) { - return gameSecretKeyMapper.findSecretKeyByPlatformAndSystemCode(platform,systemCode); + public GameSecretKey findSecretKeyByPlatformAndSystemCurrency(String platform, String systemCode) { + return gameSecretKeyMapper.findSecretKeyByPlatformAndSystemCurrency(platform,systemCode); } /** diff --git a/ff-game/src/main/java/com/ff/system/SysLoginController.java b/ff-game/src/main/java/com/ff/system/SysLoginController.java index 75d4044..848d244 100644 --- a/ff-game/src/main/java/com/ff/system/SysLoginController.java +++ b/ff-game/src/main/java/com/ff/system/SysLoginController.java @@ -67,7 +67,7 @@ public class SysLoginController { // 生成令牌 String token = ""; // 验证码校验 - // loginService.validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid()); + loginService.validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid()); // 登录前置校验 loginService.loginPreCheck(loginBody.getUsername(), loginBody.getPassword()); if (LoginType.TENANT.getValue().equals(loginBody.getLoginType())) { diff --git a/ff-game/src/main/resources/mapper/game/GameMapper.xml b/ff-game/src/main/resources/mapper/game/GameMapper.xml index d9fcd50..2706ef0 100644 --- a/ff-game/src/main/resources/mapper/game/GameMapper.xml +++ b/ff-game/src/main/resources/mapper/game/GameMapper.xml @@ -9,6 +9,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -21,15 +22,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, sort_no, platform_id, game_code, game_source_type, game_name, freespin, demo_status, stop_status, create_by, create_time, update_by, update_time from ff_game + select id, sort_no, platform_id, game_code,ingress, game_source_type, game_name, freespin, demo_status, stop_status, create_by, create_time, update_by, update_time from ff_game + + + and sort_no = #{sortNo} and platform_id = #{platformId} and game_code = #{gameCode} + and ingress = #{ingress} and game_source_type = #{gameSourceType} and game_name like concat('%', #{gameName}, '%') and freespin = #{freespin} diff --git a/ff-game/src/main/resources/mapper/game/GameSecretKeyMapper.xml b/ff-game/src/main/resources/mapper/game/GameSecretKeyMapper.xml index 41c1082..14be4b0 100644 --- a/ff-game/src/main/resources/mapper/game/GameSecretKeyMapper.xml +++ b/ff-game/src/main/resources/mapper/game/GameSecretKeyMapper.xml @@ -9,7 +9,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - + + @@ -20,16 +21,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, platform, code, `key`, system_code, lang, system_lang_code, info, create_by, create_time, update_by, update_time from ff_game_secret_key + select id, platform, code,currency, `key`, system_currency, lang, system_lang_code, info, create_by, create_time, update_by, update_time from ff_game_secret_key - SELECT system_code + SELECT system_currency FROM ff_game_secret_key WHERE code = #{code} and platform = #{platform} - - where platform = #{platform} and system_code = #{systemCode} + where platform = #{platform} and system_currency = #{systemCurrency}