From 72810d4d0e644fe1d6199b36fc575582e95336aa Mon Sep 17 00:00:00 2001 From: cengy Date: Tue, 8 Apr 2025 13:33:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(fb):=20=E6=96=B0=E5=A2=9E=20FB=20=E4=BD=93?= =?UTF-8?q?=E8=82=B2=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 - 添加 FB 体育相关的数据结构和接口定义 - 实现 FB 体育平台的会员创建、资金转账、获取会员信息等功能 - 集成 FB 体育平台的 URL 获取和登录逻辑 - 为 FB 体育平台添加错误码定义 -优化游戏列表获取逻辑,支持 FB 体育游戏数据同步 --- .../com/ff/base/constant/CacheConstants.java | 4 + .../java/com/ff/base/enums/ErrorCode.java | 10 +- .../java/com/ff/base/enums/GamePlatforms.java | 5 +- .../ff/api/controller/ApiGameController.java | 3 - .../impl/TenantGameQuotaServiceImpl.java | 32 +- .../meitian/impl/MeiTianGameServiceImpl.java | 40 +- .../api/request/MemberInfoRequestDTO.java | 4 +- .../ff/sports/api/fb/address/FbAddress.java | 29 - ff-game/src/main/java/com/ff/sports/fb/A.java | 7 - .../ff/sports/fb/address/FBSportsAddress.java | 30 + .../ff/sports/fb/client/FBSportsClient.java | 77 +++ .../ff/sports/fb/dto/CreateUserRequest.java | 30 + .../ff/sports/fb/dto/CreateUserResponse.java | 19 + .../main/java/com/ff/sports/fb/dto/Enums.java | 9 + .../sports/fb/dto/GetMemberInfoRequest.java | 27 + .../sports/fb/dto/GetMemberInfoResponse.java | 38 ++ .../com/ff/sports/fb/dto/GetUrlRequest.java | 17 + .../com/ff/sports/fb/dto/GetUrlResponse.java | 33 + .../ff/sports/fb/dto/OrderFilesRequest.java | 33 + .../ff/sports/fb/dto/OrderFilesResponse.java | 27 + .../ff/sports/fb/dto/OrderInfoRequest.java | 26 + .../ff/sports/fb/dto/OrderInfoResponse.java | 115 ++++ .../sports/fb/dto/TransferDetailRequest.java | 39 ++ .../sports/fb/dto/TransferDetailResponse.java | 39 ++ .../ff/sports/fb/dto/TransferInRequest.java | 46 ++ .../ff/sports/fb/dto/TransferInResponse.java | 20 + .../ff/sports/fb/dto/TransferOutRequest.java | 46 ++ .../ff/sports/fb/dto/TransferOutResponse.java | 20 + .../sports/fb/impl/FBSportsServiceImpl.java | 618 ++++++++++++++++++ .../com/ff/utils/CalculateDateDaysAgo.java | 25 + .../com/ff/utils/SortByAttributeNameASC.java | 40 ++ .../com/ff/utils/TimestampFromString.java | 23 + .../main/resources/mapper/game/GameMapper.xml | 54 +- 33 files changed, 1450 insertions(+), 135 deletions(-) delete mode 100644 ff-game/src/main/java/com/ff/sports/api/fb/address/FbAddress.java delete mode 100644 ff-game/src/main/java/com/ff/sports/fb/A.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/address/FBSportsAddress.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/client/FBSportsClient.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/Enums.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/TransferInRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/TransferInResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutRequest.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutResponse.java create mode 100644 ff-game/src/main/java/com/ff/sports/fb/impl/FBSportsServiceImpl.java create mode 100644 ff-game/src/main/java/com/ff/utils/CalculateDateDaysAgo.java create mode 100644 ff-game/src/main/java/com/ff/utils/SortByAttributeNameASC.java create mode 100644 ff-game/src/main/java/com/ff/utils/TimestampFromString.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 1e5c620..8df3d35 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 @@ -84,6 +84,10 @@ public class CacheConstants { * dg游戏 */ public static final String DG_GAMES = "dg_games:"; + /** + * fb体育 + */ + public static final String FB_Sports = "fp_sports:"; /** * pg游戏投注货币 */ 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 ddb5bb7..29e6031 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,8 +20,8 @@ public enum ErrorCode { CURRENCY_NOT_EXIST(1004, "游戏平台不支持的货币"), GAME_NOT_EXIST(1005, "游戏不存在"), CURRENCY_EXCHANGE(1006, "不支持币种的汇率"), - FREQUENT_INTERFACE_REQUESTS (1007, "接口请求频繁"), - BALANCE_TRANSFER_FAILED (1008, "余额转移失败"), + FREQUENT_INTERFACE_REQUESTS(1007, "接口请求频繁"), + BALANCE_TRANSFER_FAILED(1008, "余额转移失败"), LANG_NOT_EXIST(1009, "游戏平台不支持的语言"), ORDER_NOT_EXIST(1010, "订单不存在"), PLAYERS_ARE_PLAYING(1011, "玩家游玩中"), @@ -30,6 +30,12 @@ public enum ErrorCode { ACCOUNT_NOT_ONLINE(1014, "账号不在线"), FREQUENT_BALANCE_TRANSFER(1015, "当前游戏账号余额转移频繁"), PLATFORM_NOT_METHODS(1016, "游戏平台不支持的方法"), + Create_Member_Failure(1017, "创建会员失败"), + Transfer_In_Failure(1018, "转入失败"), + Transfer_Out_Failure(1019, "转出失败"), + Get_Member_Info_Failure(1020, "获取会员信息失败"), + Transfer_Not_Exist(1021, "转帐操作不存在"), + Get_Url_Failure(1022, "获取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 5689a02..a952382 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 @@ -13,8 +13,9 @@ public enum GamePlatforms { DG("DG", "DG"), MT("MT", "美天棋牌"), AE("AE", "AE"), - KM("KM", "KM") - ; + KM("KM", "KM"), + + FBSports("FBSports", "FB体育"); private final String code; private final String info; 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 76ecf27..18f64c1 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 @@ -75,9 +75,6 @@ public class ApiGameController extends BaseController { @Resource private ITenantGameQuotaService tenantGameQuotaService; - @Resource - private ITenantGameQuotaFlowService tenantGameQuotaFlowService; - @Resource private IGameBettingDetailsService gameBettingDetailsService; 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 4307341..7bafc53 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 @@ -1,42 +1,40 @@ package com.ff.common.service.impl; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.List; -import java.util.Map; - import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.NumberUtil; import com.ff.base.constant.Constants; import com.ff.base.enums.*; import com.ff.base.exception.base.ApiException; import com.ff.base.system.domain.TenantPlatform; +import com.ff.base.system.domain.TenantSecretKey; import com.ff.base.system.service.ITenantPlatformService; +import com.ff.base.system.service.ITenantSecretKeyService; import com.ff.base.utils.DateUtils; import com.ff.base.utils.QuotaUtils; -import com.ff.base.utils.StringUtils; +import com.ff.common.domain.TenantGameQuota; import com.ff.common.domain.TenantGameQuotaFlow; import com.ff.common.domain.TenantQuotaExchange; -import com.ff.base.system.domain.TenantSecretKey; import com.ff.common.dto.BalanceChangesDTO; import com.ff.common.dto.BalanceRealChangesDTO; import com.ff.common.dto.GameBalanceExchange; +import com.ff.common.mapper.TenantGameQuotaMapper; import com.ff.common.service.ITenantGameQuotaFlowService; +import com.ff.common.service.ITenantGameQuotaService; import com.ff.common.service.ITenantQuotaExchangeService; -import com.ff.base.system.service.ITenantSecretKeyService; import com.ff.game.api.IGamesService; import com.ff.game.api.request.MemberInfoRequestDTO; import com.ff.member.domain.Member; import com.ff.member.service.IMemberService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ff.common.mapper.TenantGameQuotaMapper; -import com.ff.common.domain.TenantGameQuota; -import com.ff.common.service.ITenantGameQuotaService; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Map; /** * 租户游戏配额Service业务层处理 @@ -296,14 +294,11 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { ApiException.notNull(tenantPlatform, ErrorCode.PLATFORM_NOT_EXIST.getCode()); - // 获取用户信息 Member member = memberService.selectMemberByAccount(gameBalanceExchange.getAccount(), gameBalanceExchange.getCurrencyCode(), gameBalanceExchange.getPlatformCode()); ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); - - // 检查用户是否存在,否则抛出异常 ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); @@ -332,6 +327,11 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { .agentKey(gameBalanceExchange.getAgentKey()) .build(); balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); + + if (balanceRequestAmount.compareTo(BigDecimal.ZERO) <= 0) { + throw new ApiException(ErrorCode.INSUFFICIENT_PLAYER_BALANCE.getCode()); + } + balanceRequestAmount = NumberUtil.add(balanceRequestAmount, NumberUtil.mul(balanceRequestAmount, NumberUtil.div(tenantPlatform.getUseCost(), Constants.HUNDRED))); // 计算累计转入和转出金额 @@ -393,12 +393,10 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { // 如果是扣账操作,首先处理假额度 String falseTenantQuotaType = QuotaUtils.getFalseTenantQuota(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode()); TenantGameQuota falseTenantQuota = selectTenantGameQuotaByTenantKey(tenantSecretKey.getTenantKey(), falseTenantQuotaType); - balanceRequestAmount = NumberUtil.add(gameBalanceExchange.getAmount(), NumberUtil.mul(gameBalanceExchange.getAmount(), NumberUtil.div(tenantPlatform.getUseCost(), Constants.HUNDRED))); + balanceRequestAmount = NumberUtil.add(gameBalanceExchange.getAmount(), NumberUtil.mul(gameBalanceExchange.getAmount(), NumberUtil.div(tenantPlatform.getUseCost(), Constants.HUNDRED))); if (falseTenantQuota.getBalance().compareTo(BigDecimal.ZERO) > 0) { - - BigDecimal falseQuotaBalance = falseTenantQuota.getBalance(); if (falseQuotaBalance.compareTo(balanceRequestAmount) >= 0) { // 假额度足够扣除本次所需金额 diff --git a/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java index 4741aa6..47af3fa 100644 --- a/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java @@ -24,6 +24,8 @@ import com.ff.game.service.IGameExchangeMoneyService; import com.ff.game.service.IGameService; import com.ff.member.domain.Member; import com.ff.member.service.IMemberService; +import com.ff.utils.CalculateDateDaysAgo; +import com.ff.utils.TimestampFromString; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -36,10 +38,6 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -368,7 +366,7 @@ public class MeiTianGameServiceImpl implements IGamesService { exchangeMoney.setCoinAfter(exchangeMoneyResponse.getBalance()); exchangeMoney.setCurrencyBefore(exchangeMoneyResponse.getBalance().subtract(transAmount)); exchangeMoney.setCurrencyAfter(exchangeMoneyResponse.getBalance()); - exchangeMoney.setStatus(1); // SUCCESS + exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); } else { @@ -396,7 +394,7 @@ public class MeiTianGameServiceImpl implements IGamesService { exchangeMoney.setCoinAfter(exchangeMoneyResponse.getBalance()); exchangeMoney.setCurrencyBefore(exchangeMoneyResponse.getBalance().add(transAmount)); exchangeMoney.setCurrencyAfter(exchangeMoneyResponse.getBalance()); - exchangeMoney.setStatus(1); // SUCCESS + exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); } else { throw new BaseException(MeiTianExchangeMoneyResponseDTO.TransferOut.get(exchangeMoneyResponse.getErrorCode()).getMessage()); @@ -485,7 +483,7 @@ public class MeiTianGameServiceImpl implements IGamesService { boolean doSyncRecordByDate(BetRecordByTimeDTO betRecordByTimeDTO, int daysToSubtract) { - String date = getDateStr(daysToSubtract); + String date = CalculateDateDaysAgo.getStr(daysToSubtract); String configKey = GamePlatforms.MT.getCode() + ":lastSyncDate"; String syncDateStr = sysConfigServiceImpl.selectConfigByKey(configKey); Map syncDateMap = new HashMap<>(); @@ -750,7 +748,7 @@ public class MeiTianGameServiceImpl implements IGamesService { BigDecimal originPayoffAmount = new BigDecimal(dataBean.getIncome()); // 这个值是到手的 int compareResult = originPayoffAmount.compareTo(BigDecimal.ZERO); - long gameTime = getTime(dataBean.getGameDate()); + long gameTime = TimestampFromString.from(dataBean.getGameDate()); Platform platform = gamesDataBuildDTO.getPlatform(); String systemCurrency = platform.getOurCurrency(dataBean.getCurrency()); //数据构造 @@ -782,30 +780,4 @@ public class MeiTianGameServiceImpl implements IGamesService { gameBettingDetails.setCreateTime(DateUtils.getNowDate()); return gameBettingDetails; } - - public long getTime(String date) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - try { - Date parse = simpleDateFormat.parse(date); - return parse.getTime(); - } catch (ParseException e) { - return System.currentTimeMillis(); - } - } - - public LocalDate getDate(int daysToSubtract) { - return LocalDate.now().minusDays(daysToSubtract); // 获取当前日期减去两天 - } - - public String getDateStr(int daysToSubtract) { - // 获取当前日期减去指定天数 - LocalDate date = LocalDate.now().minusDays(daysToSubtract); - - // 定义日期格式 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - - // 返回格式化日期字符串 - return date.format(formatter); - } - } diff --git a/ff-game/src/main/java/com/ff/game/api/request/MemberInfoRequestDTO.java b/ff-game/src/main/java/com/ff/game/api/request/MemberInfoRequestDTO.java index 40a3182..78c20cd 100644 --- a/ff-game/src/main/java/com/ff/game/api/request/MemberInfoRequestDTO.java +++ b/ff-game/src/main/java/com/ff/game/api/request/MemberInfoRequestDTO.java @@ -6,7 +6,7 @@ import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; /** - * 创建成员请求dto + * 查询用户信息 * * @author shi * @date 2024/10/22 @@ -19,7 +19,7 @@ public class MemberInfoRequestDTO extends GamesBaseRequestDTO { /** * 账户 */ - private String accounts; + private String accounts; } diff --git a/ff-game/src/main/java/com/ff/sports/api/fb/address/FbAddress.java b/ff-game/src/main/java/com/ff/sports/api/fb/address/FbAddress.java deleted file mode 100644 index 62ba9ec..0000000 --- a/ff-game/src/main/java/com/ff/sports/api/fb/address/FbAddress.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.ff.sports.api.fb.address; - -import com.dtflys.forest.callback.AddressSource; -import com.dtflys.forest.http.ForestAddress; -import com.dtflys.forest.http.ForestRequest; -import com.ff.base.system.service.ISysConfigService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - - -/** - * @author shi - * @date 2025/02/10 - */ -@Component -public class FbAddress implements AddressSource { - - public static final String API_BASE_URL = "fb.api.base.url"; - @Resource - private ISysConfigService configService; - - - @Override - public ForestAddress getAddress(ForestRequest request) { - String apiBaseUrl = configService.selectConfigByKey(API_BASE_URL); - return new ForestAddress("https", apiBaseUrl, 443, "services"); - } -} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/sports/fb/A.java b/ff-game/src/main/java/com/ff/sports/fb/A.java deleted file mode 100644 index badc18a..0000000 --- a/ff-game/src/main/java/com/ff/sports/fb/A.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ff.sports.fb; - -/** - * @author cengy - */ -public class A { -} diff --git a/ff-game/src/main/java/com/ff/sports/fb/address/FBSportsAddress.java b/ff-game/src/main/java/com/ff/sports/fb/address/FBSportsAddress.java new file mode 100644 index 0000000..a1f47b8 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/address/FBSportsAddress.java @@ -0,0 +1,30 @@ +package com.ff.sports.fb.address; + +import com.dtflys.forest.callback.AddressSource; +import com.dtflys.forest.http.ForestAddress; +import com.dtflys.forest.http.ForestRequest; +import com.ff.base.enums.GamePlatforms; +import com.ff.game.service.IPlatformService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + + +/** + * 文档地址:https://doc.newsportspro.com/apidoc_data.html#%E5%85%A5%E5%8F%82 + * @author shi + * @date 2025/02/10 + */ +@Component +public class FBSportsAddress implements AddressSource { + + @Resource + private IPlatformService platformService; + + @Override + public ForestAddress getAddress(ForestRequest request) { + String apiBaseUrl = platformService.get(GamePlatforms.FBSports.getCode()) + .getUrlInfo().getUrl(); + return new ForestAddress("https", apiBaseUrl, 443, "fb/data"); + } +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/sports/fb/client/FBSportsClient.java b/ff-game/src/main/java/com/ff/sports/fb/client/FBSportsClient.java new file mode 100644 index 0000000..674a4e4 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/client/FBSportsClient.java @@ -0,0 +1,77 @@ +package com.ff.sports.fb.client; + +import com.dtflys.forest.annotation.*; +import com.ff.sports.fb.address.FBSportsAddress; +import com.ff.sports.fb.dto.*; + +/** + * https://doc.newsportspro.com/apidoc_data.html + * + * @author cengy + */ +@Address(source = FBSportsAddress.class) +public interface FBSportsClient { + /** + * 创建投注用户 + * + * @return {@link CreateUserResponse} + */ + @Post(url = "/api/v2/new/user/create") + CreateUserResponse createMember(@JSONBody CreateUserRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + + /** + * 用户金额转入到FB体育平台,支持两位小数,最小0.01,必须是正数 + * + * @param request + * @param sign + * @param timestamp + * @param merchantId + * @return {@link TransferInResponse} + */ + @Post(url = "/api/v2/new/transfer/in") + TransferInResponse transferIn(@JSONBody TransferInRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + + @Post(url = "/api/v2/new/transfer/out") + TransferOutResponse transferOut(@JSONBody TransferOutRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + + @Post(url = "/api/v2/new/user/detail") + GetMemberInfoResponse getMemberInfo(@JSONBody GetMemberInfoRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + + /** + * 查询转账详情,当转入/转出接口遇到异常,可查询某次转账是否成功 + */ + @Post(url = "/api/v2/transfer/detail") + TransferDetailResponse transferDetail(@JSONBody TransferDetailRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + + @Post(url = "/api/v2/service/domain/list") + GetUrlResponse getUrl(@JSONBody GetUrlRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + + /** + * FB体育用拉取订单文件的方式同步订单数据,FB体育每5分钟生成一次订单文件, + * 通过此接口获取某一段时间内的文件ID列表,再通过文件ID获取具体订单数据 + */ + @Post(url = "/api/v2/transfer/detail") + OrderFilesResponse orderFiles(@JSONBody OrderFilesRequest request, + @Header("sign") @Var("sign") String sign, + @Header("timestamp") @Var("timestamp") long timestamp, + @Header("merchantId") @Var("merchantId") String merchantId); + +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserRequest.java new file mode 100644 index 0000000..95c942d --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserRequest.java @@ -0,0 +1,30 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class CreateUserRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String merchantUserId;// 渠道用户id,支持40位字符串,必须唯一 + private List currencyIds = null; // 币种id集合 , see enum: currency + private Integer oddsLevel = null; // 赔率级别,不传则为默认, see enum: user_odds_level_enum + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("currencyIds", currencyIds); + map.put("merchantUserId", merchantUserId); + map.put("oddsLevel", oddsLevel); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserResponse.java new file mode 100644 index 0000000..015abf1 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/CreateUserResponse.java @@ -0,0 +1,19 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class CreateUserResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean success; + private Integer data; + private Integer code; + private String message; +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/Enums.java b/ff-game/src/main/java/com/ff/sports/fb/dto/Enums.java new file mode 100644 index 0000000..cf2bd48 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/Enums.java @@ -0,0 +1,9 @@ +package com.ff.sports.fb.dto; + +/** + * @author cengy + */ +public class Enums { + + +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoRequest.java new file mode 100644 index 0000000..51e7129 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoRequest.java @@ -0,0 +1,27 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class GetMemberInfoRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 渠道用户id,不能为空 + */ + private String merchantUserId; + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("merchantUserId", merchantUserId); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoResponse.java new file mode 100644 index 0000000..0911248 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/GetMemberInfoResponse.java @@ -0,0 +1,38 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @author cengy + */ +@Data +public class GetMemberInfoResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private Boolean success; + private String message; + private MemberInfo data; + private Integer code; + + @Data + public static class MemberInfo implements Serializable{ + private static final long serialVersionUID = 1L; + private String merchantUserId; + private Integer userId; // FB体育用户id + private Integer walletType; // 用户钱包类型 , see enum: wallet_type + private Integer currencyType; // 用户币种类型 , see enum: currency_type + private List wallets; // 钱包集合 + private Integer oddsLevel;// 赔率级别 , see enum: user_odds_level_enum + } + @Data + public static class Wallet implements Serializable{ + private static final long serialVersionUID = 1L; + private Integer currencyType; // 币种类型 , see enum: currency_type + private BigDecimal balance; // 余额 + private Integer currencyId; // 币种id , see enum: currency + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlRequest.java new file mode 100644 index 0000000..15d3213 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlRequest.java @@ -0,0 +1,17 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class GetUrlRequest implements Serializable { + private static final long serialVersionUID = 1L; + + public String toJSON() { + return "{}"; + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlResponse.java new file mode 100644 index 0000000..e0ea5f8 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/GetUrlResponse.java @@ -0,0 +1,33 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author cengy + */ +@Data +public class GetUrlResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private Boolean success; + private String message; + private List data; + private Integer code; + + @Data + public static class UrlDTO implements Serializable { + private static final long serialVersionUID = 1L; + private int type; //域名类型,1:API,2:PUSH,3:H5,4:PC,5:IMAGE , see enum: domain_type_enum + private List domainList; // 域名集合 + } + + @Data + public static class DomainDTO implements Serializable { + private static final long serialVersionUID = 1L; + private String domain; // 域名 + private int weight; // 权限值 + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesRequest.java new file mode 100644 index 0000000..3d3e48b --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesRequest.java @@ -0,0 +1,33 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class OrderFilesRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 开始时间戳,13位数字,不能为null + */ + private Long startTime; + + /** + * 结束时间戳,13位数字,不能为null + */ + private Long endTime; + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("endTime", endTime); + map.put("startTime", startTime); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesResponse.java new file mode 100644 index 0000000..3042774 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderFilesResponse.java @@ -0,0 +1,27 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author cengy + */ +@Data +public class OrderFilesResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private Boolean success; + private String message; + private Integer code; + + private List data; + + @Data + public static class FileId implements Serializable { + private static final long serialVersionUID = 1L; + private Integer fileId; + } + +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoRequest.java new file mode 100644 index 0000000..5b75ecb --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoRequest.java @@ -0,0 +1,26 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class OrderInfoRequest implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 文件Id,需要从/order/file/ids接口获取到 + */ + private Integer fileId; + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("fileId", fileId); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoResponse.java new file mode 100644 index 0000000..fb48ce7 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/OrderInfoResponse.java @@ -0,0 +1,115 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author cengy + */ +@Data +public class OrderInfoResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private Boolean success; + private String message; + private Integer code; + + private List data; + + @Data + public static class OrderDTO implements Serializable { + private static final long serialVersionUID = 1L; + private String id; // 订单号 + private Integer rejectReason; // 拒单原因码 see enum: order_reject_type + private String rejectReasonStr; // 拒单原因 + private String userId; // FB平台用户ID + private String merchantId; // 渠道ID + private String merchantUserId; // 渠道用户ID + private Integer currency; // 币种 see enum: currency + private String exchangeRate; // 汇率快照 + private Integer seriesType; // 关次类型 ,0 单关、1 串关, see enum: series_type + private String betType; // 投注类型 + private Integer allUp; // 总关数 + private Integer allUpAlive; // 存活关数 + private String stakeAmount; // 投注额(本金) + private String liabilityStake; // 名义投注额(名义本金) + private String settleAmount; // 结算派奖金额 + private Integer orderStatus; // 订单状态 see enum: order_status + private Integer payStatus; // 付款状态 + private Integer oddsChange; // 是否接受赔率变更 0不接受,1 接受更好赔率,2接受任意赔率 , see enum: odds_change_enum + private String device; // 设备类型 (pc、h5、mobile) , see enum: plat_form_enum + private String ip; // 投注IP地址 + private String settleTime; // 订单结算时间 + private String createTime; // 订单创建时间 + private String modifyTime; // 订单确认时间 + private String cancelTime; // 订单取消时间 + private String thirdRemark; // 第三方备注 + private String relatedId; // 三方关联ID + private String maxWinAmount; // 最大可赢金额 + private String loseAmount; // 最大赔付金额 + private Integer rollBackCount; // 回滚次数 + private Integer itemCount; // 选项数 + private Integer seriesValue; // 串几关 + private Integer betNum; // 子单数 + private String cashOutTotalStake; // 提前结算总本金 + private String liabilityCashoutStake; // 提前结算名义总本金 + private String cashOutPayoutStake; // 提前结算总派奖额 + private String reserveId; // 预约订单单号 + private Integer cashOutCount; // 提前结算次数 + private String unitStake; // 每单金额 + private Integer reserveVersion; // 预约订单版本号 + private List betList; // 注单集合 + } + + @Data + public static class BetDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private String id; // ID + private String orderId; // 订单ID + private Integer sportId; // 运动ID + private String matchId; // 比赛ID + private String matchName; // 比赛名称 + private Integer period; // 阶段ID + private String marketId; // 玩法ID + private Integer marketType; // 玩法类型 + private Integer optionType; // 投注项类型 + private String optionName; // 选项名称 + private String marketName; // 玩法名称 + private String tournamentId; // 联赛ID + private String tournamentName; // 联赛名称 + private String odds; // 欧式赔率 + private Integer oddsFormat; // 投注时赔率类型 + private String betOdds; // 投注时赔率 + private Integer settleStatus; // 结算状态 + private Integer settleResult; // 结算结果 + private Boolean isInplay; // 是否滚球 + private String remark; // 备注 + private Double p1; // 变量1 (例如:让几个球) + private Double p2; // 变量2 + private Double p3; // 变量3 + private String extendedParameter; // 亚洲让球线 + private String extraInfo; // 当前比分 + private String pendingTime; // 延迟等待时间 + private String betScore; // 下注当时比分 + private Integer cancelReason; // 取消原因 + private String cancelReasonName; // 取消原因文本 + private Integer matchType; // 赛事类型 + private String matchTime; // 开赛时间 + private Integer virtualMatchDay; // 轮次 + private Integer virtualChampId; // 赛季 + private Integer virtualLegOrder; // 淘汰赛回合 + private Integer virtualWeekDay; // 小组赛比赛日 + private Integer virtualBlockId; // 期 + private Integer leaguePhase; // 联赛阶段 + private String maxStake; // 最大投注额 + private String validSettleStakeAmount; // 有效已结算投注额 + private String validSettleAmount; // 有效返还额 + private String cashOutCancelStake; // 提前结算取消总额 + private Integer walletType; // 钱包类型 + private Integer version; // 数据变更标记 + } + +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailRequest.java new file mode 100644 index 0000000..85f678d --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailRequest.java @@ -0,0 +1,39 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class TransferDetailRequest implements Serializable { + + + /** + * 业务id,不能为null + */ + private String businessId; + + /** + * 渠道用户ID,不能为null + */ + private String merchantUserId; + + /** + * 转账类型 , see enum: transfer_type_enum 不能为空 + */ + private String transferType; + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("businessId", businessId); + map.put("merchantUserId", merchantUserId); + map.put("transferType", transferType); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailResponse.java new file mode 100644 index 0000000..614edd0 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferDetailResponse.java @@ -0,0 +1,39 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author cengy + */ +@Data +public class TransferDetailResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private Boolean success; + private String message; + private TransferDetail data; + private Integer code; + + @Data + public static class TransferDetail implements Serializable { + private static final long serialVersionUID = 1L; + + private Integer id; + private Integer userId; + private String merchantUserId; + private String businessId; + // IN 转入 + // OUT 转出 + private String transferType; + private BigDecimal beforeTransferAmount; + private BigDecimal afterTransferAmount; + private Integer status; // 状态 , see enum: transfer_status_enum, 1 Successful 0 Failure + private Long createTime; // 记录创建时间 + private Integer currencyId;// 币种id , see enum: currency + + } + +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/TransferInRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferInRequest.java new file mode 100644 index 0000000..52b4c62 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferInRequest.java @@ -0,0 +1,46 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class TransferInRequest implements Serializable { + + /** + * 转账金额,不能为null + * 必须大於或等於0 + */ + private BigDecimal amount; + + /** + * 业务id,不能为null + */ + private String businessId; + + /** + * 渠道用户ID,不能为null + */ + private String merchantUserId; + + /** + * 币种id,可不传入 + */ + private Integer currencyId; + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("amount", amount); + map.put("businessId", businessId); + map.put("currencyId", currencyId); + map.put("merchantUserId", merchantUserId); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/TransferInResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferInResponse.java new file mode 100644 index 0000000..e5ab6ca --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferInResponse.java @@ -0,0 +1,20 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author cengy + */ +@Data +public class TransferInResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean success; + private BigDecimal data; + private Integer code; + private String message; +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutRequest.java b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutRequest.java new file mode 100644 index 0000000..37fc465 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutRequest.java @@ -0,0 +1,46 @@ +package com.ff.sports.fb.dto; + +import com.alibaba.fastjson2.JSON; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +@Data +public class TransferOutRequest implements Serializable { + + /** + * 转账金额,不能为null + * 必须大於或等於0 + */ + private BigDecimal amount; + + /** + * 业务id,不能为null + */ + private String businessId; + + /** + * 渠道用户ID,不能为null + */ + private String merchantUserId; + + /** + * 币种id,可不传入 + */ + private Integer currencyId; + + public String toJSON() { + Map map = new LinkedHashMap<>(); + map.put("amount", amount); + map.put("businessId", businessId); + map.put("currencyId", currencyId); + map.put("merchantUserId", merchantUserId); + return JSON.toJSONString(map); + } +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutResponse.java b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutResponse.java new file mode 100644 index 0000000..9fb8897 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/dto/TransferOutResponse.java @@ -0,0 +1,20 @@ +package com.ff.sports.fb.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author cengy + */ +@Data +public class TransferOutResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean success; + private BigDecimal data; + private Integer code; + private String message; +} diff --git a/ff-game/src/main/java/com/ff/sports/fb/impl/FBSportsServiceImpl.java b/ff-game/src/main/java/com/ff/sports/fb/impl/FBSportsServiceImpl.java new file mode 100644 index 0000000..cb82873 --- /dev/null +++ b/ff-game/src/main/java/com/ff/sports/fb/impl/FBSportsServiceImpl.java @@ -0,0 +1,618 @@ +package com.ff.sports.fb.impl; + +import cn.hutool.core.lang.generator.SnowflakeGenerator; +import cn.hutool.core.util.IdUtil; +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.utils.DateUtils; +import com.ff.base.utils.sign.Md5Utils; +import com.ff.base.utils.uuid.IdUtils; +import com.ff.game.api.IGamesService; +import com.ff.game.api.meitian.dto.MeiTianBetRecordResponseDTO; +import com.ff.game.api.meitian.dto.MeiTianGameDataDTO; +import com.ff.game.api.request.*; +import com.ff.game.domain.*; +import com.ff.game.service.IGameBettingDetailsService; +import com.ff.game.service.IGameExchangeMoneyService; +import com.ff.game.service.IGameService; +import com.ff.member.domain.Member; +import com.ff.member.service.IMemberService; +import com.ff.sports.fb.client.FBSportsClient; +import com.ff.sports.fb.dto.*; +import com.ff.utils.TimestampFromString; +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.stream.Collectors; + + +/** + * FB体育 + * + * @author shi + * @date 2024/10/21 + */ +@Service("FBSportsService") +@Slf4j +public class FBSportsServiceImpl implements IGamesService { + + @Resource + private RedisCache redisCache; + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + @Resource + private IGameService gameService; + + + @Resource + private IMemberService memberService; + + @Resource + private FBSportsClient fbSportsClient; + + @Resource + private IGameBettingDetailsService gameBettingDetailsService; + + /** + * 获得就是成功 + * + * @param errorCode 错误代码 + * @return {@link Boolean } + */ + private Boolean isSuccess(Integer errorCode) { + return 0 == errorCode; + } + + String getSign(String bodyJsonString, String merchantId, String merchantApiSecret, long requestTimestamp) { + + String stringThatNeedsToBeSigned = bodyJsonString + "." + merchantId + "." + requestTimestamp + "." + merchantApiSecret; + String sign = Md5Utils.md5New(stringThatNeedsToBeSigned); + return sign; + } + + /** + * 创建成员 + * + * @param createMemberRequestDTO 创建成员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) { + + long timestamp = System.currentTimeMillis(); + CreateUserRequest request = new CreateUserRequest(); + request.setMerchantUserId(createMemberRequestDTO.getAccount()); + ArrayList currencyIds = new ArrayList<>(); + currencyIds.add(Integer.parseInt(createMemberRequestDTO.getCurrency())); + request.setCurrencyIds(currencyIds); + String jsonBody = /*SortByAttributeNameASC.get(request)*/ request.toJSON(); + String sign = getSign(jsonBody, + createMemberRequestDTO.getAgentId(), + createMemberRequestDTO.getAgentKey(), + timestamp + ); + + CreateUserResponse response = fbSportsClient.createMember( + request, + sign, + timestamp, createMemberRequestDTO.getAgentId()); + if (isSuccess(response.getCode())) { + log.info("创建会员成功, account:{}->{}", createMemberRequestDTO.getAccount(), response.getData()); + return Boolean.TRUE; + } + + log.error("创建会员失败, errorCode:{}, errorMessage:{}", response.getCode(), response.getMessage()); + throw new ApiException(ErrorCode.Create_Member_Failure.getCode()); + } + + + /** + * 按代理id进行交换转账 + * + * @param requestDTO 外汇转账moeny dto + * @return {@link Long } + */ + @Override + @Transactional + public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO requestDTO) { + + Member member = memberService.selectMemberByGameAccount(requestDTO.getAccount()); + String transactionId = GamePlatforms.FBSports.getCode() + IdUtils.simpleUUID(); + List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .tenantKey(requestDTO.getTenantKey()) + .orderId(requestDTO.getOrderId()) + .build() + ); + Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); +//获取下一个自增id + GameExchangeMoney exchangeMoney = GameExchangeMoney + .builder() + .orderId(requestDTO.getOrderId()) + .tenantKey(requestDTO.getTenantKey()) + .quota(requestDTO.getQuota()) + .balance(requestDTO.getAmount()) + .exchangeType(requestDTO.getTransferType()) + .currencyCode(requestDTO.getSystemCurrency()) + .memberId(member.getId()) + .transactionId(transactionId) + .platformCode(GamePlatforms.FBSports.getCode()) + .build(); + exchangeMoney.setCreateBy(Constants.SYSTEM); + //接口限制限制50字符 + exchangeMoney.setTransactionId(transactionId); + // 转入 + if (requestDTO.getTransferType().equals(TransferType.GAMES.getCode())) { + TransferInRequest request = new TransferInRequest(); + request.setMerchantUserId(requestDTO.getAccount()); + request.setAmount(requestDTO.getAmount()); + request.setBusinessId(requestDTO.getOrderId()); + request.setCurrencyId(Integer.parseInt(requestDTO.getCurrency())); + long timestamp = System.currentTimeMillis(); + String jsonBody = request.toJSON(); + String sign = getSign(jsonBody, + requestDTO.getAgentId(), + requestDTO.getAgentKey(), + timestamp + ); + + TransferInResponse response = fbSportsClient.transferIn( + request, + sign, + timestamp, + requestDTO.getAgentId()); + if (isSuccess(response.getCode())) { + + exchangeMoney.setBalance(response.getData()); + BigDecimal transAmount = requestDTO.getAmount(); + exchangeMoney.setCoinBefore(response.getData().subtract(transAmount)); + exchangeMoney.setCoinAfter(response.getData()); + exchangeMoney.setCurrencyBefore(response.getData().subtract(transAmount)); + exchangeMoney.setCurrencyAfter(response.getData()); + exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS + gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + } else { + throw new ApiException(ErrorCode.Transfer_In_Failure.getCode()); + } + } else { + // 获取第三方钱包余额 + MemberInfoRequestDTO memberInfoRequestDTO = MemberInfoRequestDTO.builder() + .accounts(member.getGameAccount()) + .agentId(requestDTO.getAgentId()) + .agentKey(requestDTO.getAgentKey()) + .build(); + BigDecimal balance = this.getMemberInfo(memberInfoRequestDTO).getBalance(); + + TransferOutRequest request = new TransferOutRequest(); + request.setMerchantUserId(requestDTO.getAccount()); + request.setAmount(/*requestDTO.getAmount()*/ balance); + request.setBusinessId(requestDTO.getOrderId()); + request.setCurrencyId(Integer.parseInt(requestDTO.getCurrency())); + + long timestamp = System.currentTimeMillis(); + String jsonBody = request.toJSON(); + String sign = getSign(jsonBody, + requestDTO.getAgentId(), + requestDTO.getAgentKey(), + timestamp + ); + + TransferOutResponse response = fbSportsClient + .transferOut( + request, + sign, + timestamp, + requestDTO.getAgentId() + ); + + + //判断是否转移成功 + if (this.isSuccess(response.getCode())) { + //更新数据 + exchangeMoney.setBalance(response.getData()); + BigDecimal transAmount = balance; + exchangeMoney.setCoinBefore(response.getData().add(transAmount)); + exchangeMoney.setCoinAfter(response.getData()); + exchangeMoney.setCurrencyBefore(response.getData().add(transAmount)); + exchangeMoney.setCurrencyAfter(response.getData()); + exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS + gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + } else { + throw new ApiException(ErrorCode.Transfer_Out_Failure.getCode()); + } + } + return exchangeMoney.getId(); + } + + /** + * 获取会员信息 + * + * @param requestDTO 会员信息请求dto + * @return {@link MemberInfoResponseDTO } + */ + @Override + public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO requestDTO) { + GetMemberInfoRequest request = new GetMemberInfoRequest(); + request.setMerchantUserId(requestDTO.getAccounts()); + long timestamp = System.currentTimeMillis(); + String jsonBody = request.toJSON(); + String sign = getSign(jsonBody, + requestDTO.getAgentId(), + requestDTO.getAgentKey(), + timestamp + ); + GetMemberInfoResponse response = fbSportsClient.getMemberInfo( + request, + sign, + timestamp, + requestDTO.getAgentId() + ); + //判断是否获取成功 + if (this.isSuccess(response.getCode())) { + BigDecimal balance = new BigDecimal("0.00"); + + for (GetMemberInfoResponse.Wallet wallet : response.getData().getWallets()) { + balance = balance.add(wallet.getBalance()); + } + return MemberInfoResponseDTO.builder() + .status(GameMemberStatus.UNKNOWN.getCode()) + .balance(balance) + .account(requestDTO.getAccounts()) + .build(); + } else { + throw new ApiException(ErrorCode.Get_Member_Info_Failure.getCode()); + } + } + + /** + * 无重定向登录 + * + * @param requestDTO 游戏登录 + * @return {@link String } + */ + @Override + public String loginWithoutRedirect(GamesLogin requestDTO) { + GetUrlRequest request = new GetUrlRequest(); + long timestamp = System.currentTimeMillis(); + String jsonBody = request.toJSON(); + String sign = getSign(jsonBody, + requestDTO.getAgentId(), + requestDTO.getAgentKey(), + timestamp + ); + GetUrlResponse response = fbSportsClient.getUrl( + request, + sign, + timestamp, + requestDTO.getAgentId() + ); + //判断是否获取成功 + if (this.isSuccess(response.getCode())) { + List urlDTOS = new ArrayList<>(); + for (GetUrlResponse.UrlDTO urlDTO : response.getData()) { + if (urlDTO.getType() == 3) { // 3:h5 + urlDTOS.add(urlDTO); + } + } + if (urlDTOS.isEmpty()){ + throw new ApiException(ErrorCode.Get_Url_Failure.getCode()); + } + int randomIndex = new Random().nextInt(urlDTOS.size()); + GetUrlResponse.UrlDTO urlDTO = urlDTOS.get(randomIndex); + Collections.shuffle(urlDTO.getDomainList()); + return urlDTO.getDomainList().get(0).getDomain(); + } + throw new ApiException(ErrorCode.Get_Url_Failure.getCode()); + } + private static final Long GAME_ID = 1904452832756013817L; + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + @Transactional + @Override + public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) { + + Platform platform = gamesBaseRequestDTO.getVendor(); + Game game = gameService.selectGameById(GAME_ID); + //不存在这个游戏 + if (ObjectUtils.isEmpty(game)) { + game = new Game(); + game.setId(IdUtil.getSnowflakeNextId()); + game.setSortNo(1); + //game.setPlatformId(gamePlatform.getId()); + game.setPlatformCode(platform.getPlatformCode()); + game.setPlatformType(PlatformType.GAME_HALL.getCode()); + game.setGameCode("1"); + game.setGameSourceType(String.valueOf(1)); + game.setGameName("FB体育"); + game.setCreateBy(Constants.SYSTEM); + NameInfo nameInfo = new NameInfo(); + nameInfo.setLang("zh-CN"); + nameInfo.setName("FB体育"); + game.setNameInfo(Collections.singletonList(nameInfo)); + gameService.insertGame(game); + } + /*GameName gameName = gameNameService.selectGameNameById(GAME_NAME_ID); + if (ObjectUtils.isEmpty(gameName)) { + gameNameService.insertGameName(GameName.builder() + .id(GAME_NAME_ID) + .gameId(game.getId()) + .gameName(game.getGameName()) + .langCode("zh-CN") + .createBy(Constants.SYSTEM) + .build()); + }*/ + + return CacheConstants.FB_Sports; + } + + /** + * 汇兑转移状态 + * + * @param requestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO requestDTO) { + + GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(requestDTO.getGameExchangeMoneyId()); + if (null == gameExchangeMoney) { + throw new ApiException(ErrorCode.Transfer_Not_Exist.getCode()); + } + if (Objects.equals(gameExchangeMoney.getStatus(), StatusType.SUCCESS.getValue())) { + return Boolean.TRUE; + } + TransferDetailRequest request = new TransferDetailRequest(); + request.setMerchantUserId(requestDTO.getAccount()); + request.setTransferType(Objects.equals(gameExchangeMoney.getExchangeType(), TransferType.GAMES.getCode()) + ? "IN" : "OUT"); + long timestamp = System.currentTimeMillis(); + String jsonBody = request.toJSON(); + String sign = getSign(jsonBody, + requestDTO.getAgentId(), + requestDTO.getAgentKey(), + timestamp + ); + TransferDetailResponse response = fbSportsClient.transferDetail( + request, + sign, + timestamp, + requestDTO.getAgentId() + ); + if (this.isSuccess(response.getCode())) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + + /** + * 按时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) { + return doSyncRecordByRecordID(betRecordByTimeDTO); + } + + boolean doSyncRecordByRecordID(BetRecordByTimeDTO betRecordByTimeDTO) { + + return Boolean.FALSE; + } + + boolean doSyncRecordByDate(BetRecordByTimeDTO betRecordByTimeDTO, int daysToSubtract) { + return Boolean.FALSE; + } + + /** + * 按历史时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO betRecordByTimeDTO) { + doSyncRecordByDate(betRecordByTimeDTO, 0); + doSyncRecordByDate(betRecordByTimeDTO, 1); // yesterday + + return true; + } + + + /** + * 赠送免费局数 + * + * @param createFreeSpinRequest 创建自由旋转请求 + * @return {@link Boolean } + */ + @Override + public Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest) { + throw new BaseException("暂不支持免费局数"); + } + + /** + * 获取游戏详细信息 + * + * @param getGameDetailRequestDTO 获取游戏详细信息请求dto + * @return {@link GetGameDetailResponseDTO } + */ + @Override + public GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO) { + + return null; + } + + /** + * 强制会员从游戏注销 + * + * @param kickMemberRequestDTO 踢会员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean kickMember(KickMemberRequestDTO kickMemberRequestDTO) { + + return Boolean.FALSE; + } + + /** + * 踢成员全部 + * + * @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 gameDemoLoginRequestDTO 游戏演示登录请求dto + * @return {@link GameDemoLoginResponseDTO } + */ + @Override + public GameDemoLoginResponseDTO gameDemoLogin(GameDemoLoginRequestDTO gameDemoLoginRequestDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + + /** + * 批量插入 + * + * @param recordResponse 投注记录 + */ + private void batchInsert(MeiTianBetRecordResponseDTO recordResponse, BetRecordByTimeDTO betRecordByTimeDTO) { + List gameBettingDetails = new ArrayList<>(); + List wagersIds = new ArrayList<>(); + //数据组装 + List dataList = recordResponse.getDataList(); + if (CollectionUtils.isEmpty(dataList)) { + return; + } + + //数据转化 + for (MeiTianBetRecordResponseDTO.DataBean dataBean : dataList) { + GameBettingDetails bettingDetails = this.dataBuild(GamesDataBuildDTO.builder() + .platform(betRecordByTimeDTO.getVendor()) + .data(dataBean).build()); + if (!ObjectUtils.isEmpty(bettingDetails)) { + bettingDetails.setId(IdUtil.getSnowflakeNextId()); + gameBettingDetails.add(bettingDetails); + } + wagersIds.add(dataBean.getRowID()); + } + if (!CollectionUtils.isEmpty(gameBettingDetails)) { + //查询重复数据id + List removeWagersIds = gameBettingDetailsService.selectGameBettingDetailsByWagersId(wagersIds, GamePlatforms.MT.getCode()); + //用steam流清除list中与wagersIds集合相同的数据 + gameBettingDetails = gameBettingDetails.stream() + .filter(detail -> !removeWagersIds.contains(detail.getWagersId())) + .collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(gameBettingDetails)) { + gameBettingDetailsService.batchInsert(gameBettingDetails); + } + } + + } + + /** + * 数据构建 + * + * @param gamesDataBuildDTO 数据 + * @return {@link GameBettingDetails } + */ + @Override + public GameBettingDetails dataBuild(GamesDataBuildDTO gamesDataBuildDTO) { + + //转化类 + MeiTianBetRecordResponseDTO.DataBean dataBean = (MeiTianBetRecordResponseDTO.DataBean) gamesDataBuildDTO.getData(); +// GameSecretKeyCurrencyDTO gameSecretKey = +// gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() +// .currency(dataBean.getCurrency()) +// .platformCode(GamePlatforms.MT.getCode()).build()); + + + Member member = memberService.selectMemberByGameAccount(dataBean.getPlayerName()); + if (ObjectUtils.isEmpty(member)) { + return null; + } + List gameDatas = redisCache.getCacheList(CacheConstants.MeiTian_GAMES); + Map dataDTOMap = gameDatas.stream().collect(Collectors.toMap(MeiTianGameDataDTO::getGameId, e -> e)); + MeiTianGameDataDTO gamesDataDTO = dataDTOMap.get(dataBean.getGameCode()); + BigDecimal originPayoffAmount = new BigDecimal(dataBean.getIncome()); // 这个值是到手的 + + int compareResult = originPayoffAmount.compareTo(BigDecimal.ZERO); + long gameTime = TimestampFromString.from(dataBean.getGameDate()); + Platform platform = gamesDataBuildDTO.getPlatform(); + String systemCurrency = platform.getOurCurrency(dataBean.getCurrency()); + //数据构造 + GameBettingDetails gameBettingDetails = GameBettingDetails.builder() + .tenantKey(member.getTenantKey()) + //保存我们的币种id + .currencyCode(systemCurrency) + .memberId(member.getId()) + .gameCode(dataBean.getGameCode()) + .gameType(MeiTianGameType.findSystemByCode(Integer.parseInt(dataBean.getGameType()))) + .platformCode(GamePlatforms.MT.getCode()) + .gameId(gamesDataDTO.getSystemGameId()) + .gameName(gamesDataDTO.getCnName()) + .gameStatus(compareResult > 0 ? GameStatus.WIN.getCode() : compareResult < 0 ? GameStatus.FAIL.getCode() : GameStatus.FLAT.getCode()) + .gameStatusType(1) // 一般下注 + .gameCurrencyCode(dataBean.getCurrency()) + .account(dataBean.getPlayerName()) + .wagersId(dataBean.getRowID()) + .wagersTime(gameTime) + .betAmount(new BigDecimal(dataBean.getBetAmount())) + .payoffTime(gameTime) + .payoffAmount(originPayoffAmount.abs()) + .settlementTime(gameTime) + .turnover(new BigDecimal(dataBean.getCommissionable())) + .orderNo(dataBean.getRowID()) + .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/utils/CalculateDateDaysAgo.java b/ff-game/src/main/java/com/ff/utils/CalculateDateDaysAgo.java new file mode 100644 index 0000000..dc5363b --- /dev/null +++ b/ff-game/src/main/java/com/ff/utils/CalculateDateDaysAgo.java @@ -0,0 +1,25 @@ +package com.ff.utils; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +/** + * @author cengy + */ +public class CalculateDateDaysAgo { + + public static LocalDate get(int daysToSubtract) { + return LocalDate.now().minusDays(daysToSubtract); + } + + public static String getStr(int daysToSubtract) { + // 获取当前日期减去指定天数 + LocalDate date = get(daysToSubtract); + + // 定义日期格式 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + // 返回格式化日期字符串 + return date.format(formatter); + } +} diff --git a/ff-game/src/main/java/com/ff/utils/SortByAttributeNameASC.java b/ff-game/src/main/java/com/ff/utils/SortByAttributeNameASC.java new file mode 100644 index 0000000..6e351b1 --- /dev/null +++ b/ff-game/src/main/java/com/ff/utils/SortByAttributeNameASC.java @@ -0,0 +1,40 @@ +package com.ff.utils; + +import com.alibaba.fastjson2.JSON; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author cengy + */ +public class SortByAttributeNameASC { + public static String get(Object o) { + // Create a map to store field names and values + Map fieldMap = new LinkedHashMap<>(); + + // Get all fields of the class + Field[] fields = o.getClass().getDeclaredFields(); + + // Sort field names + Arrays.sort(fields, (f1, f2) -> f1.getName().compareTo(f2.getName())); + + // Fill the map with sorted fields and their values + for (Field field : fields) { + field.setAccessible(true); // Make private fields accessible + Object value = null; + try { + value = field.get(o); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + fieldMap.put(field.getName(), value); + } + + + return JSON.toJSONString(fieldMap); + } + +} diff --git a/ff-game/src/main/java/com/ff/utils/TimestampFromString.java b/ff-game/src/main/java/com/ff/utils/TimestampFromString.java new file mode 100644 index 0000000..0280b2c --- /dev/null +++ b/ff-game/src/main/java/com/ff/utils/TimestampFromString.java @@ -0,0 +1,23 @@ +package com.ff.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author cengy + */ +public class TimestampFromString { + + public static final String PATTERN_DATE = "yyyy-MM-dd HH:mm:ss"; + + public static Long from(String date) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(PATTERN_DATE); + try { + Date parse = simpleDateFormat.parse(date); + return parse.getTime(); + } catch (ParseException e) { + return 0L; + } + } +} diff --git a/ff-game/src/main/resources/mapper/game/GameMapper.xml b/ff-game/src/main/resources/mapper/game/GameMapper.xml index 3baffbe..910da1b 100644 --- a/ff-game/src/main/resources/mapper/game/GameMapper.xml +++ b/ff-game/src/main/resources/mapper/game/GameMapper.xml @@ -7,7 +7,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - @@ -16,6 +15,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -23,7 +24,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - 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 + select * from ff_game @@ -33,7 +34,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and sort_no = #{sortNo} - and platform_id = #{platformId} and game_code = #{gameCode} and ingress = #{ingress} and game_source_type = #{gameSourceType} @@ -48,40 +48,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" @@ -112,7 +91,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{id}, #{sortNo}, - #{platformId}, #{gameCode}, #{ingress}, #{gameSourceType}, @@ -131,7 +109,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update ff_game sort_no = #{sortNo}, - platform_id = #{platformId}, game_code = #{gameCode}, ingress = #{ingress}, game_source_type = #{gameSourceType}, @@ -192,8 +169,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" g.ingress, gp.platform_type from ff_game g - inner join ff_game_platform gp on g.platform_id=gp.id - where gp.stop_status=1 and g.stop_status=1 + where g.stop_status=1