From e020b73282f4fbd57cadb7f0e4c18697c09be714 Mon Sep 17 00:00:00 2001 From: shi Date: Thu, 3 Apr 2025 16:27:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(game):=20=E6=B7=BB=E5=8A=A0=20PGT=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 - 新增 PGT 游戏平台的 API接口和实现类 - 添加 PGT 游戏平台的会员账户生成逻辑 - 实现 PGT 游戏平台的余额查询、转账等功能 - 添加 PGT 游戏平台的错误响应和数据模型类 --- .../java/com/ff/base/enums/GamePlatforms.java | 3 +- .../java/com/ff/base/utils/NumberUtils.java | 14 +- .../api/controller/ApiMemberController.java | 2 +- .../com/ff/game/api/km/client/KMClient.java | 7 +- .../api/pgt/address/MyPGTAddressSource.java | 30 + .../com/ff/game/api/pgt/client/PGTClient.java | 132 +++++ .../game/api/pgt/dto/PGTBalanceResponse.java | 62 ++ .../api/pgt/dto/PGTCreateMemberResponse.java | 60 ++ .../api/pgt/dto/PGXBetHistoryResponse.java | 148 +++++ .../ff/game/api/pgt/dto/PGXErrorResponse.java | 26 + .../PGXExchangeTransferStatusResponse.java | 67 +++ .../api/pgt/dto/PGXGameLoginResponse.java | 30 + .../game/api/pgt/dto/PGXMemberResponse.java | 26 + .../api/pgt/dto/PGXPlayerStatusResponse.java | 26 + .../api/pgt/impl/GamesPGTServiceImpl.java | 534 ++++++++++++++++++ .../MySuccessCondition.java} | 4 +- .../com/ff/member/service/IMemberService.java | 4 +- .../service/impl/MemberServiceImpl.java | 12 +- 18 files changed, 1163 insertions(+), 24 deletions(-) create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/address/MyPGTAddressSource.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/client/PGTClient.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTBalanceResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTCreateMemberResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXBetHistoryResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXErrorResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXExchangeTransferStatusResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXGameLoginResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXMemberResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXPlayerStatusResponse.java create mode 100644 ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java rename ff-game/src/main/java/com/ff/game/api/{km/success/MyKMSuccessCondition.java => success/MySuccessCondition.java} (90%) 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 00d2cfd..e2136c8 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,7 +13,8 @@ public enum GamePlatforms { DG("DG", "DG"), MeiTian("MeiTian","美天棋牌"), AE("AE", "AE"), - KM("KM", "KM") + KM("KM", "KM"), + PGT("PGT", "PGT"), ; private final String code; diff --git a/ff-base/src/main/java/com/ff/base/utils/NumberUtils.java b/ff-base/src/main/java/com/ff/base/utils/NumberUtils.java index bfc3134..0ea20e8 100644 --- a/ff-base/src/main/java/com/ff/base/utils/NumberUtils.java +++ b/ff-base/src/main/java/com/ff/base/utils/NumberUtils.java @@ -9,7 +9,6 @@ import java.util.concurrent.ThreadLocalRandom; public class NumberUtils { - /** * 计算比例 * @@ -68,17 +67,13 @@ public class NumberUtils { Random random = new Random(); StringBuilder sb = new StringBuilder(); - // 每位字符可以是字母(A-Z, a-z)或数字(0-9) - for (int i = 0; i parameters, @Header Map headerMap); + + /** + * 获取会员信息 + * + * @param parameters 范围 + * @return {@link PGTBalanceResponse } + */ + @Get("/balance?${parameters}") + PGTBalanceResponse getMemberInfo(@Var("parameters") String parameters, @Header Map headerMap); + + + /** + * 获取会员游戏信息 目前仅支持供应商代号JD. + * + * @param parameters 范围 + * @return {@link PGXPlayerStatusResponse } + */ + @Get("/isPlayerIngame.ashx?${parameters}") + PGXPlayerStatusResponse getMemberPlayInfo(@Var("parameters") String parameters); + + + /** + * 无重定向登录 + * + * @param parameters 范围 + * @return {@link PGXGameLoginResponse } + */ + @Post("/launchGames.aspx?${parameters}") + PGXGameLoginResponse loginWithoutRedirect(@Var("parameters") String parameters); + + + + /** + * 按代理id进行交换转账 + * + * @param parameters 参数 + * @return {@link PGXErrorResponse } + */ + @Post(url = "/makeTransfer.aspx?{parameters}") + PGXErrorResponse exchangeTransferByAgentId(@Var("parameters") String parameters); + + /** + * 标记报告 + * + * @return {@link DGResponse } + */ + @Post(url = "markbyjson.aspx") + DGResponse markReport(@JSONBody Map params); + + + + + /** + * 汇兑转移状态 + * + * @param parameters 范围 + * @return {@link ApiNGResponseDTO }<{@link ApiExchangeTransferStatusResponseDTO }> + */ + @Post(url = "/checkTransaction.ashx?{parameters}") + PGXExchangeTransferStatusResponse exchangeTransferStatus(@Var("parameters") String parameters); + + + + + + /** + * 按时间获取投注记录 + * + * @return {@link PGXBetHistoryResponse } + */ + @Get(url = "/fetchbykey.aspx?{parameters}") + PGXBetHistoryResponse getBetRecordByTime(@Var("parameters") String parameters); + + + + @Get(url = "h/fetchArchieve.aspx?{parameters}") + PGXBetHistoryResponse getBetRecordByHistoryTime(@Var("parameters") String parameters); + + + /** + * 踢出队员 + * + * @param parameters 范围 + * @return {@link JILIKickMemberDTO } + */ + @Post("/kickPlayerFromProduct.ashx?{parameters}") + PGXErrorResponse kickMember(@Var("parameters") String parameters); + + /** + * 踢出所有队员 + * + * @param params 参数 + * @return {@link JILIKickMemberAllDTO } + */ + @Get("/kickMemberAll") + XKKickMemberAllDTO kickMemberAll(@JSONBody Map params); + + +} diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTBalanceResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTBalanceResponse.java new file mode 100644 index 0000000..d60c33e --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTBalanceResponse.java @@ -0,0 +1,62 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * PG平衡响应 + * + * @author shi + * @date 2025/04/03 + */ +@Data +public class PGTBalanceResponse { + + /** + * 每个请求的唯一引用 + */ + @JsonProperty("reqId") + private String reqId; + + /** + * 响应状态,通常为 0 表示成功,其他值表示错误 + */ + @JsonProperty("code") + private int code; + + /** + * 关于响应状态的其他信息 + */ + @JsonProperty("message") + private String message; + + /** + * 获取余额数据 + */ + @JsonProperty("data") + private BalanceData data; + + @Data + public static class BalanceData { + + /** + * 用户名 + */ + @JsonProperty("username") + private String username; + + /** + * 每个 productId 的当前余额 + */ + @JsonProperty("balance") + private BigDecimal balance; + + /** + * 响应状态 + */ + @JsonProperty("status") + private String status; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTCreateMemberResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTCreateMemberResponse.java new file mode 100644 index 0000000..8f7537a --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGTCreateMemberResponse.java @@ -0,0 +1,60 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * pgtcreate成员响应 + * + * @author shi + * @date 2025/04/03 + */ +@Data +public class PGTCreateMemberResponse { + + /** + * 请求的唯一标识符 + */ + @JsonProperty("reqId") + private String reqId; + + /** + * 状态码,0 表示成功,其他值表示错误 + */ + @JsonProperty("code") + private int code; + + /** + * 响应消息,通常用于提供请求处理的结果 + */ + @JsonProperty("message") + private String message; + + /** + * 响应的实际数据 + */ + @JsonProperty("data") + private ResponseData data; + + @Data + public static class ResponseData { + + /** + * 用户名 + */ + @JsonProperty("username") + private String username; + + /** + * 货币类型 + */ + @JsonProperty("currency") + private String currency; + + /** + * 操作状态 + */ + @JsonProperty("status") + private String status; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXBetHistoryResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXBetHistoryResponse.java new file mode 100644 index 0000000..3b98e14 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXBetHistoryResponse.java @@ -0,0 +1,148 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 错误信息与投注历史记录返回结果对象 + * + * @author shi + * @date 2025/03/28 + */ +@Data +public class PGXBetHistoryResponse { + + /** + * 错误码 + */ + @JsonProperty("errCode") + private Integer errCode; + + /** + * 投注历史记录的JSON字符串 (String类型) + */ + @JsonProperty("result") + private String result; + + /** + * 错误信息 (String类型) + */ + @JsonProperty("errMsg") + private String errMsg; + + /** + * AIO投注记录对象 + */ + @Data + public class Result { + + /** + * AIO注单号 (唯一值) (Long类型) + */ + @JsonProperty("id") + private Long id; + + /** + * 供应商注单号 (Long类型) + */ + @JsonProperty("ref_no") + private Long refNo; + + /** + * 供应商代号 (String类型) + */ + @JsonProperty("site") + private String site; + + /** + * 游戏类型代号 (String类型) + */ + @JsonProperty("product") + private String product; + + /** + * 玩家帐号 (String类型) + */ + @JsonProperty("member") + private String member; + + /** + * 游戏代号 (String类型) + */ + @JsonProperty("game_id") + private String gameId; + + /** + * 下注时间 (玩家实际的投注时间) 依据 GMT/UTC +0 时区 + */ + @JsonProperty("start_time") + private Date startTime; + + /** + * 结算时间 (String类型) 依据 GMT/UTC +0 时区 + */ + @JsonProperty("end_time") + private Date endTime; + + /** + * 开赛时间 (String类型) 依据 GMT/UTC +0 时区 + */ + @JsonProperty("match_time") + private String matchTime; + + /** + * 投注明细 (String类型) + */ + @JsonProperty("bet_detail") + private String betDetail; + + /** + * 有效投注金额 (Double类型) + */ + @JsonProperty("turnover") + private BigDecimal turnover; + + /** + * 投注金额 (Double类型) + */ + @JsonProperty("bet") + private BigDecimal bet; + + /** + * 派彩金额 (Double类型) + */ + @JsonProperty("payout") + private BigDecimal payout; + + /** + * 佣金 (Double类型) + */ + @JsonProperty("commission") + private BigDecimal commission; + + /** + * 彩池投注金额 (Double类型) + */ + @JsonProperty("p_share") + private BigDecimal pShare; + + /** + * 彩池派彩金额 (Double类型) + */ + @JsonProperty("p_win") + private BigDecimal pWin; + + /** + * 注单状态 (Int类型) + * 1 (valid bet record 有效注单) + * 0 (running/ongoing match 赛事进行中) + * -1 (invalid bet record 无效注单 e.g. voided 作废, canceled 取消) + */ + @JsonProperty("status") + private int status; + + } +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXErrorResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXErrorResponse.java new file mode 100644 index 0000000..a11da08 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXErrorResponse.java @@ -0,0 +1,26 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 错误响应类 + * + * @author shi + * @date 2025/03/27 + */ +@Data +public class PGXErrorResponse { + + /** 错误码 */ + @JsonProperty("errCode") + private Integer errCode; + + /** 内部参考代码 (字符串类型) */ + @JsonProperty("innerCode") + private String innerCode; + + /** 错误信息 (字符串类型) */ + @JsonProperty("errMsg") + private String errMsg; +} diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXExchangeTransferStatusResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXExchangeTransferStatusResponse.java new file mode 100644 index 0000000..5fab258 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXExchangeTransferStatusResponse.java @@ -0,0 +1,67 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * pgxexchange传输状态响应 + * + * @author shi + * @date 2025/03/28 + */ +@Data +public class PGXExchangeTransferStatusResponse { + + /** 错误码 */ + @JsonProperty("errCode") + private Integer errCode; + + + + /** 错误信息 (字符串类型) */ + @JsonProperty("errMsg") + private String errMsg; + + + /** GSC生成的转账ID (String类型) */ + @JsonProperty("trans_id") + private String transId; + + /** 交易时间,GMT+0 (String类型) */ + @JsonProperty("trans_time") + private String transTime; + + /** 玩家姓名 (String类型) */ + @JsonProperty("username") + private String username; + + /** 交易类型 (String类型),0为存款,1为取款 */ + @JsonProperty("type") + private String type; + + /** 提供商 (String类型) */ + @JsonProperty("provider") + private String provider; + + /** 交易金额 (double类型) */ + @JsonProperty("amount") + private double amount; + + /** 运营商的参考ID (String类型) */ + @JsonProperty("ref_id") + private String refId; + + /** 交易状态 (String类型),SUCCESS 成功 + PROCESSING 进行中,请稍后再确认 + FAILED 失败 */ + @JsonProperty("status") + private String status; + + /** GSC操作员代码 (String类型) */ + @JsonProperty("operator") + private String operator; + + /** 交易备注 (String类型) */ + @JsonProperty("remark") + private String remark; +} diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXGameLoginResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXGameLoginResponse.java new file mode 100644 index 0000000..1b18e65 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXGameLoginResponse.java @@ -0,0 +1,30 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 游戏响应对象 + */ +@Data +public class PGXGameLoginResponse { + + /** + * 错误码 (String类型) + */ + @JsonProperty("errCode") + private Integer errCode; + + /** + * 启动游戏链接 (String类型) + */ + @JsonProperty("gameUrl") + private String gameUrl; + + /** + * 错误信息 (String类型) + */ + @JsonProperty("errMsg") + private String errMsg; + +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXMemberResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXMemberResponse.java new file mode 100644 index 0000000..80c40ce --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXMemberResponse.java @@ -0,0 +1,26 @@ +package com.ff.game.api.pgt.dto; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 响应类,包含错误码、余额和错误信息 + */ +@Data +public class PGXMemberResponse { + + /** 错误码 */ + @JsonProperty("errCode") + private Integer errCode; + + /** 账户余额 (小数类型) */ + @JsonProperty("balance") + private BigDecimal balance; + + /** 错误信息 (字符串类型) */ + @JsonProperty("errMsg") + private String errMsg; +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXPlayerStatusResponse.java b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXPlayerStatusResponse.java new file mode 100644 index 0000000..536becf --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/dto/PGXPlayerStatusResponse.java @@ -0,0 +1,26 @@ +package com.ff.game.api.pgt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 响应类,包含错误码、玩家是否在游戏中状态和错误信息 + * + * @author shi + * @date 2025/03/28 + */ +@Data +public class PGXPlayerStatusResponse { + + /** 错误码 (字符串类型) */ + @JsonProperty("errCode") + private Integer errCode; + + /** 玩家是否在游戏中 (字符串类型) "true" 表示在游戏中,"false" 表示不在游戏中 */ + @JsonProperty("result") + private Boolean result; + + /** 错误信息 (字符串类型) */ + @JsonProperty("errMsg") + private String errMsg; +} \ No newline at end of file diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java new file mode 100644 index 0000000..765c85e --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java @@ -0,0 +1,534 @@ +package com.ff.game.api.pgt.impl; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson2.JSON; +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.JsonUtil; +import com.ff.base.utils.sign.Base64; +import com.ff.config.KeyConfig; +import com.ff.game.api.IGamesService; +import com.ff.game.api.pgt.client.PGTClient; +import com.ff.game.api.pgt.dto.*; +import com.ff.game.api.request.*; +import com.ff.game.domain.*; +import com.ff.game.dto.GameSecretKeyCurrencyDTO; +import com.ff.game.service.*; +import com.ff.member.domain.Member; +import com.ff.member.service.IMemberService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +/** + * pg泰 + * + * @author shi + * @date 2025/03/27 + */ +@Service("PGTService") +@Slf4j +public class GamesPGTServiceImpl implements IGamesService { + + + @Resource + private ISysConfigService configService; + + @Resource + private RedisCache redisCache; + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + + @Resource + private IGamePlatformService gamePlatformService; + + + @Resource + private IGameService gameService; + + + @Resource + private IMemberService memberService; + + @Resource + private IGameFreeRecordService gameFreeRecordService; + @Resource + private IGameSecretKeyService gameSecretKeyService; + + @Resource + private IGameSecretKeyCurrencyService gameSecretKeyCurrencyService; + + @Resource + private PGTClient pgtClient; + + + @Resource + private KeyConfig keyConfig; + + @Resource + private IGameBettingDetailsService gameBettingDetailsService; + + @Resource + private IGameNameService gameNameService; + + + /** + * 获得就是成功 + * + * @param errorCode 错误代码 + * @return {@link Boolean } + */ + private Boolean getIsSuccess(Integer errorCode) { + + return 0 == errorCode; + } + + + /** + * 获取密钥 + * + * @return {@link String } + */ + private Map getKey( GamesBaseRequestDTO gamesBaseRequestDTO) { + Map headerMap=new LinkedHashMap<>(); + String auth = gamesBaseRequestDTO.getAgentId() + ":" + gamesBaseRequestDTO.getAgentKey(); + String encodedAuth = Base64Utils.encodeToString(auth.getBytes()); + headerMap.put("Authorization","Basic "+encodedAuth); + + return headerMap; + } + + + /** + * 创建成员 + * + * @param createMemberRequestDTO 创建成员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) { + log.info("GamesPGTServiceImpl [createMember] 请求参数 {}", createMemberRequestDTO); + Map headerMap = this.getKey(createMemberRequestDTO); + Map params = new LinkedHashMap<>(); + params.put("username", createMemberRequestDTO.getAccount()); + params.put("productId","PGSOFT"); + + PGTCreateMemberResponse member = pgtClient.createMember(params, headerMap); + if (this.getIsSuccess(member.getCode())) { + return Boolean.TRUE; + } + //判断是否获取成功 + return Boolean.FALSE; + } + + + /** + * 获取会员信息 + * + * @param memberInfoRequestDTO 会员信息请求dto + * @return {@link MemberInfoResponseDTO } + */ + @Override + public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO) { + log.info("GamesPGTServiceImpl [getMemberInfo] 请求参数 {}", memberInfoRequestDTO); + Map params = new LinkedHashMap<>(); + params.put("username", memberInfoRequestDTO.getAccounts()); + params.put("productId", "PGSOFT"); + Map headerMap = this.getKey(memberInfoRequestDTO); + PGTBalanceResponse memberInfo = pgtClient.getMemberInfo(JsonUtil.mapToQueryString(params),headerMap); + //判断是否获取成功 + if (this.getIsSuccess(memberInfo.getCode())) { + MemberInfoResponseDTO memberInfoResponseDTO = MemberInfoResponseDTO.builder() + .status(GameMemberStatus.UNKNOWN.getCode()) + .balance(memberInfo.getData().getBalance()) + .account(memberInfoRequestDTO.getAccounts()) + .build(); + return memberInfoResponseDTO; + } else { + throw new BaseException(memberInfo.getMessage()); + } + } + + /** + * 无重定向登录 + * + * @param gamesLogin 游戏登录 + * @return {@link String } + */ + @Override + public String loginWithoutRedirect(GamesLogin gamesLogin) { + log.info("GamesPGXServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin); + GameSecretKey gameSecretKey = gameSecretKeyService.selectGameSecretKeyByCode(gamesLogin.getAgentId()); + Map params = new LinkedHashMap<>(); + params.put("operatorcode", gamesLogin.getAgentId()); + params.put("password", gameSecretKey.getPassword()); + params.put("providercode", gameSecretKey.getProviderCode()); + params.put("type", gamesLogin.getGameType()); + params.put("username", gamesLogin.getAccount()); + Map key = this.getKey(gamesLogin); + params.put("gameid", gamesLogin.getGameId()); + params.put("lang", gamesLogin.getLang()); + params.put("html5", 1); + params.put("signature", key); + PGXGameLoginResponse PGXGameLoginResponse = pgtClient.loginWithoutRedirect(JsonUtil.mapToQueryString(params)); + //判断是否获取成功 + if (this.getIsSuccess(PGXGameLoginResponse.getErrCode())) { + return PGXGameLoginResponse.getGameUrl(); + } else { + throw new BaseException(PGXGameLoginResponse.getErrMsg()); + } + } + + + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + @Transactional + @Override + public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) { + + + return CacheConstants.PGX_GAMES; + } + + /** + * 按代理id进行交换转账 + * + * @param exchangeTransferMoneyRequestDTO 外汇转账moeny dto + * @return {@link Long } + */ + @Override + @Transactional + public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { + log.info("GamesPGXServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); + + GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() + .platformCode(GamePlatforms.PGX.getInfo()) + .code(exchangeTransferMoneyRequestDTO.getAgentId()) + .currency(exchangeTransferMoneyRequestDTO.getCurrency()) + .build()); + + Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); + String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17); + List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) + .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) + .build() + ); + Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + + GameSecretKey gameSecretKey = gameSecretKeyService.selectGameSecretKeyByCode(exchangeTransferMoneyRequestDTO.getAgentId()); + + //获取下一个自增id + GameExchangeMoney exchangeMoney = GameExchangeMoney + .builder() + .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) + .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) + .quota(exchangeTransferMoneyRequestDTO.getQuota()) + .balance(exchangeTransferMoneyRequestDTO.getAmount()) + .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) + .currencyCode(currencyDTO.getSystemCurrency()) + .memberId(member.getId()) + .transactionId(transactionId) + .platformCode(GamePlatforms.PGX.getInfo()) + .build(); + exchangeMoney.setCreateBy(Constants.SYSTEM); + + //获取余额 + String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? PGXTransferType.WITHDRAW.getCode() : PGXTransferType.DEPOSIT.getCode(); + + BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); + BigDecimal amountBefore = BigDecimal.ZERO; + + // 获取第三方钱包余额 + MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() + .accounts(exchangeTransferMoneyRequestDTO.getAccount()) + .agentId(exchangeTransferMoneyRequestDTO.getAgentId()) + .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) + .build(); + + //判断是不是提出 + if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { + + amountBefore = this.getMemberInfo(gamesBaseRequestDTO).getBalance(); + amount = amountBefore; + + } + + + Map paramsMap = new LinkedHashMap<>(); + paramsMap.put("amount", amount); + paramsMap.put("operatorcode", exchangeTransferMoneyRequestDTO.getAgentId()); + paramsMap.put("password", gameSecretKey.getPassword()); + paramsMap.put("providercode", gameSecretKey.getProviderCode()); + paramsMap.put("referenceid", transactionId); + paramsMap.put("type", type); + paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount()); + + + PGXErrorResponse errorResponse = pgtClient.exchangeTransferByAgentId(JsonUtil.mapToQueryString(paramsMap)); + if (this.getIsSuccess(errorResponse.getErrCode())) { + + //更新数据 + exchangeMoney.setBalance(amount); + exchangeMoney.setCoinBefore(amountBefore); + //转后的余额 + BigDecimal coinAfter = this.getMemberInfo(gamesBaseRequestDTO).getBalance(); + + exchangeMoney.setCoinAfter(coinAfter); + exchangeMoney.setCurrencyBefore(exchangeMoney.getCoinBefore()); + exchangeMoney.setCurrencyAfter(exchangeMoney.getCoinAfter()); + exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); + + gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + //确认状态 + ExchangeTransferStatusRequestDTO exchangeTransferStatusRequestDTO = new ExchangeTransferStatusRequestDTO(); + exchangeTransferStatusRequestDTO.setAccount(member.getGameAccount()); + exchangeTransferStatusRequestDTO.setOrderId(exchangeMoney.getTransactionId()); + exchangeTransferStatusRequestDTO.setAgentId(gameSecretKey.getCode()); + exchangeTransferStatusRequestDTO.setAgentKey(gameSecretKey.getKey()); + this.exchangeTransferStatus(exchangeTransferStatusRequestDTO); + } else { + log.error("GamesFCServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{}", errorResponse.getErrCode()); + throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode()); + } + return exchangeMoney.getId(); + } + + /** + * 汇兑转移状态 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public Boolean exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { + log.info("GamesPGXServiceImpl [exchangeTransferStatus] 请求参数 {}", exchangeTransferMoneyRequestDTO); + Map paramsMap = new LinkedHashMap<>(); + paramsMap.put("operatorcode", exchangeTransferMoneyRequestDTO.getAgentId()); + paramsMap.put("referenceid", exchangeTransferMoneyRequestDTO.getOrderId()); + + + PGXExchangeTransferStatusResponse exchangeTransferStatusResponse = pgtClient.exchangeTransferStatus(JsonUtil.mapToQueryString(paramsMap)); + if (this.getIsSuccess(exchangeTransferStatusResponse.getErrCode())) { + List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .platformCode(GamePlatforms.PGX.getInfo()) + .transactionId(exchangeTransferMoneyRequestDTO.getOrderId()) + .build() + ); + + for (GameExchangeMoney exchangeMoney : gameExchangeMonies) { + //更新数据 + exchangeMoney.setStatus(PGXTransactionStatus.findValueByCode(exchangeTransferStatusResponse.getStatus())); + gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney); + } + return Boolean.TRUE; + } else { + log.error("GamesPGXServiceImpl [exchangeTransferStatus]错误代码{},错误信息{}", exchangeTransferStatusResponse.getErrCode(), exchangeTransferStatusResponse.getErrMsg()); + return Boolean.FALSE; + } + } + + + /** + * 按时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link List }<{@link GameBettingDetails }> + */ + @Override + public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) { + //请求参数 + log.info("GamesPGXServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO); + Map paramsMap = new LinkedHashMap<>(); + paramsMap.put("operatorcode", betRecordByTimeDTO.getAgentId()); + + paramsMap.put("versionkey", 0); + PGXBetHistoryResponse betRecordByTime = pgtClient.getBetRecordByTime(JsonUtil.mapToQueryString(paramsMap)); + + if (this.getIsSuccess(betRecordByTime.getErrCode())) { + List results = JSON.parseArray(betRecordByTime.getResult(), PGXBetHistoryResponse.Result.class); + this.batchInsert(results, betRecordByTimeDTO); + return Boolean.TRUE; + } else { + log.error("GamesPGXServiceImpl [getBetRecordByTime] 获取投注记录失败,错误代码{},错误信息{}", betRecordByTime.getErrCode(), betRecordByTime.getErrMsg()); + throw new BaseException(betRecordByTime.getErrMsg()); + } + } + + /** + * 按历史时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO betRecordByTimeDTO) { + //请求参数 + log.info("GamesPGXServiceImpl [getBetRecordByHistoryTime] 请求参数 {}", betRecordByTimeDTO); + Map paramsMap = new LinkedHashMap<>(); + paramsMap.put("operatorcode", betRecordByTimeDTO.getAgentId()); + paramsMap.put("versionkey", 0); + PGXBetHistoryResponse betRecordByTime = pgtClient.getBetRecordByHistoryTime(JsonUtil.mapToQueryString(paramsMap)); + + if (this.getIsSuccess(betRecordByTime.getErrCode())) { + List results = JSON.parseArray(betRecordByTime.getResult(), PGXBetHistoryResponse.Result.class); + this.batchInsert(results, betRecordByTimeDTO); + return Boolean.TRUE; + } else { + log.error("GamesPGXServiceImpl [getBetRecordByHistoryTime] 获取投注记录失败,错误代码{},错误信息{}", betRecordByTime.getErrCode(), betRecordByTime.getErrMsg()); + throw new BaseException(betRecordByTime.getErrMsg()); + } + } + + /** + * 赠送免费局数 + * + * @param createFreeSpinRequest 创建自由旋转请求 + * @return {@link Boolean } + */ + @Override + public Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 获取游戏详细信息 + * + * @param getGameDetailRequestDTO 获取游戏详细信息请求dto + * @return {@link GetGameDetailResponseDTO } + */ + @Override + public GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 强制会员从游戏注销 + * + * @param kickMemberRequestDTO 踢会员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean kickMember(KickMemberRequestDTO kickMemberRequestDTO) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 踢成员全部 + * + * @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 dataBean 数据bean + */ + private void batchInsert(List dataBean, GamesBaseRequestDTO gamesBaseRequestDTO) { + List gameBettingDetails = new ArrayList<>(); + List wagersIds = new ArrayList<>(); + + //数据转化 + for (PGXBetHistoryResponse.Result bean : dataBean) { + GameBettingDetails bettingDetails = this.dataBuild(GamesDataBuildDTO.builder().agentId(gamesBaseRequestDTO.getAgentId()).data(bean).build()); + if (!ObjectUtils.isEmpty(bettingDetails)) { + bettingDetails.setId(IdUtil.getSnowflakeNextId()); + gameBettingDetails.add(bettingDetails); + } + wagersIds.add(String.valueOf(bean.getId())); + } + if (!CollectionUtils.isEmpty(gameBettingDetails)) { + //查询重复数据id + List removeWagersIds = gameBettingDetailsService.selectGameBettingDetailsByWagersId(wagersIds,GamePlatforms.PGX.getInfo()); + //用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) { + //转化类 + + return new GameBettingDetails(); + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/km/success/MyKMSuccessCondition.java b/ff-game/src/main/java/com/ff/game/api/success/MySuccessCondition.java similarity index 90% rename from ff-game/src/main/java/com/ff/game/api/km/success/MyKMSuccessCondition.java rename to ff-game/src/main/java/com/ff/game/api/success/MySuccessCondition.java index 3a29b10..f1c97d2 100644 --- a/ff-game/src/main/java/com/ff/game/api/km/success/MyKMSuccessCondition.java +++ b/ff-game/src/main/java/com/ff/game/api/success/MySuccessCondition.java @@ -1,4 +1,4 @@ -package com.ff.game.api.km.success; +package com.ff.game.api.success; import com.dtflys.forest.callback.SuccessWhen; @@ -11,7 +11,7 @@ import com.dtflys.forest.http.ForestResponse; * @author shi * @date 2025/04/02 */ -public class MyKMSuccessCondition implements SuccessWhen { +public class MySuccessCondition implements SuccessWhen { /** * 请求成功条件 diff --git a/ff-game/src/main/java/com/ff/member/service/IMemberService.java b/ff-game/src/main/java/com/ff/member/service/IMemberService.java index c31748e..6aa977d 100644 --- a/ff-game/src/main/java/com/ff/member/service/IMemberService.java +++ b/ff-game/src/main/java/com/ff/member/service/IMemberService.java @@ -30,9 +30,11 @@ public interface IMemberService /** * 生成会员游戏账号 * + * @param platformCode 平台代码 + * @param tenantSn 租户sn * @return {@link String } */ - String getMemberGameAccount(String platformCode); + String getMemberGameAccount(String platformCode,String tenantSn); /** * 新增会员 diff --git a/ff-game/src/main/java/com/ff/member/service/impl/MemberServiceImpl.java b/ff-game/src/main/java/com/ff/member/service/impl/MemberServiceImpl.java index 971752c..248cd38 100644 --- a/ff-game/src/main/java/com/ff/member/service/impl/MemberServiceImpl.java +++ b/ff-game/src/main/java/com/ff/member/service/impl/MemberServiceImpl.java @@ -53,19 +53,21 @@ public class MemberServiceImpl implements IMemberService { * @return {@link String } */ @Override - public synchronized String getMemberGameAccount(String platformCode) { + public synchronized String getMemberGameAccount(String platformCode,String tenantSn) { String gameAccount = null; if (GamePlatforms.DG.getInfo().equals(platformCode) || GamePlatforms.KM.getInfo().equals(platformCode)) { + tenantSn=tenantSn.toUpperCase(); do { - gameAccount = RandomGeneratorUtils.generateRandomAccountUpper(); + gameAccount = RandomGeneratorUtils.generateRandomAccountUpper()+tenantSn; } while (!ObjectUtils.isEmpty(memberMapper.selectMemberByGameAccount(gameAccount))); - } else if (GamePlatforms.PG.getInfo().equals(platformCode) || GamePlatforms.PGX.getInfo().equals(platformCode)) { + } else if (GamePlatforms.PG.getInfo().equals(platformCode) || GamePlatforms.PGX.getInfo().equals(platformCode) || GamePlatforms.PGT.getInfo().equals(platformCode)) { + tenantSn=tenantSn.toLowerCase(); do { - gameAccount = RandomGeneratorUtils.generateRandomAccountLower(); + gameAccount = RandomGeneratorUtils.generateRandomAccountLower()+tenantSn; } while (!ObjectUtils.isEmpty(memberMapper.selectMemberByGameAccount(gameAccount))); } else { do { - gameAccount = RandomGeneratorUtils.generateRandomAccount(); + gameAccount = RandomGeneratorUtils.generateRandomAccount()+tenantSn; } while (!ObjectUtils.isEmpty(memberMapper.selectMemberByGameAccount(gameAccount))); }