feat(game): 添加 SA 游戏平台支持

- 新增 SA游戏平台的接口实现类 GamesSAServiceImpl
- 添加 SA 游戏平台相关的错误码和缓存常量
- 实现 SA游戏平台的用户登录、余额转移、投注记录查询等功能
- 新增 SA 游戏类型枚举类 SAGameType
- 添加 XML 响应对象的序列化和反序列化支持
main-sa
shi 2025-03-26 17:45:28 +08:00
parent 9f6d1710b0
commit 8332c4fdcd
13 changed files with 818 additions and 186 deletions

View File

@ -63,6 +63,12 @@ public class CacheConstants
*/
public static final String FC_GAMES= "fc_games:";
/**
* sa
*/
public static final String SA_GAMES= "sa_games:";
/**
* pg

View File

@ -28,6 +28,7 @@ public enum ErrorCode {
INSUFFICIENT_PLAYER_BALANCE(1012, "玩家余额不足"),
KICK_OUT_AILED(1013, "玩家踢出失败"),
ACCOUNT_NOT_ONLINE(1014, "账号不在线"),
FREQUENT_BALANCE_TRANSFER(1015, "当前游戏账号余额转移频繁"),
;
// 获取错误码

View File

@ -8,6 +8,7 @@ public enum GamePlatforms {
XK("XK", "XK"),
PG("PG", "PG"),
FC("FC", "FC"),
SA("SA", "SA"),
;
private final String code;

View File

@ -0,0 +1,64 @@
package com.ff.base.enums;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
/**
* sagame
*
* @author shi
* @date 2025/03/26
*/
@Getter
@AllArgsConstructor
public enum SAGameType {
// 编号与名称映射
M_COLOR_DISC(531, "M 色碟"),
M_DICE_BAO(532, "M 骰宝"),
M_ROULETTE(533, "M 轮盘"),
M_DRAGON_TIGER(534, "M 龙虎"),
M_BODING(535, "M 博丁"),
M_BLACKJACK(536, "M 黑杰克"),
M_ANDABAH(537, "M 安达巴哈"),
M_INDIA_ZHA_ZHENG(538, "M 印度炸金花"),
M_THAI_DICE_BAO(539, "M 泰国骰宝"),
M_FISH_SHRIMP_CRAB(540, "M 鱼虾蟹"),
C_ROULETTE(861, "C 轮盘"),
C_BACCARAT_C01(871, "百家乐 C01"),
C_BACCARAT_C02(872, "百家乐 C02"),
C_BACCARAT_C03(873, "百家乐 C03"),
C_BACCARAT_C04(874, "百家乐 C04"),
C_BACCARAT_C05(875, "百家乐 C05"),
C_BACCARAT_C06(876, "百家乐 C06"),
C_BACCARAT_C07(877, "百家乐 C07"),
C_FAST_BACCARAT_C08(878, "极速百家乐 C08"),
D_BACCARAT_D01(901, "百家乐 D01"),
D_BACCARAT_D02(902, "百家乐 D02"),
D_BACCARAT_D03(903, "百家乐 D03"),
D_BACCARAT_D04(904, "百家乐 D04"),
D_BACCARAT_D05(905, "百家乐 D05"),
D_BACCARAT_D06(906, "百家乐 D06"),
D_BACCARAT_D07(907, "百家乐 D07"),
D_FAST_BACCARAT_D08(908, "极速百家乐 D08"),
D_BLACKJACK(921, "D 黑杰克"),
D_DRAGON_TIGER(922, "D 龙虎"),
D_BODING(923, "D 博丁"),
D_ROULETTE(924, "D 轮盘"),
D_DICE_BAO(925, "D 骰宝"),
D_THAI_DICE_BAO(926, "D 泰国骰宝"),
D_COLOR_DISC(927, "D 色碟");
private final int code;
private final String name;
public static String getNameByCode(int code) {
for (SAGameType gameType : values()) {
if (gameType.getCode() == code) {
return gameType.getName();
}
}
return null;
}
}

View File

@ -291,7 +291,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService {
// 获取平台接口密钥
GameSecretKeyCurrencyDTO gameSecretKey = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder()
.platformCode(gameBalanceExchange.getPlatformCode())
.currency(gameBalanceExchange.getCurrencyCode()).build());
.systemCurrency(gameBalanceExchange.getCurrencyCode()).build());
// 检查平台密钥是否存在,否则抛出异常
ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode());

View File

@ -58,23 +58,44 @@ public interface SAClient {
@Post("/getGameList")
XKGamesDTO getGameList(@JSONBody Map<String, Object> params);
/**
* id
*
*
* @param params
* @return {@link JILIExchangeMoneyResponseDTO }
* @return {@link String }
*/
@Post(url = "/exchangeTransferByAgentId")
XKExchangeMoneyResponseDTO exchangeTransferByAgentId( @JSONBody Map<String, Object> params);
@Post( url ="/api.aspx/CreditBalanceDV",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
String exchangeTransferByInto(@Body String params);
/**
*
*
* @param params
* @return {@link String }
*/
@Post( url ="/api.aspx/DebitAllBalanceDV",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
String exchangeTransferByOut(@Body String params);
/**
*
*
* @param params
* @return {@link XKBetRecordResponseDTO }
* @return {@link String }
*/
@Post(url = "/getGameRecordByTime")
XKBetRecordResponseDTO getBetRecordByTime( @JSONBody Map<String, Object> params);
@Post( url ="/api.aspx/GetAllBetDetailsForTimeIntervalDV",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
String getBetRecordByTime( @Body String params);
/**

View File

@ -0,0 +1,59 @@
package com.ff.game.api.sa.dto;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.math.BigDecimal;
/**
*
*
* @author shi
* @date 2025/03/26
*/
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "CreditBalanceResponse")
public class SACreditBalanceResponse {
/**
* ID
*/
@XmlElement(name = "ErrorMsgId")
private int errorMsgId;
/**
*
*/
@XmlElement(name = "ErrorMsg")
private String errorMsg;
/**
*
*/
@XmlElement(name = "Username")
private String username;
/**
*
*/
@XmlElement(name = "Balance")
private BigDecimal balance;
/**
*
*/
@XmlElement(name = "CreditAmount")
private BigDecimal creditAmount;
/**
*
*/
@XmlElement(name = "OrderId")
private String orderId;
}

View File

@ -0,0 +1,51 @@
package com.ff.game.api.sa.dto;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.math.BigDecimal;
/**
* sadebit
*
* @author shi
* @date 2025/03/26
*/
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "DebitAllBalanceResponse")
public class SADebitAllBalanceResponse {
/**
* ID
*/
@XmlElement(name = "ErrorMsgId")
private int errorMsgId;
/**
*
*/
@XmlElement(name = "ErrorMsg")
private String errorMsg;
/**
*
*/
@XmlElement(name = "Username")
private String username;
/**
*
*/
@XmlElement(name = "DebitAmount")
private BigDecimal debitAmount;
/**
*
*/
@XmlElement(name = "OrderId")
private String orderId;
}

View File

@ -0,0 +1,431 @@
package com.ff.game.api.sa.dto;
import lombok.Data;
import javax.smartcardio.Card;
import javax.xml.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* GetAllBetDetailsResponse
*/
@Data
@XmlRootElement(name = "GetAllBetDetailsForTimeIntervalResponse")
@XmlAccessorType(XmlAccessType.FIELD)
public class SAGetAllBetDetailsResponse {
/**
*
*/
@XmlElement(name = "NumOfRecord")
private int numOfRecord;
/**
*
*/
@XmlElementWrapper(name = "BetDetailList")
@XmlElement(name = "BetDetail")
private List<BetDetail> betDetailList;
/**
* ID
*/
@XmlElement(name = "ErrorMsgId")
private int errorMsgId;
/**
*
*/
@XmlElement(name = "ErrorMsg")
private String errorMsg;
/**
* BetDetail
*/
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public static class BetDetail {
/**
*
*/
@XmlElement(name = "BetTime")
private Date betTime;
/**
*
*/
@XmlElement(name = "PayoutTime")
private Date payoutTime;
/**
*
*/
@XmlElement(name = "Username")
private String username;
/**
* ID
*/
@XmlElement(name = "HostID")
private int hostID;
/**
*
*/
@XmlElement(name = "Detail")
private String detail;
/**
*
*/
@XmlElement(name = "GameID")
private String gameID;
/**
*
*/
@XmlElement(name = "Round")
private int round;
/**
*
*/
@XmlElement(name = "Set")
private int set;
/**
*
*/
@XmlElement(name = "BetID")
private long betID;
/**
*
*/
@XmlElement(name = "Currency")
private String currency;
/**
*
*/
@XmlElement(name = "BetAmount")
private BigDecimal betAmount;
/**
*
*/
@XmlElement(name = "Rolling")
private BigDecimal rolling;
/**
*
*/
@XmlElement(name = "ResultAmount")
private BigDecimal resultAmount;
/**
*
*/
@XmlElement(name = "Balance")
private BigDecimal balance;
/**
*
*/
@XmlElement(name = "GameType")
private String gameType;
/**
*
*/
@XmlElement(name = "BetType")
private int betType;
/**
*
*/
@XmlElement(name = "BetSource")
private int betSource;
/**
*
*/
@XmlElement(name = "TransactionID")
private long transactionID;
/**
* 0 - 1 -
*/
@XmlElement(name = "BetConfirmation")
private int betConfirmation;
/**
*
*/
@XmlElement(name = "GameResult")
private GameResult gameResult;
}
/**
* GameResult
*/
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public static class GameResult {
/**
*
*/
@XmlElement(name = "BaccaratResult")
private BaccaratResult baccaratResult;
}
/**
* BaccaratResult
*/
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public static class BaccaratResult {
/**
* 1
*/
@XmlElement(name = "PlayerCard1")
private Card playerCard1;
/**
* 2
*/
@XmlElement(name = "PlayerCard2")
private Card playerCard2;
/**
* 3
*/
@XmlElement(name = "PlayerCard3")
private Card playerCard3;
/**
* 1
*/
@XmlElement(name = "BankerCard1")
private Card bankerCard1;
/**
* 2
*/
@XmlElement(name = "BankerCard2")
private Card bankerCard2;
/**
*
*/
@XmlElement(name = "ResultDetail")
private ResultDetail resultDetail;
}
/**
* Card
*/
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public static class Card {
/**
* 1 = , 2 = , 3 = , 4 =
*/
@XmlElement(name = "Suit")
private int suit;
/**
* 2 - 10JQKA
*/
@XmlElement(name = "Rank")
private int rank;
}
/**
* ResultDetail
*/
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public static class ResultDetail {
/**
*
*/
@XmlElement(name = "BRTie")
private boolean brTie;
/**
*
*/
@XmlElement(name = "BRPlayerWin")
private boolean brPlayerWin;
/**
*
*/
@XmlElement(name = "BRBankerWin")
private boolean brBankerWin;
/**
*
*/
@XmlElement(name = "BRPlayerPair")
private boolean brPlayerPair;
/**
*
*/
@XmlElement(name = "BRBankerPair")
private boolean brBankerPair;
/**
*
*/
@XmlElement(name = "BRS2CardsLuckySix")
private boolean brS2CardsLuckySix;
/**
*
*/
@XmlElement(name = "BRS3CardsLuckySix")
private boolean brS3CardsLuckySix;
/**
* SS
*/
@XmlElement(name = "BRSSS2CardsLuckySix")
private boolean brSSS2CardsLuckySix;
/**
* SS
*/
@XmlElement(name = "BRSSS3CardsLuckySix")
private boolean brSSS3CardsLuckySix;
/**
* SS
*/
@XmlElement(name = "BRSPlayerBonus")
private boolean brSPlayerBonus;
/**
* SS
*/
@XmlElement(name = "BRSBankerBonus")
private boolean brSBankerBonus;
/**
* SS
*/
@XmlElement(name = "BRSSTie")
private boolean brSSTie;
/**
* SS
*/
@XmlElement(name = "BRSSPlayerWin")
private boolean brSSPlayerWin;
/**
* SS
*/
@XmlElement(name = "BRSSBankerWin")
private boolean brSSBankerWin;
/**
* SS
*/
@XmlElement(name = "BRSSPlayerPair")
private boolean brSSPlayerPair;
/**
* SS
*/
@XmlElement(name = "BRSSBankerPair")
private boolean brSSBankerPair;
/**
*
*/
@XmlElement(name = "BRPlayerNatural")
private boolean brPlayerNatural;
/**
*
*/
@XmlElement(name = "BRBankerNatural")
private boolean brBankerNatural;
/**
* SS
*/
@XmlElement(name = "BRSSPlayerNatural")
private boolean brSSPlayerNatural;
/**
* SS
*/
@XmlElement(name = "BRSSBankerNatural")
private boolean brSSBankerNatural;
/**
*
*/
@XmlElement(name = "BRSAnyPair")
private boolean brSAnyPair;
/**
*
*/
@XmlElement(name = "BRSSSAnyPair")
private boolean brSSSAnyPair;
/**
*
*/
@XmlElement(name = "BRSPerfectPair")
private boolean brSPerfectPair;
/**
*
*/
@XmlElement(name = "BRSSSPerfectPair")
private boolean brSSSPerfectPair;
/**
*
*/
@XmlElement(name = "BRSSSPlayerBonus")
private boolean brSSSPlayerBonus;
/**
*
*/
@XmlElement(name = "BRSSSBankerBonus")
private boolean brSSSBankerBonus;
/**
*
*/
@XmlElement(name = "BRSSSLuckySix")
private boolean brSSSLuckySix;
/**
*
*/
@XmlElement(name = "BRSLuckySix")
private boolean brSLuckySix;
}
}

View File

@ -1,6 +1,8 @@
package com.ff.game.api.sa.dto;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.math.BigDecimal;
@ -12,6 +14,7 @@ import java.math.BigDecimal;
* @date 2025/03/26
*/
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "GetUserStatusResponse")
public class SAGetUserStatusResponse {

View File

@ -2,6 +2,8 @@ package com.ff.game.api.sa.dto;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@ -13,6 +15,7 @@ import javax.xml.bind.annotation.XmlRootElement;
* @date 2025/03/25
*/
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "RegUserInfoResponse")
public class SARegUserInfoResponse {
@XmlElement(name = "ErrorMsgId")

View File

@ -17,9 +17,7 @@ import com.ff.config.KeyConfig;
import com.ff.game.api.IGamesService;
import com.ff.game.api.request.*;
import com.ff.game.api.sa.client.SAClient;
import com.ff.game.api.sa.dto.SALoginRequestResponse;
import com.ff.game.api.sa.dto.SARegUserInfoResponse;
import com.ff.game.api.sa.dto.SAGetUserStatusResponse;
import com.ff.game.api.sa.dto.*;
import com.ff.game.api.xk.dto.*;
import com.ff.game.domain.*;
import com.ff.game.dto.GameSecretKeyCurrencyDTO;
@ -93,6 +91,20 @@ public class GamesSAServiceImpl implements IGamesService {
@Resource
private IGameNameService gameNameService;
/**
* id
*/
private static final Long GAME_ID = 1904452832756002817L;
/**
* ID
*/
private static final Long PLATFORM_ID = 1904411420157108225L;
/**
* id
*/
private static final Long GAME_NAME_ID = 1904452832756002817L;
/**
*
@ -103,6 +115,7 @@ public class GamesSAServiceImpl implements IGamesService {
private Boolean getIsSuccess(Integer errorCode) {
ApiException.isTrue(113 != errorCode, ErrorCode.GAME_ACCOUNT_CREATION_FAILED.getCode());
ApiException.isTrue(116 != errorCode, ErrorCode.ACCOUNT_NOT_EXIST.getCode());
ApiException.isTrue(122 != errorCode, ErrorCode.FREQUENT_BALANCE_TRANSFER.getCode());
return 0 == errorCode;
}
@ -173,8 +186,7 @@ public class GamesSAServiceImpl implements IGamesService {
.balance(saGetUserStatusResponse.getBalance())
.status(saGetUserStatusResponse.isOnline() ? GameMemberStatus.ONLINE.getCode() : GameMemberStatus.OFFLINE.getCode())
.build();
}
else {
} else {
throw new ApiException(ErrorCode.ACCOUNT_NOT_EXIST.getCode());
}
}
@ -187,7 +199,7 @@ public class GamesSAServiceImpl implements IGamesService {
*/
@Override
public String loginWithoutRedirect(GamesLogin gamesLogin) {
log.info("GamesXKServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin);
log.info("GamesSAServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin);
Map<String, Object> params = new LinkedHashMap<>();
params.put("Username", gamesLogin.getAccount());
@ -229,58 +241,30 @@ public class GamesSAServiceImpl implements IGamesService {
@Transactional
@Override
public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) {
List<XKGamesDTO.DataBean> gamesDatas = redisCache.getCacheList(CacheConstants.XK_GAMES);
if (!CollectionUtils.isEmpty(gamesDatas)) {
return CacheConstants.XK_GAMES;
}
Map<String, Object> params = new LinkedHashMap<>();
params.put("agentId", gamesBaseRequestDTO.getAgentId());
String query = JsonUtil.mapToQueryString(params);
gamesBaseRequestDTO.setQuery(query);
String key = this.getKey(gamesBaseRequestDTO, null);
params.put("key", key);
XKGamesDTO xkGamesDTO = SAClient.getGameList(params);
//判断是否获取成功
if (this.getIsSuccess(xkGamesDTO.getCode())) {
for (XKGamesDTO.DataBean gamesDataDTO : xkGamesDTO.getData()) {
GamePlatform gamePlatform = GamePlatform.builder()
.platformType(XKGameType.findSystemByCode(gamesDataDTO.getGameCategoryId()))
.platformCode(GamePlatforms.XK.getCode())
.build();
List<GamePlatform> gamePlatforms = gamePlatformService.selectGamePlatformList(gamePlatform);
GamePlatform gamePlatform = gamePlatformService.selectGamePlatformById(PLATFORM_ID);
//没有此平台就新增一个平台
if (CollectionUtils.isEmpty(gamePlatforms)) {
gamePlatform.setPlatformName(GamePlatforms.XK.getInfo() + XKGameType.findInfoByCode(gamesDataDTO.getGameCategoryId()));
if (ObjectUtils.isEmpty(gamePlatform)) {
gamePlatform = new GamePlatform();
gamePlatform.setPlatformType(PlatformType.CARD_GAME.getCode());
gamePlatform.setPlatformName(GamePlatforms.SA.getInfo() + PlatformType.CARD_GAME.getName());
gamePlatform.setSortNo(gamePlatformService.selectMaxSortNo() + 1);
gamePlatform.setCreateBy(Constants.SYSTEM);
gamePlatformService.insertGamePlatform(gamePlatform);
} else {
gamePlatform = gamePlatforms.get(0);
}
Game game = Game.builder()
.platformId(gamePlatform.getId())
.gameCode(String.valueOf(gamesDataDTO.getGameId()))
.build();
List<Game> games = gameService.selectGameList(game);
Game game = gameService.selectGameById(GAME_ID);
//不存在这个游戏
if (CollectionUtils.isEmpty(games)) {
game.setGameSourceType(gamesDataDTO.getGameCategoryId());
game.setFreespin(gamesDataDTO.isFreeSpin());
if (ObjectUtils.isEmpty(game)) {
game = new Game();
game.setSortNo(gameService.selectMaxSortNoByPlatformId(gamePlatform.getId()) + 1);
game.setGameName(gamesDataDTO.getName());
game.setPlatformId(gamePlatform.getId());
game.setGameCode("1");
game.setGameSourceType(1);
game.setGameName("真人棋牌");
game.setCreateBy(Constants.SYSTEM);
gameService.insertGame(game);
} else {
game = games.get(0);
}
gamesDataDTO.setSystemGameId(game.getId());
List<GameName> gameNames = gameNameService.selectGameNameList(GameName.builder().gameId(game.getId()).gameName(game.getGameName()).build());
if (CollectionUtils.isEmpty(gameNames)) {
GameName gameName = gameNameService.selectGameNameById(GAME_NAME_ID);
if (ObjectUtils.isEmpty(gameName)) {
gameNameService.insertGameName(GameName.builder()
.gameId(game.getId())
.gameName(game.getGameName())
@ -288,18 +272,7 @@ public class GamesSAServiceImpl implements IGamesService {
.createBy(Constants.SYSTEM)
.build());
}
}
redisCache.deleteObject(CacheConstants.XK_GAMES);
redisCache.setCacheList(CacheConstants.XK_GAMES, xkGamesDTO.getData());
redisCache.expire(CacheConstants.XK_GAMES, 5L, TimeUnit.HOURS);
} else {
throw new BaseException(xkGamesDTO.getMsg());
}
return CacheConstants.XK_GAMES;
return CacheConstants.SA_GAMES;
}
/**
@ -311,14 +284,14 @@ public class GamesSAServiceImpl implements IGamesService {
@Override
@Transactional
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) {
log.info("GamesXKServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
log.info("GamesSAServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder()
.platformCode(GamePlatforms.XK.getInfo())
.platformCode(GamePlatforms.SA.getInfo())
.code(exchangeTransferMoneyRequestDTO.getAgentId())
.build());
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount());
String transactionId = GamePlatforms.XK.getCode() + IdUtils.simpleUUID();
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
@ -326,6 +299,12 @@ public class GamesSAServiceImpl implements IGamesService {
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//判断是转入还是转出
String transactionId = "OUT" + DateUtils.dateTimeNow() + exchangeTransferMoneyRequestDTO.getAccount();
if (!TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) {
transactionId = "IN" + DateUtils.dateTimeNow() + exchangeTransferMoneyRequestDTO.getAccount();
}
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
@ -338,39 +317,65 @@ public class GamesSAServiceImpl implements IGamesService {
.currencyCode(currencyDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.XK.getCode())
.platformCode(GamePlatforms.SA.getCode())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
//接口限制限制50字符
exchangeMoney.setTransactionId(GamePlatforms.XK.getCode() + IdUtils.simpleUUID());
if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) {
Map<String, Object> params = new LinkedHashMap<>();
params.put("account", exchangeTransferMoneyRequestDTO.getAccount());
params.put("transactionId", exchangeMoney.getTransactionId());
params.put("amount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toString());
params.put("transferType", exchangeTransferMoneyRequestDTO.getTransferType());
params.put("agentId", exchangeTransferMoneyRequestDTO.getAgentId());
params.put("Username", exchangeTransferMoneyRequestDTO.getAccount());
params.put("OrderId", exchangeMoney.getTransactionId());
String query = JsonUtil.mapToQueryString(params);
exchangeTransferMoneyRequestDTO.setQuery(query);
String key = this.getKey(exchangeTransferMoneyRequestDTO, null);
params.put("key", key);
XKExchangeMoneyResponseDTO exchangeMoneyResponse = SAClient.exchangeTransferByAgentId(params);
String key = this.getKey(exchangeTransferMoneyRequestDTO, "DebitAllBalanceDV");
String result = SAClient.exchangeTransferByOut(key);
SADebitAllBalanceResponse saDebitAllBalanceResponse = XmlUtils.xmlDecrypt(result, SADebitAllBalanceResponse.class);
Integer errorCode = saDebitAllBalanceResponse.getErrorMsgId();
//判断是否转移成功
if (this.getIsSuccess(exchangeMoneyResponse.getCode())) {
XKExchangeMoneyResponseDTO.DataBean exchangeMoneyResponseData = exchangeMoneyResponse.getData();
ApiException.isTrue(!StatusType.FAILURE.getValue().equals(exchangeMoneyResponseData.getStatus()), ErrorCode.BALANCE_TRANSFER_FAILED.getCode());
if (this.getIsSuccess(errorCode)) {
//更新数据
exchangeMoney.setBalance(NumberUtil.sub(exchangeMoneyResponseData.getCurrencyAfter(), exchangeMoneyResponseData.getCurrencyBefore()).abs());
exchangeMoney.setCoinBefore(exchangeMoneyResponseData.getCoinBefore());
exchangeMoney.setCoinAfter(exchangeMoneyResponseData.getCoinAfter());
exchangeMoney.setCurrencyBefore(exchangeMoneyResponseData.getCurrencyBefore());
exchangeMoney.setCurrencyAfter(exchangeMoneyResponseData.getCurrencyAfter());
exchangeMoney.setStatus(exchangeMoneyResponseData.getStatus());
exchangeMoney.setBalance(saDebitAllBalanceResponse.getDebitAmount());
exchangeMoney.setCoinBefore(saDebitAllBalanceResponse.getDebitAmount());
exchangeMoney.setCoinAfter(BigDecimal.ZERO);
exchangeMoney.setCurrencyBefore(exchangeMoney.getCurrencyBefore());
exchangeMoney.setCurrencyAfter(exchangeMoney.getCurrencyAfter());
exchangeMoney.setStatus(StatusType.SUCCESS.getValue());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
} else {
log.error("GamesXKServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{},错误信息{}", exchangeMoneyResponse.getCode(), exchangeMoneyResponse.getMsg());
throw new BaseException(exchangeMoneyResponse.getMsg());
log.error("GamesXKServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{}", errorCode);
throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode());
}
} else {
Map<String, Object> params = new LinkedHashMap<>();
params.put("Username", exchangeTransferMoneyRequestDTO.getAccount());
params.put("OrderId", exchangeMoney.getTransactionId());
params.put("CreditAmount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toPlainString());
params.put("CurrencyType", currencyDTO.getCurrency());
String query = JsonUtil.mapToQueryString(params);
exchangeTransferMoneyRequestDTO.setQuery(query);
String key = this.getKey(exchangeTransferMoneyRequestDTO, "CreditBalanceDV");
String result = SAClient.exchangeTransferByInto(key);
SACreditBalanceResponse saCreditBalanceResponse = XmlUtils.xmlDecrypt(result, SACreditBalanceResponse.class);
Integer errorCode = saCreditBalanceResponse.getErrorMsgId();
//判断是否转移成功
if (this.getIsSuccess(errorCode)) {
//更新数据
exchangeMoney.setBalance(saCreditBalanceResponse.getCreditAmount());
exchangeMoney.setCoinBefore(NumberUtil.sub(saCreditBalanceResponse.getBalance(), saCreditBalanceResponse.getCreditAmount()).abs());
exchangeMoney.setCoinAfter(saCreditBalanceResponse.getBalance());
exchangeMoney.setCurrencyBefore(exchangeMoney.getCoinBefore());
exchangeMoney.setCurrencyAfter(exchangeMoney.getCoinAfter());
exchangeMoney.setStatus(StatusType.SUCCESS.getValue());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
} else {
log.error("GamesXKServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{}", errorCode);
throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode());
}
}
return exchangeMoney.getId();
}
@ -395,52 +400,33 @@ public class GamesSAServiceImpl implements IGamesService {
*/
@Override
public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) {
List<GameBettingDetails> gameBettingDetails = new ArrayList<>();
String startTime = DateUtils.convertTimeZone(betRecordByTimeDTO.getStartTime(), "Asia/Shanghai", DateUtils.YYYY_MM_DD_HH_MM_SS);
String endTime = DateUtils.convertTimeZone(betRecordByTimeDTO.getEndTime(), "Asia/Shanghai", DateUtils.YYYY_MM_DD_HH_MM_SS);
//请求参数
log.info("GamesXKServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO);
log.info("GamesSAServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO);
Map<String, Object> params = new LinkedHashMap<>();
params.put("startTime", betRecordByTimeDTO.getStartTime());
params.put("endTime", betRecordByTimeDTO.getEndTime());
params.put("page", betRecordByTimeDTO.getPage());
params.put("pageLimit", betRecordByTimeDTO.getPageLimit());
params.put("agentId", betRecordByTimeDTO.getAgentId());
params.put("FromTime", startTime);
params.put("ToTime",endTime);
String query = JsonUtil.mapToQueryString(params);
betRecordByTimeDTO.setQuery(query);
String key = this.getKey(betRecordByTimeDTO, null);
params.put("key", key);
XKBetRecordResponseDTO xkBetRecordResponseDTO = SAClient.getBetRecordByTime(params);
String key = this.getKey(betRecordByTimeDTO, "GetAllBetDetailsForTimeIntervalDV");
String result = SAClient.getBetRecordByTime(key);
SAGetAllBetDetailsResponse saGetAllBetDetailsResponse = XmlUtils.xmlDecrypt(result, SAGetAllBetDetailsResponse.class);
Integer errorCode = saGetAllBetDetailsResponse.getErrorMsgId();
//判断是否获取成功
if (this.getIsSuccess(xkBetRecordResponseDTO.getCode())) {
if (this.getIsSuccess(errorCode)) {
//数据组装
XKBetRecordResponseDTO.DataBean dataBean = xkBetRecordResponseDTO.getData();
this.batchInsert(xkBetRecordResponseDTO);
//获取下一页数据
while (!Objects.equals(dataBean.getCurrentPage(), dataBean.getTotalPages()) && dataBean.getTotalPages() > 0) {
betRecordByTimeDTO.setPage(dataBean.getCurrentPage() + 1);
//请求参数
params = new LinkedHashMap<>();
params.put("startTime", betRecordByTimeDTO.getStartTime());
params.put("endTime", betRecordByTimeDTO.getEndTime());
params.put("page", betRecordByTimeDTO.getPage());
params.put("pageLimit", betRecordByTimeDTO.getPageLimit());
params.put("agentId", betRecordByTimeDTO.getAgentId());
query = JsonUtil.mapToQueryString(params);
betRecordByTimeDTO.setQuery(query);
key = this.getKey(betRecordByTimeDTO, null);
params.put("key", key);
xkBetRecordResponseDTO = SAClient.getBetRecordByTime(params);
this.batchInsert(xkBetRecordResponseDTO);
}
this.batchInsert(saGetAllBetDetailsResponse);
return Boolean.TRUE;
} else {
log.error("GamesXKServiceImpl [getBetRecordByTime] 获取投注记录失败,错误代码{},错误信息{}", xkBetRecordResponseDTO.getCode(), xkBetRecordResponseDTO.getMsg());
throw new BaseException(xkBetRecordResponseDTO.getMsg());
log.error("GamesXKServiceImpl [getBetRecordByTime] 获取投注记录失败,错误代码{}", errorCode);
}
return Boolean.FALSE;
}
/**
@ -538,21 +524,21 @@ public class GamesSAServiceImpl implements IGamesService {
/**
*
*
* @param xkBetRecordResponseDTO xkdto
* @param saGetAllBetDetailsResponse sa
*/
private void batchInsert(XKBetRecordResponseDTO xkBetRecordResponseDTO) {
private void batchInsert(SAGetAllBetDetailsResponse saGetAllBetDetailsResponse) {
List<GameBettingDetails> gameBettingDetails = new ArrayList<>();
List<String> wagersIds = new ArrayList<>();
//数据组装
XKBetRecordResponseDTO.DataBean dataBean = xkBetRecordResponseDTO.getData();
List<SAGetAllBetDetailsResponse.BetDetail> result = saGetAllBetDetailsResponse.getBetDetailList();
//数据转化
for (XKBetRecordResponseDTO.DataBean.ResultBean bean : dataBean.getResult()) {
for (SAGetAllBetDetailsResponse.BetDetail bean : result) {
GameBettingDetails bettingDetails = this.dataBuild(GamesDataBuildDTO.builder().data(bean).build());
if (!ObjectUtils.isEmpty(bettingDetails)) {
bettingDetails.setId(IdUtil.getSnowflakeNextId());
gameBettingDetails.add(bettingDetails);
}
wagersIds.add(String.valueOf(bean.getWagersId()));
wagersIds.add(String.valueOf(bean.getBetID()));
}
if (!CollectionUtils.isEmpty(gameBettingDetails)) {
//查询重复数据id
@ -577,50 +563,56 @@ public class GamesSAServiceImpl implements IGamesService {
@Override
public GameBettingDetails dataBuild(GamesDataBuildDTO gamesDataBuildDTO) {
//转化类
XKBetRecordResponseDTO.DataBean.ResultBean resultBean = (XKBetRecordResponseDTO.DataBean.ResultBean) gamesDataBuildDTO.getData();
SAGetAllBetDetailsResponse.BetDetail resultBean = (SAGetAllBetDetailsResponse.BetDetail) gamesDataBuildDTO.getData();
GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder()
.platformCode(GamePlatforms.XK.getInfo())
.code(resultBean.getAgentId())
.platformCode(GamePlatforms.SA.getInfo())
.currency(resultBean.getCurrency())
.build());
Member member = memberService.selectMemberByGameAccount(resultBean.getAccount());
Member member = memberService.selectMemberByGameAccount(resultBean.getUsername());
if (ObjectUtils.isEmpty(member)) {
return null;
}
List<XKGamesDTO.DataBean> gamesDatas = redisCache.getCacheList(CacheConstants.XK_GAMES);
Map<String, XKGamesDTO.DataBean> dataDTOMap = gamesDatas.stream().collect(Collectors.toMap(XKGamesDTO.DataBean::getGameId, e -> e));
XKGamesDTO.DataBean gamesDataDTO = dataDTOMap.get(resultBean.getGameId());
BigDecimal payoffAmount = BigDecimal.ZERO;
if (GameStatus.WIN.getCode().equals(resultBean.getStatus())) {
payoffAmount = NumberUtil.sub(resultBean.getPayoffAmount(), resultBean.getTurnover());
} else if (GameStatus.FAIL.getCode().equals(resultBean.getStatus())) {
payoffAmount = NumberUtil.sub(resultBean.getPayoffAmount(), resultBean.getTurnover()).negate();
Game game = gameService.selectGameById(GAME_ID);
// 判断输赢
Integer gameStatus = GameStatus.FLAT.getCode();
if (BigDecimal.ZERO.compareTo(resultBean.getResultAmount()) > 0) {
gameStatus = GameStatus.FAIL.getCode();
} else if (BigDecimal.ZERO.compareTo(resultBean.getResultAmount()) < 0) {
gameStatus = GameStatus.WIN.getCode();
}
//数据构造
GameBettingDetails gameBettingDetails = GameBettingDetails.builder()
.tenantKey(member.getTenantKey())
//保存我们的币种id
.currencyCode(currencyDTO.getSystemCurrency())
.memberId(member.getId())
.gameCode(resultBean.getGameId())
.gameType(XKGameType.findSystemByCode(resultBean.getGameCategoryId()))
.platformCode(GamePlatforms.XK.getCode())
.gameId(gamesDataDTO.getSystemGameId())
.gameName(gamesDataDTO.getName())
.gameStatus(resultBean.getStatus())
.gameStatusType(resultBean.getType())
.gameCurrencyCode(resultBean.getAgentId())
.account(String.valueOf(resultBean.getAccount()))
.wagersId(String.valueOf(resultBean.getWagersId()))
.wagersTime(resultBean.getWagersTime())
.betAmount(resultBean.getBetAmount().abs())
.payoffTime(resultBean.getPayoffTime())
.payoffAmount(payoffAmount)
.settlementTime(resultBean.getSettlementTime())
.turnover(resultBean.getTurnover())
.orderNo(String.valueOf(resultBean.getRoundIndex()))
.gameCode(resultBean.getGameID())
.gameType(1)
.platformCode(GamePlatforms.SA.getCode())
.gameId(GAME_ID)
.gameName(game.getGameName())
.gameStatus(gameStatus)
.gameStatusType(1)
.gameCurrencyCode(resultBean.getCurrency())
.account(resultBean.getUsername())
.wagersId(String.valueOf(resultBean.getBetID()))
.wagersTime(resultBean.getBetTime().getTime())
.betAmount(resultBean.getBetAmount())
.payoffTime(resultBean.getPayoutTime().getTime())
.payoffAmount(resultBean.getResultAmount().abs())
.settlementTime(resultBean.getPayoutTime().getTime())
.turnover(resultBean.getRolling())
.orderNo(null)
.round(String.valueOf(resultBean.getRound()))
.table(String.valueOf(resultBean.getHostID()))
.seat(String.valueOf(resultBean.getSet()))
.settlementStatus(SettlementStatusEnum.COMPLETED.getCode())
.build();
gameBettingDetails.setCreateBy(Constants.SYSTEM);

View File

@ -347,7 +347,7 @@ public class GamesXKServiceImpl implements IGamesService {
Map<String, Object> params = new LinkedHashMap<>();
params.put("account", exchangeTransferMoneyRequestDTO.getAccount());
params.put("transactionId", exchangeMoney.getTransactionId());
params.put("amount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toString());
params.put("amount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toPlainString());
params.put("transferType", exchangeTransferMoneyRequestDTO.getTransferType());
params.put("agentId", exchangeTransferMoneyRequestDTO.getAgentId());
String query = JsonUtil.mapToQueryString(params);