diff --git a/ff-bean/xk-client/pom.xml b/ff-bean/xk-client/pom.xml new file mode 100644 index 0000000..321a568 --- /dev/null +++ b/ff-bean/xk-client/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + ff + com.ff + 0.0.1 + + + xk-client + 0.0.1 + xk-client + jar + + + + + + com.ff + ff-domain + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.apache.commons + commons-lang3 + + + + + com.alibaba.fastjson2 + fastjson2 + + + + commons-io + commons-io + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.5.15 + + true + + + + + repackage + + + + + + xk-client + + + diff --git a/ff-bean/xk-client/src/main/java/com/ff/client/IGamesService.java b/ff-bean/xk-client/src/main/java/com/ff/client/IGamesService.java new file mode 100644 index 0000000..dbe38d9 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/client/IGamesService.java @@ -0,0 +1,153 @@ +package com.ff.client; + +import com.ff.dto.*; + +import java.util.List; + +/** + * 游戏数据解析服务 + * + * @author shi + * @date 2024/10/21 + */ +public interface IGamesService { + + + /** + * 创建成员 + * + * @param createMemberRequestDTO 创建成员请求dto + * @return {@link Boolean } + */ + Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO); + + + /** + * 获取会员信息 + * + * @param memberInfoRequestDTO 会员信息请求dto + * @return {@link MemberInfoResponseDTO } + */ + MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO); + + /** + * 无重定向登录 + * + * @param gamesLogin 游戏登录 + * @return {@link String } + */ + String loginWithoutRedirect(GamesLogin gamesLogin); + + + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO); + + + /** + * 按代理id进行交换转账 + * + * @param exchangeTransferMoneyRequestDTO 外汇转账moeny dto + * @return {@link Long } + */ + Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO); + + + /** + * 汇兑转移状态确认 + * + * @param exchangeTransferMoneyRequestDTO 兑换转账请求dto + * @return {@link ExchangeTransferStatusResponseDTO } + */ + ExchangeTransferStatusResponseDTO exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO); + + + /** + * 按时间获取投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO); + + + /** + * 按历史时间获取投注记录 部分平台需要两个接口同时跑投注记录 + * + * @param betRecordByTimeDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO betRecordByTimeDTO); + + /** + * 赠送免费局数 + * + * @param createFreeSpinRequest 创建自由旋转请求 + * @return {@link Boolean } + */ + Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest); + + + /** + * 获取游戏详细信息 + * + * @param getGameDetailRequestDTO 获取游戏详细信息请求dto + * @return {@link GetGameDetailResponseDTO } + */ + GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO); + + + /** + * 强制会员从游戏注销 + * + * @param kickMemberRequestDTO 踢会员请求dto + * @return {@link Boolean } + */ + Boolean kickMember(KickMemberRequestDTO kickMemberRequestDTO); + + /** + * 踢成员全部 + * + * @param kickMemberAllDTO 踢成员全部dto + * @return {@link Boolean } + */ + Boolean kickMemberAll(KickMemberAllDTO kickMemberAllDTO); + + /** + * 免费游戏玩家使用的纪录 + * + * @param getFreeSpinDashflowRequestDTO 获取自由旋转dashflow请求dto + * @return {@link List }<{@link GameFreeRecord }> + */ + List getFreeSpinDashflow(GetFreeSpinDashflowRequestDTO getFreeSpinDashflowRequestDTO); + + /** + * 取消赠送免费局数 + * + * @param cancelFreeSpinRequestDTO 取消免费旋转请求 + * @return {@link Boolean } + */ + Boolean cancelFreeSpin(CancelFreeSpinRequestDTO cancelFreeSpinRequestDTO); + + /** + * 游戏演示登录 + * + * @param gameDemoLoginRequestDTO 游戏演示登录请求dto + * @return {@link GameDemoLoginResponseDTO } + */ + GameDemoLoginResponseDTO gameDemoLogin(GameDemoLoginRequestDTO gameDemoLoginRequestDTO); + + + /** + * 数据构建 + * + * @param gamesDataBuildDTO 数据 + * @return {@link GameBettingDetails } + */ + GameBettingDetails dataBuild(GamesDataBuildDTO gamesDataBuildDTO); + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/BetRecordByTimeDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/BetRecordByTimeDTO.java new file mode 100644 index 0000000..2a22b3b --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/BetRecordByTimeDTO.java @@ -0,0 +1,35 @@ +package com.ff.dto; + +import lombok.Data; + +/** + * 按时间dto投注记录 + * + * @author shi + * @date 2024/10/22 + */ +@Data +public class BetRecordByTimeDTO extends GamesBaseRequestDTO { + /** + * 开始时间 + */ + private Long startTime; + /** + * 结束时间 + */ + private Long endTime; + /** + * 页数 + */ + private Integer page; + /** + * 每页资料笔数 + */ + private Integer pageLimit; + /** + * 游戏id + */ + private Integer gameId; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/CancelFreeSpinRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/CancelFreeSpinRequestDTO.java new file mode 100644 index 0000000..03c4bd9 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/CancelFreeSpinRequestDTO.java @@ -0,0 +1,23 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 取消免费旋转请求 + * + * @author shi + * @date 2024/11/11 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class CancelFreeSpinRequestDTO extends GamesBaseRequestDTO { + /** + * 取消免费赠送游戏id + */ + private String referenceId; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/CreateFreeSpinRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/CreateFreeSpinRequestDTO.java new file mode 100644 index 0000000..e37220e --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/CreateFreeSpinRequestDTO.java @@ -0,0 +1,69 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 创建自由旋转请求dto + * + * @author shi + * @date 2024/11/11 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class CreateFreeSpinRequestDTO extends GamesBaseRequestDTO { + + /** + * 玩家账号 (JILI 新玩家则会自动创立账号) + */ + private String account; + + /** + * 玩家使用货币。转账钱包这项请填空字符串。 + */ + private String currency; + + /** + * 免费局数序号, 长度上限 50 + */ + private String referenceId; + + /** + * 有效期限 + * + * + */ + private Long freeSpinValidity; + + /** + * 局数 + */ + private Integer numberOfRounds; + + /** + * 可使用游戏 ID, 超过一笔时以逗号分隔; 系统内游戏id + * 长度 上限 200 + */ + private List gameIds; + + /** + * 指定投注额; + * 未指定时, 一律使用游戏中的最小投注额 + */ + private BigDecimal betValue; + + /** + * 免费游戏局数可使用的开始时间 + * 未带此参数时, 赠送后玩家可以立即使用 + */ + private Long startTime; + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/CreateMemberRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/CreateMemberRequestDTO.java new file mode 100644 index 0000000..2c6ae5f --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/CreateMemberRequestDTO.java @@ -0,0 +1,38 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.Map; + +/** + * 创建成员请求dto + * + * @author shi + * @date 2024/10/22 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class CreateMemberRequestDTO extends GamesBaseRequestDTO { + /** + * 账户 + */ + private String account; + + /** + * ae 平台 投注限额 + */ + private Map>> betLimit; + + /** + * 平台类型 0 桌面 1 移动 + */ + private Integer platformType; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferMoneyRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferMoneyRequestDTO.java new file mode 100644 index 0000000..5ed3f1d --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferMoneyRequestDTO.java @@ -0,0 +1,58 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; + +/** + * 外汇转账 + * + * @author shi + * @date 2024/10/22 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class ExchangeTransferMoneyRequestDTO extends GamesBaseRequestDTO { + + + /** + * 账户 + */ + private String account; + + /** + * 租户密钥 + */ + private String tenantKey; + + /** + * 订单id + */ + private String orderId; + /** + * 金额 + */ + private BigDecimal amount; + + + /** + * 租户额度 + */ + private BigDecimal quota; + + + /** + * 转账类型 + * 1: 从 游戏商 转移额度到 平台商 (不看 amount 值,全 + * 部转出) + * 2: 从 平台商 转移额度到 游戏商 + * 3: 从 游戏商 转移额度到 平台商 + */ + private Integer transferType; + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferStatusRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferStatusRequestDTO.java new file mode 100644 index 0000000..e4ae569 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferStatusRequestDTO.java @@ -0,0 +1,36 @@ +package com.ff.dto; + +import lombok.Data; + +/** + * 兑换转账状态请求dto + * + * @author shi + * @date 2025/03/12 + */ +@Data +public class ExchangeTransferStatusRequestDTO extends GamesBaseRequestDTO { + + + + + /** + * 账户 + */ + private String account; + + /** + * 货币 + */ + private String currency; + + /** + * 订单ID + */ + private String orderId; + + /** + * 游戏兑换货币id + */ + private Long gameExchangeMoneyId; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferStatusResponseDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferStatusResponseDTO.java new file mode 100644 index 0000000..1313d84 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/ExchangeTransferStatusResponseDTO.java @@ -0,0 +1,45 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * 交易所转账状态响应数据 + * + * @author shi + * @date 2025/04/08 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ExchangeTransferStatusResponseDTO { + + + /** + * 状态类型 StatusType 枚举 + */ + private Integer statusType; + + + /** + * 操作金额 + */ + private BigDecimal balance; + + /** + * 转账前金额(游戏币) + */ + private BigDecimal coinBefore; + + /** + * 转账后金额(游戏币) + */ + private BigDecimal coinAfter; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GameBettingDetails.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GameBettingDetails.java new file mode 100644 index 0000000..bf6eedc --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GameBettingDetails.java @@ -0,0 +1,183 @@ +package com.ff.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.ff.base.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; + +/** + * 会员投注细目对象 ff_game_betting_details + * + * @author shi + * @date 2025-02-10 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class GameBettingDetails extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + + /** + * 租户key + */ + private String tenantKey; + + + /** + * 币种编码 + */ + private String currencyCode; + + /** + * 会员id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long memberId; + + /** + * 游戏id + */ + private String gameCode; + + /** + * 游戏id + */ + @JsonSerialize(using = ToStringSerializer.class) + private String gameId; + + /** + * 游戏类型 ff_game_type 字典 + */ + private Integer gameType; + + /** + * 游戏平台 + */ + private String platformCode; + + /** + * 游戏名称 + */ + private String gameName; + + /** + * 注单状态 1: 赢 2: 输 3: 平局 4 未知 + */ + private Integer gameStatus; + + /** + * 注单类型 + * 1 一般下注 + * 9 舞龙争霸和梅杜莎的 + * 11 道具卡 + * 12 游戏内购 + * 17 满额必开 (下注) + * 18 满额必开 (开奖) + * 19 免费游戏 + * 28 旋转奖金 + * DG + * (1:注单,2:红包小费) + * AE + * 正常状况: + * 预设:0 + * 结果更改过状况: + * Resettle / Unsettle / Voidsettle / Unvoidsettle: 1 + * Voidbet: -1 + */ + private Integer gameStatusType; + + /** + * 游戏币种类型 + */ + private String gameCurrencyCode; + + /** + * 游戏账号 + */ + private String account; + + + /** + * 局号 + */ + private String round; + + /** + * 桌号 + */ + private String table; + + /** + * 座号 + */ + private String seat; + + /** + * 投注内容,部分游戏字段内容较长,建议数据库字段类型为 text + */ + private String betContent; + + /** + * 游戏注单唯一值 + */ + private String wagersId; + + /** + * 投注时间 (Unix 时间戳) + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long wagersTime; + + /** + * 投注金额 + */ + private BigDecimal betAmount; + + /** + * 派彩时间 (Unix 时间戳) + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long payoffTime; + + /** + * 派彩金额 + */ + private BigDecimal payoffAmount; + + + /** + * 对帐时间 (Unix 时间戳) + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long settlementTime; + + /** + * 有效投注金额 ※注 1 + */ + private BigDecimal turnover; + + /** + * 订单id + */ + private String orderNo; + + /** + * 结算状态 1 未结算 2已结算 3 已撤单 4 已取消 + */ + private Integer settlementStatus; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GameDemoLoginRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GameDemoLoginRequestDTO.java new file mode 100644 index 0000000..ff587ea --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GameDemoLoginRequestDTO.java @@ -0,0 +1,34 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 游戏演示登录请求dto + * + * @author shi + * @date 2025/04/03 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class GameDemoLoginRequestDTO extends GamesBaseRequestDTO{ + /** + * 语言 + */ + private String lang; + + + /** + * 游戏类型 + */ + private String gameType; + + /** + * 游戏id + */ + private String gameId; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GameDemoLoginResponseDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GameDemoLoginResponseDTO.java new file mode 100644 index 0000000..7e70425 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GameDemoLoginResponseDTO.java @@ -0,0 +1,23 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 游戏演示登录响应dto + * + * @author shi + * @date 2025/04/03 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class GameDemoLoginResponseDTO { + /** + * 网址 + */ + private String url; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GameFreeRecord.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GameFreeRecord.java new file mode 100644 index 0000000..33f2a5c --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GameFreeRecord.java @@ -0,0 +1,106 @@ +package com.ff.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.ff.base.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 免费赠送游戏记录对象 ff_game_free_record + * + * @author shi + * @date 2025-02-13 + */ +@Data +@AllArgsConstructor +@SuperBuilder +@NoArgsConstructor +public class GameFreeRecord extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 币种编码 + */ + private String currencyCode; + + /** + * 平台代码 + */ + private String platformCode; + + /** + * 免费局数序号(唯一标识符) + */ + private String referenceId; + + /** + * 会员id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long memberId; + + /** + * 用户账号 + */ + private String memberAccount; + + /** + * 游戏id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long gameId; + + /** + * 免费游戏局数可使用的开始时间 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sendTime; + + /** + * 免费局数过期时间 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long expiredTime; + + /** + * 免费局数记录更新时间 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long freeUpdateTime; + + /** + * 免费局数赠送的游戏名称 + */ + private String sendGame; + + /** + * 免费局数赠送的数量 + */ + private Integer sendAmount; + + /** + * 已使用的免费局数数量 + */ + private Integer usedAmount; + + /** + * 未使用的免费局数数量 + */ + private Integer unusedAmount; + + /** + * 免费状态 1正常 0 取消 + */ + private Integer freeStatus; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GamesBaseRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GamesBaseRequestDTO.java new file mode 100644 index 0000000..0b2c4fc --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GamesBaseRequestDTO.java @@ -0,0 +1,51 @@ +package com.ff.dto; + +import com.ff.game.domain.KeyInfo; +import com.ff.game.domain.Platform; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.io.Serializable; + +/** + * 游戏请求dto + * + * @author shi + * @date 2024/10/22 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class GamesBaseRequestDTO implements Serializable { + private static final long serialVersionUID = 5139311242800113436L; + /** + * 代理id + */ + private String agentId; + + /** + * 代理密钥 + */ + private String agentKey; + + /** + * 查询 + */ + private String query; + + + /** + * 货币 + */ + private String currency; + + private Platform vendor; + + private KeyInfo keyInfo; + + private String systemCurrency; + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GamesDataBuildDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GamesDataBuildDTO.java new file mode 100644 index 0000000..1b61b15 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GamesDataBuildDTO.java @@ -0,0 +1,46 @@ +package com.ff.dto; + +import com.ff.game.domain.Platform; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 游戏数据构建dto + * + * @author shi + * @date 2024/10/22 + */ +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +@Data +public class GamesDataBuildDTO +{ + + /** + * 数据 + */ + private Object data; + + /** + * 系统货币代码 + */ + private String systemCurrencyCode; + + /** + * 货币代码 + */ + private String currencyCode; + + /** + * 代理id + */ + private String agentId; + + private Platform platform; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GamesLogin.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GamesLogin.java new file mode 100644 index 0000000..a20da99 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GamesLogin.java @@ -0,0 +1,57 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.Map; + +/** + * 游戏登录 + * + * @author shi + * @date 2024/10/22 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class GamesLogin extends GamesBaseRequestDTO{ + /** + * 账户 + */ + private String account; + /** + * 游戏唯一识别值(同等 GameList 各游戏的 GameId) + */ + private String gameId; + /** + * UI 语系, 请参考 附录 – 语系参数 + */ + private String lang; + /** + * 不列入 md5 加密,游戏回主页功能导向位置 + */ + private String homeUrl; + /** + * 不列入 md5 加密,带入 web 或是 app + */ + private String platform; + /** + * 不列入 md5 加密, 带入 1 即关闭全屏幕模式 + */ + private Integer disableFullScreen; + + /** + * 游戏类型 + */ + private String gameType; + + + /** + * ae 平台 投注限额 + */ + private Map>> betLimit; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GetFreeSpinDashflowRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GetFreeSpinDashflowRequestDTO.java new file mode 100644 index 0000000..20d4295 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GetFreeSpinDashflowRequestDTO.java @@ -0,0 +1,19 @@ +package com.ff.dto; + +import lombok.Data; + +/** + * 获取自由旋转dashflow请求dto + * + * @author shi + * @date 2024/11/11 + */ +@Data +public class GetFreeSpinDashflowRequestDTO extends GamesBaseRequestDTO { + + /** + * 开始时间 + */ + private Long startTime; + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GetGameDetailRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GetGameDetailRequestDTO.java new file mode 100644 index 0000000..b75948c --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GetGameDetailRequestDTO.java @@ -0,0 +1,28 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 获取游戏详细信息请求dto + * + * @author shi + * @date 2024/11/12 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class GetGameDetailRequestDTO extends GamesBaseRequestDTO { + + /** + * 投注id + */ + private String wagersId; + /** + * 郎 + */ + private String lang; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/GetGameDetailResponseDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/GetGameDetailResponseDTO.java new file mode 100644 index 0000000..9255beb --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/GetGameDetailResponseDTO.java @@ -0,0 +1,25 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 获取游戏详细信息请求dto + * + * @author shi + * @date 2024/11/12 + */ +@NoArgsConstructor +@Data +@AllArgsConstructor +@Builder +public class GetGameDetailResponseDTO { + + + /** + * url + */ + private String url; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/KickMemberAllDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/KickMemberAllDTO.java new file mode 100644 index 0000000..d842489 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/KickMemberAllDTO.java @@ -0,0 +1,28 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import javax.validation.constraints.NotNull; + +/** + * 踢成员全部dto + * + * @author shi + * @date 2024/11/12 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class KickMemberAllDTO extends GamesBaseRequestDTO { + + /** + * 游戏id + */ + private String gameId; + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/KickMemberRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/KickMemberRequestDTO.java new file mode 100644 index 0000000..d2b0d6a --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/KickMemberRequestDTO.java @@ -0,0 +1,25 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 踢会员请求dto + * + * @author shi + * @date 2024/11/12 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class KickMemberRequestDTO extends GamesBaseRequestDTO { + + /** + * 账户 + */ + private String account; +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/MemberInfoRequestDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/MemberInfoRequestDTO.java new file mode 100644 index 0000000..a53226c --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/MemberInfoRequestDTO.java @@ -0,0 +1,25 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 查询用户信息 + * + * @author shi + * @date 2024/10/22 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class MemberInfoRequestDTO extends GamesBaseRequestDTO { + /** + * 账户 + */ + private String accounts; + + +} diff --git a/ff-bean/xk-client/src/main/java/com/ff/dto/MemberInfoResponseDTO.java b/ff-bean/xk-client/src/main/java/com/ff/dto/MemberInfoResponseDTO.java new file mode 100644 index 0000000..d967b13 --- /dev/null +++ b/ff-bean/xk-client/src/main/java/com/ff/dto/MemberInfoResponseDTO.java @@ -0,0 +1,41 @@ +package com.ff.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.math.BigDecimal; + + +/** + * 成员信息响应dto + * + * @author shi + * @date 2024/10/30 + */ +@NoArgsConstructor +@Data +@AllArgsConstructor +@SuperBuilder +public class MemberInfoResponseDTO { + + + /** + * 账户 + */ + private String account; + /** + * 余额 + */ + private BigDecimal balance; + /** + * 状态: + * 1: 在线 + * 2: 脱机 + * 3: 账号不存在 + * 4:未知 + */ + private Integer status; +} diff --git a/ff-fetcher/pom.xml b/ff-fetcher/pom.xml index c8541c1..33b34fd 100644 --- a/ff-fetcher/pom.xml +++ b/ff-fetcher/pom.xml @@ -15,6 +15,14 @@ + + com.ff + xk-client + + + com.ff + comp-redis + com.xuxueli xxl-job-core diff --git a/ff-fetcher/src/main/java/com/ff/service/PlatformManager.java b/ff-fetcher/src/main/java/com/ff/service/PlatformManager.java new file mode 100644 index 0000000..693d26d --- /dev/null +++ b/ff-fetcher/src/main/java/com/ff/service/PlatformManager.java @@ -0,0 +1,24 @@ +package com.ff.service; + +import com.ff.game.domain.Platform; +import com.ff.redis.GRedisCache; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author cengy + */ +@Service +public class PlatformManager { + + @Autowired + GRedisCache gRedisCache; + + public Platform get(String platformCode) { + return gRedisCache.getCacheObject(getCacheKey(platformCode)); + } + + private String getCacheKey(String configKey) { + return "platform:" + configKey; + } +} diff --git a/ff-fetcher/src/main/java/com/ff/utils/AdjustTimestampByMinuteOffset.java b/ff-fetcher/src/main/java/com/ff/utils/AdjustTimestampByMinuteOffset.java new file mode 100644 index 0000000..fad2f47 --- /dev/null +++ b/ff-fetcher/src/main/java/com/ff/utils/AdjustTimestampByMinuteOffset.java @@ -0,0 +1,12 @@ +package com.ff.utils; + +/** + * @author cengy + */ +public class AdjustTimestampByMinuteOffset { + + public static long get(long timestampMillis, int minuteOffset) { + // 将分钟转换为毫秒,并加到时间戳上 + return timestampMillis + minuteOffset * 60 * 1000L; + } +} diff --git a/ff-fetcher/src/main/java/com/ff/utils/CurrentMillis.java b/ff-fetcher/src/main/java/com/ff/utils/CurrentMillis.java new file mode 100644 index 0000000..1689b56 --- /dev/null +++ b/ff-fetcher/src/main/java/com/ff/utils/CurrentMillis.java @@ -0,0 +1,13 @@ +package com.ff.utils; + +import java.time.Instant; + +/** + * @author cengy + */ +public class CurrentMillis { + + public static Long get() { + return Instant.now().toEpochMilli(); + } +} diff --git a/ff-fetcher/src/main/java/com/ff/xxljob/fetch/TaskParam.java b/ff-fetcher/src/main/java/com/ff/xxljob/fetch/TaskParam.java index 51b98b8..868ec99 100644 --- a/ff-fetcher/src/main/java/com/ff/xxljob/fetch/TaskParam.java +++ b/ff-fetcher/src/main/java/com/ff/xxljob/fetch/TaskParam.java @@ -9,5 +9,5 @@ import lombok.Data; public class TaskParam { // 定时任务的参数:平台code, 拉多少分钟前的 private String platformCode; - private long ago; + private int ago; } diff --git a/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchHistoryOrderListTask.java b/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchHistoryOrderListTask.java index 1a532f6..48b1da8 100644 --- a/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchHistoryOrderListTask.java +++ b/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchHistoryOrderListTask.java @@ -1,20 +1,74 @@ package com.ff.xxljob.task; +import com.ff.client.IGamesService; +import com.ff.dto.BetRecordByTimeDTO; +import com.ff.game.domain.KeyInfo; +import com.ff.game.domain.Platform; +import com.ff.service.PlatformManager; +import com.ff.utils.AdjustTimestampByMinuteOffset; +import com.ff.utils.CurrentMillis; import com.ff.xxljob.fetch.TaskParam; import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * 拉取历史投注订单列表 * * @author cengy */ @Component +@Slf4j public class FetchHistoryOrderListTask extends FetchTask { + @Autowired(required = false) + private Map clientServiceMap = new HashMap<>(); + + @Autowired + private PlatformManager platformManager; + @XxlJob("fetchHistoryOrderListTask") @Override public void doExecute(TaskParam taskParam) { + //捞取指定分钟前的数据 + Platform platform = platformManager.get(taskParam.getPlatformCode()); + if (null == platform) { + return; + } + int agoMin = taskParam.getAgo(); + //捞取指定分钟前的数据 + Long endTime = CurrentMillis.get(); + Long startTime = AdjustTimestampByMinuteOffset.get(endTime, agoMin); + List keyData = platform.getKeyInfo(); + + for (KeyInfo keyInfo : keyData) { + try { + BetRecordByTimeDTO betRecordByTimeDTO = new BetRecordByTimeDTO(); + betRecordByTimeDTO.setStartTime(startTime); + betRecordByTimeDTO.setEndTime(endTime); + betRecordByTimeDTO.setPage(1); + betRecordByTimeDTO.setPageLimit(1000); + betRecordByTimeDTO.setAgentId(keyInfo.getCode()); + betRecordByTimeDTO.setAgentKey(keyInfo.getKey()); + betRecordByTimeDTO.setKeyInfo(keyInfo); + betRecordByTimeDTO.setVendor(platform); + + betRecordByTimeDTO.setSystemCurrency(keyInfo.getCurrency()); + betRecordByTimeDTO.setCurrency(platform.getCurrencyInfo().get(keyInfo.getCurrency())); + + clientServiceMap.get(platform.getPlatformCode() + "Service").getBetRecordByHistoryTime(betRecordByTimeDTO); + } catch (Exception e) { + log.error("同步平台投注记录失败platformCode:{}", platform.getPlatformCode(), e); + } + if (platform.isMultiAgent()) { + break; + } + } } } diff --git a/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchOrderListTask.java b/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchOrderListTask.java index 24ccec5..09d6325 100644 --- a/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchOrderListTask.java +++ b/ff-fetcher/src/main/java/com/ff/xxljob/task/FetchOrderListTask.java @@ -1,20 +1,76 @@ package com.ff.xxljob.task; +import com.ff.client.IGamesService; +import com.ff.dto.BetRecordByTimeDTO; +import com.ff.game.domain.KeyInfo; +import com.ff.game.domain.Platform; +import com.ff.service.PlatformManager; +import com.ff.utils.AdjustTimestampByMinuteOffset; +import com.ff.utils.CurrentMillis; import com.ff.xxljob.fetch.TaskParam; import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * 拉取投注订单列表 * * @author cengy */ @Component +@Slf4j public class FetchOrderListTask extends FetchTask { + @Autowired(required = false) + private Map clientServiceMap = new HashMap<>(); + + @Autowired + private PlatformManager platformManager; + @XxlJob("fetchOrderListTask") @Override public void doExecute(TaskParam taskParam) { + Platform platform = platformManager.get(taskParam.getPlatformCode()); + if (null == platform) { + return; + } + int agoMin = taskParam.getAgo(); + //捞取指定分钟前的数据 + Long endTime = CurrentMillis.get(); + Long startTime = AdjustTimestampByMinuteOffset.get(endTime, agoMin); + + List keyData = platform.getKeyInfo(); + + for (KeyInfo keyInfo : keyData) { + try { + BetRecordByTimeDTO betRecordByTimeDTO = new BetRecordByTimeDTO(); + betRecordByTimeDTO.setStartTime(startTime); + betRecordByTimeDTO.setEndTime(endTime); + betRecordByTimeDTO.setPage(1); + betRecordByTimeDTO.setPageLimit(1000); + betRecordByTimeDTO.setAgentId(keyInfo.getCode()); + betRecordByTimeDTO.setAgentKey(keyInfo.getKey()); + betRecordByTimeDTO.setKeyInfo(keyInfo); + betRecordByTimeDTO.setVendor(platform); + + betRecordByTimeDTO.setSystemCurrency(keyInfo.getCurrency()); + betRecordByTimeDTO.setCurrency(platform.getCurrencyInfo().get(keyInfo.getCurrency())); + + clientServiceMap.get(platform.getPlatformCode() + "Service").getBetRecordByTime(betRecordByTimeDTO); + } catch (Exception e) { + log.error("同步平台投注记录失败platformCode:{}", platform.getPlatformCode(), e); + } + if (platform.isMultiAgent()) { + break; + } + } + + } } diff --git a/ff-platform/xk-dbsports/pom.xml b/ff-platform/xk-dbsports/pom.xml new file mode 100644 index 0000000..a4f5e83 --- /dev/null +++ b/ff-platform/xk-dbsports/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + ff + com.ff + 0.0.1 + + + xk-dbsports + 0.0.1 + xk-dbsports + jar + + + + + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.apache.commons + commons-lang3 + + + + + com.alibaba.fastjson2 + fastjson2 + + + + commons-io + commons-io + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.5.15 + + true + + + + + repackage + + + + + + xk-dbsports + + + diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/address/DBSportsAddress.java b/ff-platform/xk-dbsports/src/main/java/com/ff/address/DBSportsAddress.java new file mode 100644 index 0000000..70a2e09 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/address/DBSportsAddress.java @@ -0,0 +1,32 @@ +package com.ff.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.sun.media.jfxmediaimpl.platform.PlatformManager; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + + +/** + * DB体育对接文档 + * 账号: api + * 密码: a12345678 + * + * @author cengy + */ +@Component +public class DBSportsAddress implements AddressSource { + + @Resource + private PlatformManager platformService; + + @Override + public ForestAddress getAddress(ForestRequest request) { + String apiBaseUrl = platformService.get(GamePlatforms.DBSports.getCode()) + .getUrlInfo().getUrl(); + return new ForestAddress("https", apiBaseUrl, 443, ""); + } +} \ No newline at end of file diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/client/DBSportsClient.java b/ff-platform/xk-dbsports/src/main/java/com/ff/client/DBSportsClient.java new file mode 100644 index 0000000..df3020a --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/client/DBSportsClient.java @@ -0,0 +1,110 @@ +package com.ff.client; + +import com.ff.dto.CreateUserResponse; +import com.ff.dto.TransferResponse; +import com.ff.sports.db.address.DBSportsAddress; + +/** + * @author cengy + */ +@Address(source = DBSportsAddress.class) +public interface DBSportsClient { + /** + * 创建投注用户 + * + * @return {@link CreateUserResponse} + */ + @Post(url = "/api/user/create", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + CreateUserResponse createMember(@Body CreateUserRequest request, + @Header("requestId") @Var("requestId") String requestId); + + /** + * 用户登录接口(注册和登录合并为一个接口) + * + * @param request + * @param requestId + * @return + */ + @Post(url = "/api/user/login", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + LoginResponse login(@Body LoginRequest request, + @Header("requestId") String requestId); + + /** + * 用户金额转入到DB体育平台,支持两位小数,最小0.01,必须是正数 + * + * @param request + * @return {@link TransferResponse} + */ + @Post(url = "/api/fund/transfer", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + TransferResponse transferIn(@Body TransferRequest request, + @Header("requestId") @Var("requestId") String requestId + ); + + @Post(url = "/api/fund/transfer", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + TransferResponse transferOut(@Body TransferRequest request, + @Header("requestId") String requestId + ); + + @Post(url = "/api/fund/checkBalance", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + GetMemberInfoResponse getMemberInfo(@Body GetMemberInfoRequest request, + @Header("requestId") String requestId); + + /** + * 根据转账ID查询交易记录接口。 + */ + @Post(url = "/api/fund/getTransferRecord", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + TransferDetailResponse transferDetail(@Body TransferDetailRequest request, + @Header("requestId") String requestId); + + /** + * 剔用户 + * + * @param request + * @param requestId + * @return + */ + @Post(value = "/api/user/kickOutUser", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + KickUserResponse kickUser(@Body KickUserRequest request, + @Header("requestId") String requestId); + + + /** + * 拉取订单Json数据 + */ + @Post(url = "/api/bet/queryBetListV2", + headers = { + "Content-type: application/x-www-form-urlencoded" + } + ) + GetBetListResponse getBetList(@Body GetBetListRequest request, + @Header("requestId") String requestId); + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/CreateUserRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/CreateUserRequest.java new file mode 100644 index 0000000..418b522 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/CreateUserRequest.java @@ -0,0 +1,28 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class CreateUserRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String userName; // 用户名(可以包含但是不要等同于特殊字符或者空格,长度控制在30个字符以下) + private String merchantCode; // 商户code + private String timestamp = System.currentTimeMillis() + ""; // 13位时间戳 + private String currency; // 币种 + private String nickname; // N 昵称 + private String agentId; // N 信用网(代理id) + private String signature; // 签名 signature =MD5(MD5(userName +”&”+ merchantCode +”&”+ timestamp) + ”&”+ key) + + public void buildSignature(String key) { + String signature = Md5Utils.md5New(Md5Utils.md5New(userName + "&" + merchantCode + "&" + timestamp) + "&" + key); + this.signature = signature; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/CreateUserResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/CreateUserResponse.java new file mode 100644 index 0000000..03228b0 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/CreateUserResponse.java @@ -0,0 +1,26 @@ +package com.ff.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class CreateUserResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean status; + private String msg; + private String code; + private Long serverTime; + private UserDTO data; + + @Data + public static class UserDTO { + private String userId; + } + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/Enums.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/Enums.java new file mode 100644 index 0000000..9042222 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/Enums.java @@ -0,0 +1,9 @@ +package com.ff.dto; + +/** + * @author cengy + */ +public class Enums { + + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetBetListRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetBetListRequest.java new file mode 100644 index 0000000..a9e568f --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetBetListRequest.java @@ -0,0 +1,93 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class GetBetListRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户名(可选) + */ + private String userName; + + /** + * 开始时间(13位时间戳,必填) + */ + private String startTime; + + /** + * 结束时间(13位时间戳,必填) + */ + private String endTime; + + /** + * 商户编码(必填) + */ + private String merchantCode; + + /** + * 赛种ID(可选) + */ + private Integer sportId; + + /** + * 联赛ID(可选) + */ + private Long tournamentId; + + /** + * 结算状态(可选) + * 0: 未结算 + * 1: 已结算 + * 2: 取消人工 + * 3: 待确认 + * 4: 风控拒单 + * 5: 撤单(赛事取消) + */ + private Integer settleStatus; + + /** + * 页面编号,从1开始(可选) + */ + private Integer pageNum; + + /** + * 每页条数(最大1000,可选) + */ + private Integer pageSize; + + /** + * 请求时间戳(13位,必填) + */ + private String timestamp = String.valueOf(System.currentTimeMillis()); + + /** + * 排序方式(可选) + * 1: 订单创建时间(投注时间) + * 2: 订单更新时间 + */ + private Integer orderBy; + + /** + * 语言(可选,默认中文,传"en"返回英文) + */ + private String language; + + /** + * 签名(必填) + */ + private String signature; + + public void buildSignature(String key) { + String signature = Md5Utils.md5New(Md5Utils.md5New(merchantCode + "&" + startTime + "&" + endTime + "&" + timestamp) + "&" + key); + this.signature = signature; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetBetListResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetBetListResponse.java new file mode 100644 index 0000000..3331a52 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetBetListResponse.java @@ -0,0 +1,199 @@ +package com.ff.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @author cengy + */ +@Data +public class GetBetListResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean status; + private String msg; + private String code; + private Long serverTime; + private DataDTO data; + + @Data + public static class DataDTO { + + + // 当前页码 + private Integer pageNum; + // 每页条数 + private Integer pageSize; + // 总条数 + private Integer totalCount; + // 注单列表 + private List list; + } + + @Data + public static class OrderItemDTO { + // 用户名 + private String userName; + + // 商户编码 + private String merchantCode; + + // 订单ID + private String orderNo; + + // 订单状态,具体见参数字段映射 + private Integer orderStatus; + + // 投注时间(13位时间戳) + private Long createTime; + + // 订单更新时间(13位时间戳) + private Long modifyTime; + + // 实际投注金额 + private String orderAmount; + + // 注单项数量 + private Integer betCount; + + // 结算时间(13位时间戳) + private Long settleTime; + + // 结算金额 + private Double settleAmount; + + // 提前结算投注金额 + private Double preBetAmount; + + // 盈利金额 + private Double profitAmount; + + // 注单结算结果 + // 2:走水,3:输,4:赢,5:赢半,6:输半,7:赛事取消,8:赛事延期 + private Integer outcome; + + // 串关类型 + private Integer seriesType; + + // 串关值 + private String seriesValue; + + // 结算次数 + private Integer settleTimes; + + // 设备类型:1-H5,2-PC,3-Android,4-IOS + private String deviceType; + + // 移动设备标识 + private String deviceImei; + + // 用户IP地址 + private String ip; + + // 币种 + private String currency; + + // 汇率 + private BigDecimal exchangeRate; + + // 最大中奖金额 + private Double maxWinAmount; + + // VIP等级 + private Integer vipLevel; + + // 投注前余额 + private BigDecimal beforeTransfer; + + // 投注后余额 + private BigDecimal afterTransfer; + + // 有效投注金额 + private BigDecimal validOrderAmount; + + // 注单详情列表 + private List detailList; + } + + @Data + public static class DetailItemDTO { + // 投注项编号 + private Long betNo; + + // 投注项ID + private Long playOptionsId; + + // 赛事ID + private Long matchId; + + // 比赛开始时间(13位时间戳) + private Long beginTime; + + // 注单金额 + private Double betAmount; + + // 联赛名称 + private String matchName; + + // 比赛对阵 + private String matchInfo; + + // 投注类型: + // 1:早盘,2:滚球盘,3:冠军盘,4:虚拟赛事,5:电竞赛事 + private Integer matchType; + + // 赛种ID + private Integer sportId; + + // 玩法ID + private Integer playId; + + // 投注项(如主客队) + private String playOptions; + + // 游戏名称 + private String sportName; + + // 联赛ID + private Long tournamentId; + + // 投注项名称 + private String playOptionName; + + // 玩法名称 + private String playName; + + // 盘口类型 + private String marketType; + + // 盘口值 + private String marketValue; + + // 让球值 + private BigDecimal handicap; + + // 结算比分(我方处理后所得,数据商可能未提供) + private String settleScore; + + // 基准分 + private String scoreBenchmark; + + // 当前赔率(欧洲盘表示) + private BigDecimal oddsValue; + + // 注单结算结果: + // 0:无结果,2:走水,3:输,4:赢,5:赢一半,6:输一半, + // 7:赛事取消,8:赛事延期,11:比赛延迟,12:比赛中断, + // 13:未知,15:比赛放弃,16:异常盘口,17:未知状态, + // 18:比赛取消,19:比赛延期 + private String betResult; + + // 最终赔率(按盘口类型) + private BigDecimal oddFinally; + } + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetMemberInfoRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetMemberInfoRequest.java new file mode 100644 index 0000000..69009ab --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetMemberInfoRequest.java @@ -0,0 +1,36 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class GetMemberInfoRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户名,不能为空 + */ + private String userName; + + /** + * 商户编码 + */ + private String merchantCode; + /** + * Long型时间戳(13位) + */ + private String timestamp = System.currentTimeMillis() + ""; + + private String signature; + + public void buildSignature(String key) { + + String signature = Md5Utils.md5New(Md5Utils.md5New(merchantCode + "&" + userName + "&" + timestamp) + "&" + key); + this.signature = signature; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetMemberInfoResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetMemberInfoResponse.java new file mode 100644 index 0000000..c3d34e4 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/GetMemberInfoResponse.java @@ -0,0 +1,26 @@ +package com.ff.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author cengy + */ +@Data +public class GetMemberInfoResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private Boolean status; + private String msg; + private String code; + private Long serverTime; + private MemberInfoDTO data; + + @Data + public static class MemberInfoDTO { + private BigDecimal balance; + private String userName; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/KickUserRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/KickUserRequest.java new file mode 100644 index 0000000..07c707a --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/KickUserRequest.java @@ -0,0 +1,24 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class KickUserRequest implements Serializable { + + private static final long serialVersionUID = 1L; + private String userName; + private String merchantCode; + private String timestamp = System.currentTimeMillis() + ""; + private String signature; + + public void buildSignature(String key) { + String signature = Md5Utils.md5New(Md5Utils.md5New(merchantCode + "&" + userName + "&" + timestamp) + "&" + key); + this.signature = signature; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/KickUserResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/KickUserResponse.java new file mode 100644 index 0000000..ae7ba63 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/KickUserResponse.java @@ -0,0 +1,20 @@ +package com.ff.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class KickUserResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean status; + private String msg; + private String code; + private Long serverTime; + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/LoginRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/LoginRequest.java new file mode 100644 index 0000000..207eca9 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/LoginRequest.java @@ -0,0 +1,57 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author cengy + */ +@Data +public class LoginRequest implements Serializable { + + private static final long serialVersionUID = 1L; + private String userName; + private String merchantCode; + private String timestamp = System.currentTimeMillis() + ""; + private String signature; + + // 不能传错,用户可能受到设备类型相关风控措施的错误限制,进而影响正常用户货量,并产生客诉 + private String terminal; // 终端类型:【电脑传值:pc】,【移动设备传值:mobile】 注:这个参数传值必须是pc或者mobile, + private BigDecimal balance; // 用户余额,N + private String currency; // 币种(见参数映射:支持币种 )会员首次登录,必须填写币种参数,否则注册失败 + + private String callbackUrl; // 玩家会话失效跳转的商户地址url(非必传) + private String stoken; // 非必传字段(商户方用户会话) + + // 非必传字段(支持体育游戏其他端的跳转) , + // C端⽀持跳转的游戏,如果C端⽀持跳转多个游戏 , + // 则使⽤逗号区分。 具体字段可查看:参数字段映射第6条 参数字段映射 + private String jumpsupport; + private String jumpfrom; // 非必传字段,同上 + + private String agentId; // 信用网(代理id),N + // 用户语种: + //zh:中文 + //en:英文 + //vi:越南语 + //tw:中文繁体 + //th:泰语 + //ms:马来语 + //ad:印尼语 + //ko:韩语 + //mya:缅甸语 + //pt:葡萄牙语 + //es:西班牙语 + //非必传字段 + private String language; + private String ip; // 非必传字段 说明:商户端在该字段上传入用户登陆时端ip + + public void buildSignature(String key) { + String signature = Md5Utils.md5New(Md5Utils.md5New(merchantCode + "&" + userName + "&" + terminal + "&" + timestamp) + "&" + key); + + this.signature = signature; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/LoginResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/LoginResponse.java new file mode 100644 index 0000000..9b689dc --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/LoginResponse.java @@ -0,0 +1,34 @@ +package com.ff.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author cengy + */ +@Data +public class LoginResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean status; + private String msg; + private String code; + private Long serverTime; + private LoginRespDTO data; + + @Data + public static class LoginRespDTO { + private String domain; // 体育游戏前端URL + private String token; // 带有登录状态的token + private String apiDomain;// 赛事API的域名(若没有对接赛事API,为空) + private String imgDomain; // 静态资源域名 + private String loginUrl; // 登录体育URL,可直接跳转 + private String userId; // 用户id + private String url; // 参加活动的商户使用,客户端域名和参数拼接后提供商户使用 + private List loginUrlArr; // loginUrl数组,多个域名,调试使用 + } + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferDetailRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferDetailRequest.java new file mode 100644 index 0000000..d6e8ae8 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferDetailRequest.java @@ -0,0 +1,38 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class TransferDetailRequest implements Serializable { + + /** + * 用户名,N + */ + private String userName; + /** + * 商户code + */ + private String merchantCode; + /** + * 交易id(19位数字) + */ + private String transferId; + + private String timestamp = System.currentTimeMillis() + ""; + + /** + * 签名 + */ + private String signature; + + public void buildSignature(String key) { + String signature = Md5Utils.md5New(Md5Utils.md5New(merchantCode + "&" + transferId + "&" + timestamp) + "&" + key); + this.signature = signature; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferDetailResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferDetailResponse.java new file mode 100644 index 0000000..38b10cb --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferDetailResponse.java @@ -0,0 +1,39 @@ +package com.ff.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 TransferDetailDTO data; + private Boolean status; + private String msg; + private String code; + private Long serverTime; + + @Data + public static class TransferDetailDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private String transferId; // 交易id + private String merchantCode; // 商户代码 + private Long userId; // 用户id + private Integer transferType; // 交易类型 1:加款,2:扣款 + private BigDecimal amount; // 交易金额 + private BigDecimal beforeTransfer; // 转账前余额 + private Integer afterTransfer; // 转账后余额 + private Integer status; // 转账成功与否(0:失败,1:成功) + private String mag; // 转账模式 1:免转,2:转账 + private Integer transferMode; // 转账涉及订单(transferMode为2时,该字段为空) + private Long createTime; // 交易时间 + + } + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferRequest.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferRequest.java new file mode 100644 index 0000000..556a408 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferRequest.java @@ -0,0 +1,28 @@ +package com.ff.dto; + +import com.ff.base.utils.sign.Md5Utils; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class TransferRequest implements Serializable { + + private String userName; + private String merchantCode; + private int transferType; // 1:加款 2:扣款 + + private String amount; // 金额,小数2位 + private String transferId; // 交易的讯息号,唯一标示,不可重复,19位长度的字符串 + private String timestamp = String.valueOf(System.currentTimeMillis()); + private String signature; + + public void buildSignature(String key) { + String signature = Md5Utils.md5New(Md5Utils.md5New(merchantCode + "&" + userName + "&" + transferType + "&" + amount + "&" + transferId + "&" + timestamp) + "&" + key); + this.signature = signature; + } + +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferResponse.java b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferResponse.java new file mode 100644 index 0000000..7bbc66b --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/dto/TransferResponse.java @@ -0,0 +1,25 @@ +package com.ff.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author cengy + */ +@Data +public class TransferResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean status; + private String msg; + private String code; + private Long serverTime; + private TransferDTO data; + + @Data + public static class TransferDTO { + private String userName; + } +} diff --git a/ff-platform/xk-dbsports/src/main/java/com/ff/impl/DBSportsServiceImpl.java b/ff-platform/xk-dbsports/src/main/java/com/ff/impl/DBSportsServiceImpl.java new file mode 100644 index 0000000..0fe65b0 --- /dev/null +++ b/ff-platform/xk-dbsports/src/main/java/com/ff/impl/DBSportsServiceImpl.java @@ -0,0 +1,616 @@ +package com.ff.impl; + +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.exception.base.ApiException; +import com.ff.base.exception.base.BaseException; +import com.ff.base.utils.DateUtils; +import com.ff.base.utils.StringUtils; +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.request.GameDemoLoginResponseDTO; +import com.ff.game.api.request.GetGameDetailResponseDTO; +import com.ff.game.api.request.MemberInfoResponseDTO; +import com.ff.game.domain.GameBettingDetails; +import com.ff.game.domain.GameFreeRecord; +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.db.client.DBSportsClient; +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.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + + +/** + * DB体育 + * + * @author cengy + * @date 2024/10/21 + */ +@Service("DBSportsService") +@Slf4j +public class DBSportsServiceImpl implements IGamesService { + + @Resource + private RedisCache redisCache; + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + @Resource + private IGameService gameService; + + + @Resource + private IMemberService memberService; + + @Resource + private DBSportsClient dbSportsClient; + + @Resource + private IGameBettingDetailsService gameBettingDetailsService; + + /** + * 获得就是成功 + * + * @param errorCode 错误代码 + * @return {@link Boolean } + */ + private Boolean isSuccess(String errorCode) { + return "0000".equals(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 requestDTO 创建成员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean createMember(CreateMemberRequestDTO requestDTO) { + + CreateUserRequest request = new CreateUserRequest(); + request.setUserName(requestDTO.getAccount()); + request.setMerchantCode(requestDTO.getAgentId()); + request.setCurrency(requestDTO.getCurrency()); + request.buildSignature(requestDTO.getAgentKey()); + + //String lang = requestDTO.getLan + String requestId = IdUtils.fastUUID(); + CreateUserResponse response = dbSportsClient.createMember(request, requestId); + if (isSuccess(response.getCode())) { + return Boolean.TRUE; + } + + log.error("创建会员失败, errorCode:{}, errorMessage:{}", response.getCode(), response.getMsg()); + throw new ApiException(ErrorCode.Create_Member_Failure.getCode()); + } + + + /** + * 按代理id进行交换转账 + * + * @param requestDTO 外汇转账 + * @return {@link Long } + */ + @Override + @Transactional + public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO requestDTO) { + + Member member = memberService.selectMemberByGameAccount(requestDTO.getAccount()); + String transactionId = GamePlatforms.DBSports.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.DBSports.getCode()) + .build(); + exchangeMoney.setCreateBy(Constants.SYSTEM); + //接口限制限制50字符 + exchangeMoney.setTransactionId(transactionId); + // 转入 + if (requestDTO.getTransferType().equals(TransferType.GAMES.getCode())) { + TransferRequest request = new TransferRequest(); + request.setUserName(requestDTO.getAccount()); + request.setTransferType(1); + request.setTransferId(requestDTO.getOrderId()); + request.setMerchantCode(requestDTO.getAgentId()); + request.setAmount(requestDTO.getAmount().toString()); + request.buildSignature(requestDTO.getAgentKey()); + + TransferResponse response = dbSportsClient.transferIn( + request, IdUtils.fastUUID() + ); + if (isSuccess(response.getCode())) { + GetMemberInfoRequest queryMemberRequest = new GetMemberInfoRequest(); + queryMemberRequest.setUserName(requestDTO.getAccount()); + queryMemberRequest.setMerchantCode(requestDTO.getAgentId()); + queryMemberRequest.buildSignature(requestDTO.getAgentKey()); + String requestId = IdUtils.fastUUID(); + try { + GetMemberInfoResponse queryMemberResponse = dbSportsClient.getMemberInfo(queryMemberRequest, requestId); + if (this.isSuccess(queryMemberResponse.getCode())) { + BigDecimal transAmount = requestDTO.getAmount(); + BigDecimal afterAmount = queryMemberResponse.getData().getBalance(); + BigDecimal beforeAmount = afterAmount.subtract(transAmount); + exchangeMoney.setBalance(transAmount); + exchangeMoney.setCoinBefore(beforeAmount); + exchangeMoney.setCoinAfter(afterAmount); + exchangeMoney.setCurrencyBefore(beforeAmount); + exchangeMoney.setCurrencyAfter(afterAmount); + } + } catch (Exception e) { + log.error("查询会员失败, errorCode:{}, errorMessage:{}", response.getCode(), response.getMsg(), e); + } + 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(); + if (balance.compareTo(BigDecimal.ZERO) <= 0) { + throw new ApiException(ErrorCode.INSUFFICIENT_PLAYER_BALANCE.getCode()); + } + + TransferRequest request = new TransferRequest(); + request.setUserName(requestDTO.getAccount()); + request.setTransferType(2); // 转出 + request.setTransferId(requestDTO.getOrderId()); + request.setMerchantCode(requestDTO.getAgentId()); + request.setAmount(/*requestDTO.getAmount().toString()*/ balance.toString()); + request.buildSignature(requestDTO.getAgentKey()); + + TransferResponse response = dbSportsClient + .transferOut( + request, IdUtils.fastUUID() + ); + + //判断是否转移成功 + if (this.isSuccess(response.getCode())) { + BigDecimal transAmount = balance; + BigDecimal beforeAmount = balance; + BigDecimal afterAmount = BigDecimal.ZERO; + + //更新数据 + exchangeMoney.setBalance(transAmount); + exchangeMoney.setCoinBefore(beforeAmount); + exchangeMoney.setCoinAfter(afterAmount); + exchangeMoney.setCurrencyBefore(beforeAmount); + exchangeMoney.setCurrencyAfter(afterAmount); + 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.setUserName(requestDTO.getAccounts()); + request.setMerchantCode(requestDTO.getAgentId()); + request.buildSignature(requestDTO.getAgentKey()); + String requestId = IdUtils.fastUUID(); + GetMemberInfoResponse response = dbSportsClient.getMemberInfo(request, requestId); + //判断是否获取成功 + if (this.isSuccess(response.getCode())) { + return MemberInfoResponseDTO.builder() + .status(GameMemberStatus.UNKNOWN.getCode()) + .balance(response.getData().getBalance()) + .account(requestDTO.getAccounts()) + .build(); + } + throw new ApiException(ErrorCode.Get_Member_Info_Failure.getCode()); + } + + /** + * 无重定向登录 + * + * @param requestDTO 游戏登录 + * @return {@link String } + */ + @Override + public String loginWithoutRedirect(GamesLogin requestDTO) { + LoginRequest request = new LoginRequest(); + request.setUserName(requestDTO.getAccount()); + request.setMerchantCode(requestDTO.getAgentId()); + if (requestDTO.getPlatform().equalsIgnoreCase("web")) { + request.setTerminal("pc"); + } else { + request.setTerminal("mobile"); + } + request.setLanguage(requestDTO.getLang()); + request.setCurrency(requestDTO.getCurrency()); + + request.buildSignature(requestDTO.getAgentKey()); + + LoginResponse response = dbSportsClient.login( + request, IdUtils.fastUUID() + ); + + if (this.isSuccess(response.getCode())) { + LoginResponse.LoginRespDTO respDTO = response.getData(); + + String loginURL = respDTO.getLoginUrl(); + if (StringUtils.isEmpty(loginURL)) { + throw new ApiException(ErrorCode.Get_Url_Failure.getCode()); + } + + return loginURL; + } + throw new ApiException(ErrorCode.Get_Url_Failure.getCode()); + } + + /** + * 获取游戏列表 + * + * @param gamesBaseRequestDTO 游戏请求dto + * @return {@link String } + */ + @Transactional + @Override + public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) { + + Platform platform = gamesBaseRequestDTO.getVendor(); + Game condition = new Game(); + condition.setPlatformCode(platform.getPlatformCode()); + condition.setPlatformType(PlatformType.SPORTS.getCode()); + List gameList = gameService.selectGameList(condition); + //不存在这个游戏 + if (ObjectUtils.isEmpty(gameList)) { + Game game = new Game(); + game.setId(IdUtil.getSnowflakeNextId()); + game.setSortNo(1); + game.setPlatformCode(platform.getPlatformCode()); + game.setPlatformType(PlatformType.SPORTS.getCode()); + game.setGameCode("1"); + game.setGameSourceType(String.valueOf(1)); + game.setGameName(GamePlatforms.DBSports.getInfo()); + game.setCreateBy(Constants.SYSTEM); + NameInfo nameInfo = new NameInfo(); + nameInfo.setLang("zh-CN"); + nameInfo.setName("DB体育"); + 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.DB_Sports; + } + + /** + * 汇兑转移状态 + * + * @param requestDTO 兑换转账请求dto + * @return {@link Boolean } + */ + @Override + public ExchangeTransferStatusResponseDTO exchangeTransferStatus(ExchangeTransferStatusRequestDTO requestDTO) { + + GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(requestDTO.getGameExchangeMoneyId()); + if (null == gameExchangeMoney) { + throw new ApiException(ErrorCode.Transfer_Not_Exist.getCode()); + } + Integer status = StatusType.IN_PROGRESS.getValue(); + + if (!Objects.equals(gameExchangeMoney.getStatus(), StatusType.SUCCESS.getValue())) { + TransferDetailRequest request = new TransferDetailRequest(); + request.setMerchantCode(requestDTO.getAgentId()); + request.setTransferId(gameExchangeMoney.getOrderId()); + request.buildSignature(requestDTO.getAgentKey()); + TransferDetailResponse response = dbSportsClient.transferDetail( + request, IdUtils.fastUUID() + ); + if (this.isSuccess(response.getCode()) && response.getData().getStatus() == 1) { + status = StatusType.SUCCESS.getValue(); + } else { + status = StatusType.FAILURE.getValue(); + } + } + + return ExchangeTransferStatusResponseDTO.builder() + .statusType(status) + .balance(gameExchangeMoney.getBalance()) + .coinBefore(gameExchangeMoney.getCoinBefore()) + .coinAfter(gameExchangeMoney.getCoinAfter()) + .build(); + } + + + /** + * 按时间获取投注记录 + * + * @param requestDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByTime(BetRecordByTimeDTO requestDTO) { + + this.getRealtimeRecord(requestDTO, 1); + + return Boolean.TRUE; + } + + void getRealtimeRecord(BetRecordByTimeDTO requestDTO, int pageNum) { + + GetBetListRequest request = new GetBetListRequest(); + request.setStartTime(/*String.valueOf(requestDTO.getStartTime())*/ "1744333220000"); + request.setEndTime(/*String.valueOf(requestDTO.getEndTime())*/ "1744335020000"); + request.setMerchantCode(requestDTO.getAgentId()); + request.setPageNum(pageNum); + request.setPageSize(1000); + request.buildSignature(requestDTO.getAgentKey()); + + GetBetListResponse response = dbSportsClient.getBetList( + request, IdUtils.fastUUID() + ); + + if (this.isSuccess(response.getCode())) { + List list = response.getData().getList(); + if (CollectionUtils.isEmpty(list)) { + return; + } + this.batchInsert(list, requestDTO); + getRealtimeRecord(requestDTO, ++pageNum); + } + } + + /** + * 按历史时间获取投注记录 + * + * @param requestDTO 按时间dto投注记录 + * @return {@link Boolean } + */ + @Override + public Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO requestDTO) { + + return Boolean.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) { + throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode()); + } + + /** + * 强制会员从游戏注销 + * + * @param kickMemberRequestDTO 踢会员请求dto + * @return {@link Boolean } + */ + @Override + public Boolean kickMember(KickMemberRequestDTO kickMemberRequestDTO) { + + KickUserRequest request = new KickUserRequest(); + request.setUserName(kickMemberRequestDTO.getAccount()); + request.setMerchantCode(kickMemberRequestDTO.getAgentId()); + request.buildSignature(kickMemberRequestDTO.getAgentKey()); + KickUserResponse kickUserResponse = dbSportsClient.kickUser(request, IdUtils.fastUUID()); + if (this.isSuccess(kickUserResponse.getCode())) { + return Boolean.TRUE; + } + 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 settledOrderList 投注记录 + */ + private void batchInsert(List settledOrderList, BetRecordByTimeDTO betRecordByTimeDTO) { + List gameBettingDetails = new ArrayList<>(); + List wagersIds = new ArrayList<>(); + //数据组装 + List dataList = settledOrderList; + if (CollectionUtils.isEmpty(dataList)) { + return; + } + + //数据转化 + for (GetBetListResponse.OrderItemDTO dataBean : dataList) { + if (dataBean.getOrderStatus() != 1) { // 只关心结算的 + continue; + } + 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.getOrderNo()); + } + if (CollectionUtils.isEmpty(gameBettingDetails)) { + return; + } + //查询重复数据id + List removeWagersIds = gameBettingDetailsService + .selectGameBettingDetailsByWagersId(wagersIds, GamePlatforms.DBSports.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) { + + //转化类 + GetBetListResponse.OrderItemDTO dataBean = (GetBetListResponse.OrderItemDTO) gamesDataBuildDTO.getData(); + Member member = memberService.selectMemberByGameAccount(dataBean.getUserName()); + if (ObjectUtils.isEmpty(member)) { + return null; + } + //List gameList = redisCache.getCacheList(CacheConstants.DB_Sports); + //Game game = gameList.get(0); + BigDecimal originPayoffAmount = BigDecimal.valueOf(dataBean.getSettleAmount()); + BigDecimal betAmount = new BigDecimal(dataBean.getOrderAmount()); + + int compareResult = originPayoffAmount.compareTo(betAmount); + long payoffTime = dataBean.getSettleTime(); + long createTime = dataBean.getCreateTime(); + Platform platform = gamesDataBuildDTO.getPlatform(); + String systemCurrency = platform.getOurCurrency(dataBean.getCurrency()); + //数据构造 + GameBettingDetails gameBettingDetails = GameBettingDetails.builder() + .tenantKey(member.getTenantKey()) + //保存我们的币种id + .currencyCode(systemCurrency) + .memberId(member.getId()) + .gameCode("1") + .gameType(PlatformType.SPORTS.getCode()) // 体育 + .platformCode(GamePlatforms.DBSports.getCode()) + .gameId(GamePlatforms.DBSports.getCode() + "_1") + .gameName(GamePlatforms.DBSports.getInfo()) + .gameStatus(compareResult > 0 ? GameStatus.WIN.getCode() : compareResult < 0 ? GameStatus.FAIL.getCode() : GameStatus.FLAT.getCode()) + .gameStatusType(1) // 一般下注 + .gameCurrencyCode(dataBean.getCurrency()) + .account(dataBean.getUserName()) + .wagersId(dataBean.getOrderNo()) + .wagersTime(createTime) + .betAmount(betAmount) + .payoffTime(payoffTime) + .payoffAmount(originPayoffAmount.abs()) + .settlementTime(payoffTime) + .turnover(betAmount) + .orderNo(dataBean.getOrderNo()) + .settlementStatus(SettlementStatusEnum.COMPLETED.getCode()) + .build(); + gameBettingDetails.setCreateBy(Constants.SYSTEM); + gameBettingDetails.setCreateTime(DateUtils.getNowDate()); + return gameBettingDetails; + } +} diff --git a/pom.xml b/pom.xml index b17b6dc..579bfa9 100644 --- a/pom.xml +++ b/pom.xml @@ -214,14 +214,13 @@ com.ff - ff-service + comp-redis ${ff.version} - com.ff - comp-redis - 0.0.1 + xk-client + ${ff.version} @@ -231,6 +230,10 @@ ff-fetcher ff-bean/ff-domain ff-bean/comp-redis + ff-bean/xk-client + + + ff-platform/xk-dbsports pom diff --git a/sh/linux/build.sh b/sh/linux/build.sh index f3cabf4..2888485 100644 --- a/sh/linux/build.sh +++ b/sh/linux/build.sh @@ -29,10 +29,11 @@ if [ $? -eq 0 ]; then mkdir -p ${basePath}/dumps # 6. 拷贝构建产物 - cp ff-game/target/xk-*.jar ${basePath}/ + cp -v ff-game/target/xk-*.jar ${basePath}/ # 7. 拷贝配置文件 - cp ff-game/src/main/resources/application-prod.yml ${basePath}/config + cp -v ff-game/src/main/resources/config/**/*.properties ${basePath}/config/ + cp -v ff-game/src/main/resources/application-prod.properties ${basePath}/ # 8. 拷贝启动脚本 cp ./start.sh ${basePath}/ diff --git a/sh/win/build.bat b/sh/win/build.bat index f6305a2..ae7501e 100644 --- a/sh/win/build.bat +++ b/sh/win/build.bat @@ -3,6 +3,8 @@ setlocal set targetName=xk-admin set basePath=\opt\server\dist\%targetName% +set resourcePath=ff-game\src\main\resources + :: 1. 切换到项目根目录(当前脚本所在目录的上两级) cd /d %~dp0 @@ -42,7 +44,11 @@ for /f %%f in ('dir /b ff-game\target\xk-*.jar') do ( :: 7. 拷贝配置文件 echo 拷贝配置文件... -copy "ff-game\src\main\resources\application-prod.yml" "%basePath%\config\" +rem Copy all .properties files recursively +for /r "%sourcePath%\config" %%f in (*.properties) do ( + copy "%%f" "%targetPath%\" +) +copy "%sourcePath%\application-prod.properties" "%basePath%\" :: 8. 拷贝启动脚本 echo 拷贝启动脚本...